logo Netzschleuder network catalog, repository, and centrifuge

History of librec_trust

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: librec_trust by Tiago de Paula Peixoto 791f56d
diff --git a/entries/librec_trust/__init__.py b/entries/librec_trust/__init__.py
new file mode 100644
index 0000000..b94c4e4
--- /dev/null
+++ b/entries/librec_trust/__init__.py
@@ -0,0 +1,133 @@
+#! /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 *
+
+import calendar
+import time
+
+title = "FilmTrust and CiaoDVD trust and rating networks (2011-2013)"
+description = r"""Trust networks and ratings of users of two movie websites, crawled by G. Guo and collaborators for research on trust-aware recommender systems, and distributed with the LibRec library:
+
+- FilmTrust, a movie sharing and rating website, crawled in its entirety in June 2011. Users rate movies, and can declare that they trust other users.
+- CiaoDVD, the DVD category of the British consumer review website Ciao (dvd.ciao.co.uk), crawled in November and December 2013. Users write reviews of movies with a rating, rate the helpfulness of other users' reviews, and declare which other users they trust. Movies without any review were left out by the authors.
+
+User and movie identifiers were anonymized; the identifiers of users are the same in the networks of one website. There are five networks:
+
+- `filmtrust_trust`: a directed network of users, where an edge $i \to j$ means that user $i$ trusts user $j$.
+- `filmtrust_ratings`: a bipartite network of users and the movies they rated, with the rating. Three user-movie pairs appear twice in the data (with the same or a different rating); all rows are kept as edges.
+- `ciaodvd_trust`: a directed network of users, where an edge $i \to j$ means that user $i$ trusts user $j$.
+- `ciaodvd_ratings`: a bipartite network of users and the movies they reviewed, with the rating and the date of the review. A user may have reviewed a movie more than once (320 user-movie pairs appear more than once); each review is an edge.
+- `ciaodvd_review_ratings`: a directed multigraph of users, where an edge $i \to j$ means that user $i$ rated the helpfulness of a review written by user $j$ (the author of the review is given by `ciaodvd_ratings`). Each rating is an edge. Users who did not write reviews or rate them appear only in the trust network.
+
+The trust values given in the data are all 1, and are therefore left out.
+
+The networks have the following properties:
+
+- `user_id` (users), `movie_id` (movies): the anonymized identifiers in the data; `is_movie` (bipartite networks), whether the node is a movie (otherwise a user).
+- `ciaodvd_ratings`, vertex `genre`: the numeric identifier of the movie's genre (one of 17; their names are not given, -1 for users).
+- `filmtrust_ratings`, edge `rating`: the rating of the movie (from 0.5 to 4, in steps of 0.5).
+- `ciaodvd_ratings`, edges: `rating`, the rating of the movie (1 to 5); `review_id`, the identifier of the review; `time`, the date of the review, as the Unix time of 00:00 UTC of that day.
+- `ciaodvd_review_ratings`, edges: `review_id`, the identifier of the rated review; `helpfulness`, the rating of the review: 0 (off topic), 1 (not helpful), 2 (somewhat helpful), 3 (helpful), 4 (very helpful) or 5 (exceptional)."""
+tags = ['Social', 'Online', 'Preferences', 'Weighted', 'Multigraph', 'Timestamps', 'Metadata']
+url = ['https://guoguibing.github.io/librec/datasets.html']
+citation = [('G. Guo, J. Zhang, and N. Yorke-Smith, "A Novel Bayesian Similarity Measure for Recommender Systems." Proceedings of the 23rd International Joint Conference on Artificial Intelligence (IJCAI), 2619-2625 (2013).', 'https://www.ijcai.org/Proceedings/13/Papers/386.pdf'),
+            ('G. Guo, J. Zhang, D. Thalmann, and N. Yorke-Smith, "ETAF: An Extended Trust Antecedents Framework for Trust Prediction." Proceedings of the 2014 IEEE/ACM International Conference on Advances in Social Networks Analysis and Mining (ASONAM), 540-547 (2014).', 'https://doi.org/10.1109/ASONAM.2014.6921639')]
+icon_hash = None
+upstream_license = None
+upstream_prefix = 'https://raw.githubusercontent.com/guoguibing/guoguibing.github.io/ef318698918b3bcb5b299074ce6e18eef564ceff/librec/datasets'
+files = [('filmtrust.zip:trust.txt', 'filmtrust_trust', None),
+         ('filmtrust.zip:ratings.txt', 'filmtrust_ratings', None),
+         ('CiaoDVD.zip:trusts.txt', 'ciaodvd_trust', None),
+         ('CiaoDVD.zip:movie-ratings.txt', 'ciaodvd_ratings', None),
+         (('CiaoDVD.zip:review-ratings.txt', 'CiaoDVD.zip:movie-ratings.txt'),
+          'ciaodvd_review_ratings', None)]
+
+def fetch_upstream(force=False):
+    return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+                                force)
+
+def _rows(name, fname):
+    with open_upstream_file(name, fname, "r") as f:
+        for line in f:
+            line = line.strip()
+            if line:
+                yield line.replace(",", " ").split()
+
+def _date(x):
+    return calendar.timegm(time.strptime(x, "%Y-%m-%d"))
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+    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]
+        rows = list(_rows(name, fnames[0]))
+        if alt.endswith("_trust"):
+            assert all(r[2] == "1" for r in rows)
+            g = Graph(directed=True)
+            g.vp.user_id = g.add_edge_list([(int(r[0]), int(r[1])) for r in rows],
+                                           hashed=True, hash_type="int")
+        elif alt == "ciaodvd_review_ratings":
+            author = {r[3]: int(r[0]) for r in _rows(name, fnames[1])}
+            g = Graph(directed=True)
+            g.ep.review_id = g.new_ep("int64_t")
+            g.ep.helpfulness = g.new_ep("int32_t")
+            g.vp.user_id = g.add_edge_list([(int(r[0]), author[r[1]], int(r[1]),
+                                             int(r[2])) for r in rows],
+                                           hashed=True, hash_type="int",
+                                           eprops=[g.ep.review_id,
+                                                   g.ep.helpfulness])
+        else:
+            users = sorted(set(int(r[0]) for r in rows))
+            movies = sorted(set(int(r[1]) for r in rows))
+            uidx = {u: i for i, u in enumerate(users)}
+            midx = {m: len(users) + i for i, m in enumerate(movies)}
+            g = Graph(directed=False)
+            g.add_vertex(len(users) + len(movies))
+            g.vp.is_movie = g.new_vp("bool")
+            g.vp.is_movie.a[len(users):] = True
+            g.vp.user_id = g.new_vp("int64_t")
+            g.vp.movie_id = g.new_vp("int64_t")
+            g.vp.user_id.a[:len(users)] = users
+            g.vp.user_id.a[len(users):] = -1
+            g.vp.movie_id.a[:len(users)] = -1
+            g.vp.movie_id.a[len(users):] = movies
+            g.ep.rating = g.new_ep("double")
+            if alt == "filmtrust_ratings":
+                g.add_edge_list([(uidx[int(r[0])], midx[int(r[1])], float(r[2]))
+                                 for r in rows], eprops=[g.ep.rating])
+            else:
+                g.vp.genre = g.new_vp("int32_t", val=-1)
+                for r in rows:
+                    gen = int(r[2])
+                    v = midx[int(r[1])]
+                    assert g.vp.genre[v] in (-1, gen)
+                    g.vp.genre[v] = gen
+                g.ep.review_id = g.new_ep("int64_t")
+                g.ep.time = g.new_ep("int64_t")
+                g.add_edge_list([(uidx[int(r[0])], midx[int(r[1])], float(r[4]),
+                                  int(r[3]), _date(r[5])) for r in rows],
+                                eprops=[g.ep.rating, g.ep.review_id, g.ep.time])
+        yield alt, g