History of soc_lj_snapshots
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] Add the date when each entry was added, and remove icon_hash beff7c9
The dates are those of the commits that first added the entries' files (2020-08-11 for the entries of the initial commit); renamed entries keep the date of their first name. Changed: none
diff --git a/entries/soc_lj_snapshots/__init__.py b/entries/soc_lj_snapshots/__init__.py
index 94226db..faa3715 100644
--- a/entries/soc_lj_snapshots/__init__.py
+++ b/entries/soc_lj_snapshots/__init__.py
@@ -41,7 +41,7 @@ url = ['https://snap.stanford.edu/data/soc-lj-friends.html',
'https://snap.stanford.edu/data/soc-lj-comm-watchers.html']
citation = [('L. Backstrom, D. Huttenlocher, J. Kleinberg, and X. Lan, "Group Formation in Large Social Networks: Membership, Growth, and Evolution." Proceedings of the 12th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (KDD), 44-54 (2006).', 'https://doi.org/10.1145/1150402.1150412'),
('J. Leskovec, K. J. Lang, A. Dasgupta, and M. W. Mahoney, "Community Structure in Large Networks: Natural Cluster Sizes and the Absence of Large Well-Defined Clusters." Internet Mathematics 6(1), 29-123 (2009).', 'https://doi.org/10.1080/15427951.2009.10129177')]
-icon_hash = None
+date_added = '2026-10-27'
upstream_license = None
upstream_prefix = 'https://snap.stanford.edu/data'
files = [(f'soc-lj-friends-{i:02d}.txt.gz', f'friends_{i:02d}', None) for i in range(1, 13)]
[entries] Prefix the properties in the descriptions with (Node), (Edge) or (Graph) bc3dbbd
The lists of properties at the end of the descriptions marked edge properties with "Edge" but left node properties unmarked, or grouped them in "Nodes: `a`, ...; `b`, ..." items, so the kind of a property was often unclear. Every item now starts with (Node), (Edge) or (Graph), followed by the property names, a colon and the explanation, one item per property or group of properties; qualifications (kinds of nodes, networks) follow the names in parentheses. Properties that were only named got a short explanation, and a few items that named the wrong kind of property were corrected.
diff --git a/entries/soc_lj_snapshots/__init__.py b/entries/soc_lj_snapshots/__init__.py
index 67886f2..94226db 100644
--- a/entries/soc_lj_snapshots/__init__.py
+++ b/entries/soc_lj_snapshots/__init__.py
@@ -34,7 +34,7 @@ These networks are related to the entry `livejournal` (the friendship network of
The networks have the following properties:
-- `user_id`: the anonymized identifier of the user; in the community networks, `community_id`, the identifier of the community (-1 for users, and `user_id` is -1 for communities), and `is_community`, whether the node is a community."""
+- (Node) `user_id`: the anonymized identifier of the user; in the community networks, `community_id`, the identifier of the community (-1 for users, and `user_id` is -1 for communities), and `is_community`, whether the node is a community."""
tags = ['Social', 'Online', 'Unweighted', 'Affiliation']
url = ['https://snap.stanford.edu/data/soc-lj-friends.html',
'https://snap.stanford.edu/data/soc-lj-comm-members.html',
[entries] New entry: soc_lj_snapshots 4d7d27a
diff --git a/entries/soc_lj_snapshots/__init__.py b/entries/soc_lj_snapshots/__init__.py
new file mode 100644
index 0000000..67886f2
--- /dev/null
+++ b/entries/soc_lj_snapshots/__init__.py
@@ -0,0 +1,107 @@
+#! /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 = "LiveJournal friendships and communities over time (2006)"
+description = r"""Snapshots of the friendship network of users of LiveJournal, an online community where members maintain journals and blogs, declare which other members are their friends, and join and watch communities (group blogs), collected by L. Backstrom and collaborators by crawling LiveJournal and distributed by the Stanford Network Analysis Project (SNAP). The data consist of 12 consecutive snapshots of the friendship network, and 8 snapshots (the 5th to the 12th) of the memberships of users in communities and of the users watching communities. The dates of the snapshots are not documented; they are numbered in their order, as given. The user identifiers are anonymized; they appear to be the same in all snapshots and in the community networks (96% of the users of the first friendship snapshot appear in the last one, and 98% of the community members of the 12th snapshot in the friendship network of the same snapshot), although this is not documented.
+
+There are three kinds of networks:
+
+- `friends_<n>` (for $n$ from 01 to 12): directed networks of users, where an edge $i \to j$ means that user $i$ declared user $j$ as a friend.
+- `members_<n>` (for $n$ from 05 to 12): bipartite networks of users and communities, where an edge means that the user is a member of the community.
+- `watchers_<n>` (for $n$ from 05 to 12): bipartite networks of users and communities, where an edge means that the user watches the community.
+
+The file of the 8th friendship snapshot contains a corrupted region of 80,526 lines (lines 39,765,096 to 39,845,621, of which 17,103 are malformed and others contain impossible identifiers); these lines are left out of `friends_08`.
+
+These networks are related to the entry `livejournal` (the friendship network of the crawl of the same study, with 4.8 million users), whose relation to the snapshots is not documented.
+
+The networks have the following properties:
+
+- `user_id`: the anonymized identifier of the user; in the community networks, `community_id`, the identifier of the community (-1 for users, and `user_id` is -1 for communities), and `is_community`, whether the node is a community."""
+tags = ['Social', 'Online', 'Unweighted', 'Affiliation']
+url = ['https://snap.stanford.edu/data/soc-lj-friends.html',
+ 'https://snap.stanford.edu/data/soc-lj-comm-members.html',
+ 'https://snap.stanford.edu/data/soc-lj-comm-watchers.html']
+citation = [('L. Backstrom, D. Huttenlocher, J. Kleinberg, and X. Lan, "Group Formation in Large Social Networks: Membership, Growth, and Evolution." Proceedings of the 12th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (KDD), 44-54 (2006).', 'https://doi.org/10.1145/1150402.1150412'),
+ ('J. Leskovec, K. J. Lang, A. Dasgupta, and M. W. Mahoney, "Community Structure in Large Networks: Natural Cluster Sizes and the Absence of Large Well-Defined Clusters." Internet Mathematics 6(1), 29-123 (2009).', 'https://doi.org/10.1080/15427951.2009.10129177')]
+icon_hash = None
+upstream_license = None
+upstream_prefix = 'https://snap.stanford.edu/data'
+files = [(f'soc-lj-friends-{i:02d}.txt.gz', f'friends_{i:02d}', None) for i in range(1, 13)]
+files += [(f'soc-lj-comm-members-{i:02d}.txt.gz', f'members_{i:02d}', None) for i in range(5, 13)]
+files += [(f'soc-lj-comm-watchers-{i:02d}.txt.gz', f'watchers_{i:02d}', None) for i in range(5, 13)]
+
+def fetch_upstream(force=False):
+ return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+ force)
+
+# A region of the file of the 8th friendship snapshot is corrupted (lines
+# with garbled numbers, many of them malformed): these lines (1-based, counting
+# the header) are left out.
+_corrupted = {"soc-lj-friends-08.txt.gz": (39765096, 39845621)}
+
+def _edges(name, fname):
+ import pandas
+ import array
+ if fname not in _corrupted:
+ with open_upstream_file(name, fname, "r") as f:
+ df = pandas.read_csv(f, sep="\t", header=None, comment="#",
+ names=["u", "v"],
+ dtype={"u": numpy.int64, "v": numpy.int64})
+ return df.to_numpy()
+ first, last = _corrupted[fname]
+ E = array.array("q")
+ with open_upstream_file(name, fname, "r") as f:
+ for i, line in enumerate(f, start=1):
+ if first <= i <= last or line.startswith("#"):
+ continue
+ u, v = line.split("\t")
+ E.append(int(u))
+ E.append(int(v))
+ return numpy.frombuffer(E, dtype="int64").reshape(-1, 2).copy()
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+ name = __name__.split(".")[-1]
+ for fname, alt, fmt in files:
+ if alts is not None and alt not in alts:
+ continue
+ E = _edges(name, fname)
+ if alt.startswith("friends"):
+ g = Graph(directed=True)
+ g.vp.user_id = g.add_edge_list(E, hashed=True)
+ else:
+ users = numpy.unique(E[:, 0])
+ comms = numpy.unique(E[:, 1])
+ E[:, 0] = numpy.searchsorted(users, E[:, 0])
+ E[:, 1] = numpy.searchsorted(comms, E[:, 1]) + len(users)
+ g = Graph(directed=False)
+ g.add_vertex(len(users) + len(comms))
+ g.add_edge_list(E)
+ g.vp.is_community = g.new_vp("bool")
+ g.vp.is_community.a[len(users):] = True
+ g.vp.user_id = g.new_vp("int64_t", val=-1)
+ g.vp.user_id.a[:len(users)] = users
+ g.vp.community_id = g.new_vp("int64_t", val=-1)
+ g.vp.community_id.a[len(users):] = comms
+ del E
+ yield alt, g