History of yelp_restaurants
The changes to the source code of this entry in the repository, newest first, each with the differences it made to the entry's files. They are also listed on GitLab.
[entries] New entry: yelp_restaurants f71a261
diff --git a/entries/yelp_restaurants/__init__.py b/entries/yelp_restaurants/__init__.py
new file mode 100644
index 0000000..93a5bd3
--- /dev/null
+++ b/entries/yelp_restaurants/__init__.py
@@ -0,0 +1,97 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2020-2026 Tiago de Paula Peixoto <tiago@skewed.de>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from .. import *
+
+title = "Yelp users and restaurants (AllSet, 2021)"
+description = """A bipartite network of Yelp users and the restaurants they reviewed, compiled by Chien et al. from the Yelp Open Dataset (a subset of Yelp's businesses, reviews and users released by Yelp for academic use) as a benchmark for node classification. All businesses in Yelp's "Restaurants" category were selected, and each user is connected to the restaurants they reviewed (the compilers describe them as restaurants "visited by the same user"). Every user is connected to at least two restaurants. The restaurants are located in 459 cities and 16 states or provinces of North America; the identities of the users and businesses in the original data are not included, and the version of the Yelp Open Dataset that was used is not stated.
+
+The network has the following properties:
+
+- `is_user`: whether the node is a user (otherwise it is a restaurant). Users are numbered in the order of their identifiers in the source data.
+- Restaurant nodes: `name`, the name of the restaurant; `stars`, the average star rating of the restaurant's reviews on Yelp, rounded to half stars (1.0 to 5.0); `latitude` and `longitude`, the location of the restaurant, in degrees (as given in the source; one restaurant has a positive longitude, probably a sign error); `city`, `zipcode` and `state`, integer codes for the city, postal code and state or province of the restaurant (the code tables are not available in the source data, so codes can only be compared for equality).
+- User nodes have empty or zero values for the restaurant properties."""
+tags = ['Online', 'Commerce', 'Unweighted', 'Metadata', 'Spatial']
+url = 'https://github.com/jianhao2016/AllSet'
+citation = [('E. Chien, C. Pan, J. Peng, O. Milenkovic, "You are AllSet: A Multiset Function Framework for Hypergraph Neural Networks." International Conference on Learning Representations (ICLR) (2022)', 'https://openreview.net/forum?id=hpBTIv2uy_E'),
+ ('Yelp, "Yelp Open Dataset."', 'https://www.yelp.com/dataset')]
+icon_hash = None
+upstream_license = ("Yelp Dataset Terms of Use", "https://www.yelp.com/dataset")
+upstream_prefix = 'https://raw.githubusercontent.com/jianhao2016/AllSet/6281a2f1a91f6f26040777bb0b2578fc035dc57a/data/raw_data'
+_d = 'AllSet_all_raw_data.zip:AllSet_all_raw_data/yelp/'
+files = [((_d + 'yelp_restaurant_incidence_H.csv',
+ _d + 'yelp_restaurant_name.csv',
+ _d + 'yelp_restaurant_business_stars.csv',
+ _d + 'yelp_restaurant_latlong.csv',
+ _d + 'yelp_restaurant_locations.csv'),
+ None, None)]
+
+def fetch_upstream(force=False):
+ return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+ force)
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+ global files
+ name = __name__.split(".")[-1]
+ for fnames, alt, fmt in files:
+ if alts is not None and alt not in alts:
+ continue
+ if isinstance(fnames, str):
+ fnames = [fnames]
+ with ExitStack() as stack:
+ fs = [stack.enter_context(open_upstream_file(name, fn, "r")) for fn in fnames]
+
+ # Incidences: header "he,node,val", with 1-based user ("he") and
+ # restaurant ("node") ids written as floats; val is always 1
+ next(fs[0])
+ H = numpy.array(fs[0].read().replace(",", " ").split(),
+ dtype=float).reshape(-1, 3).astype(numpy.int64)
+ groups = H[:, 0] - 1
+ members = H[:, 1] - 1
+
+ # Restaurant attributes, one row per restaurant, in id order
+ rows = list(csv.reader(fs[1]))[1:]
+ names = [r[0] for r in rows]
+ stars = [int(l) for l in list(fs[2])[1:]]
+ latlong = [r for r in csv.reader(fs[3])][1:]
+ locs = [r for r in csv.reader(fs[4])][1:]
+
+ N = len(names)
+ assert N == len(stars) == len(latlong) == len(locs)
+ assert members.max() < N
+ g = bipartite_graph(groups, members, groups.max() + 1, N, "is_user")
+
+ g.vp.name = g.new_vp("string")
+ for v in range(N):
+ g.vp.name[v] = names[v]
+ g.vp.stars = g.new_vp("double")
+ # stars are given as twice the star rating (2 to 10)
+ g.vp.stars.a[:N] = numpy.array(stars) / 2
+ g.vp.latitude = g.new_vp("double")
+ g.vp.longitude = g.new_vp("double")
+ ll = numpy.array(latlong, dtype=float)
+ g.vp.latitude.a[:N] = ll[:, 0]
+ g.vp.longitude.a[:N] = ll[:, 1]
+ loc = numpy.array(locs, dtype=numpy.int64)
+ for i, k in enumerate(["city", "zipcode", "state"]):
+ g.vp[k] = g.new_vp("int")
+ g.vp[k].a[:N] = loc[:, i]
+ yield alt, g