History of github_developers
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: github_developers 39fbafd
diff --git a/entries/github_developers/__init__.py b/entries/github_developers/__init__.py
new file mode 100644
index 0000000..54d672d
--- /dev/null
+++ b/entries/github_developers/__init__.py
@@ -0,0 +1,78 @@
+#! /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 csv
+import json
+
+title = "GitHub developer mutual followers (2019)"
+description = r"""A social network of developers on the software hosting platform GitHub, collected from its public API in June 2019 by B. Rozemberczki and collaborators (MUSAE study) for benchmarks of node embedding and classification methods. Nodes are developers who have starred at least 10 repositories, and an undirected edge connects two developers who follow each other (a mutual follower relationship). Each developer is labeled as a web or a machine learning developer, a label which the authors derived from the job title, and has a list of binary features extracted from the location, the starred repositories, the employer and the email address (only the indices of the features are given, not their meaning; 16 lists contain repeated indices, kept as given).
+
+This network is unrelated to the `github` entry (users and the repositories they watched, from the GitHub contest of 2009).
+
+The network has the following properties:
+
+- `name`: the GitHub user name.
+- `is_ml`: whether the developer is a machine learning developer (otherwise a web developer).
+- `features`: the indices of the developer's binary features."""
+tags = ['Social', 'Online', 'Unweighted', 'Metadata']
+url = ['https://snap.stanford.edu/data/github-social.html',
+ 'https://github.com/benedekrozemberczki/datasets']
+citation = [('B. Rozemberczki, C. Allen, and R. Sarkar, "Multi-scale attributed node embedding." Journal of Complex Networks 9(2), cnab014 (2021).', 'https://doi.org/10.1093/comnet/cnab014')]
+icon_hash = None
+upstream_license = ('MIT License', 'https://github.com/benedekrozemberczki/datasets/blob/3b19135105432cbca65765c1113b91c395ed9d44/LICENSE')
+upstream_prefix = 'https://snap.stanford.edu/data'
+files = [(('git_web_ml.zip:git_web_ml/musae_git_edges.csv',
+ 'git_web_ml.zip:git_web_ml/musae_git_target.csv',
+ 'git_web_ml.zip:git_web_ml/musae_git_features.json'), 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):
+ name = __name__.split(".")[-1]
+ for fnames, alt, fmt in files:
+ if alts is not None and alt not in alts:
+ continue
+ with open_upstream_file(name, fnames[0], "rb") as f:
+ E = numpy.loadtxt(f, delimiter=",", skiprows=1, dtype="int64")
+ with open_upstream_file(name, fnames[1], "r") as f:
+ rows = list(csv.DictReader(f))
+ g = Graph(directed=False)
+ g.add_vertex(len(rows))
+ assert E.max() < len(rows)
+ g.add_edge_list(E)
+ g.vp.name = g.new_vp("string")
+ g.vp.is_ml = g.new_vp("bool")
+ for r in rows:
+ v = int(r["id"])
+ g.vp.name[v] = r["name"]
+ g.vp.is_ml[v] = int(r["ml_target"]) == 1
+ with open_upstream_file(name, fnames[2], "r") as f:
+ feats = json.load(f)
+ assert len(feats) == g.num_vertices()
+ g.vp.features = g.new_vp("vector<int32_t>")
+ for v, x in feats.items():
+ g.vp.features[int(v)] = x
+ yield alt, g