logo Netzschleuder network catalog, repository, and centrifuge

History of tkgl_wikidata

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 by Tiago de Paula Peixoto 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/tkgl_wikidata/__init__.py b/entries/tkgl_wikidata/__init__.py
index 6a68569..ae466ac 100644
--- a/entries/tkgl_wikidata/__init__.py
+++ b/entries/tkgl_wikidata/__init__.py
@@ -41,7 +41,7 @@ url = ['https://tgb.complexdatalab.com/docs/tkg/',
        'https://github.com/shenyangHuang/TGB']
 citation = [('J. Gastinger, S. Huang, M. Galkin, E. Loghmani, A. Parviz, F. Poursafaei, J. Danovitch, E. Rossi, I. Koutis, H. Stuckenschmidt, R. Rabbany, G. Rabusseau, "TGB 2.0: A Benchmark for Learning on Temporal Knowledge Graphs and Heterogeneous Graphs." Advances in Neural Information Processing Systems 37 (Datasets and Benchmarks Track) (2024)', 'https://doi.org/10.48550/arXiv.2406.09639'),
             ('D. Vrandečić, M. Krötzsch, "Wikidata: a free collaborative knowledgebase." Communications of the ACM 57(10), 78-85 (2014)', 'https://doi.org/10.1145/2629489')]
-icon_hash = None
+date_added = '2026-10-27'
 upstream_license = ('CC0 1.0 (Wikidata)', 'https://www.wikidata.org/wiki/Wikidata:Licensing')
 upstream_prefix = 'https://object-arbutus.alliancecan.ca/swift/v1/14c95234f6cd4a21a47deafe20cce2a7/tgb'
 files = [('tkgl-wikidata.zip:tkgl-wikidata_edgelist.csv', 'temporal', None),
[entries] Prefix the properties in the descriptions with (Node), (Edge) or (Graph) by Tiago de Paula Peixoto 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/tkgl_wikidata/__init__.py b/entries/tkgl_wikidata/__init__.py
index c1cfda5..6a68569 100644
--- a/entries/tkgl_wikidata/__init__.py
+++ b/entries/tkgl_wikidata/__init__.py
@@ -33,9 +33,9 @@ The data do not include the labels of the entities and relations, which can be l
 
 The networks have the following properties:
 
-- `wikidata_id`: the Wikidata identifier of the entity, e.g. `Q31`.
-- Edge `relation`: the Wikidata property of the statement, e.g. `P166`.
-- Edge `year` (`temporal` only): the year of the statement."""
+- (Node) `wikidata_id`: the Wikidata identifier of the entity, e.g. `Q31`.
+- (Edge) `relation`: the Wikidata property of the statement, e.g. `P166`.
+- (Edge) `year` (`temporal` only): the year of the statement."""
 tags = ['Informational', 'Relatedness', 'Unweighted', 'Multigraph', 'Timestamps', 'Metadata']
 url = ['https://tgb.complexdatalab.com/docs/tkg/',
        'https://github.com/shenyangHuang/TGB']
[entries] Remove unneeded code from the entries by Tiago de Paula Peixoto 2c69f19
Unneeded "global files" statements, unused imports and variables,
f-strings without placeholders, duplicate keys in foodweb_little_rock
(keeping the order and the values used), and the second definition of
get_lines() in twitter_higgs. Nothing changes in the networks or
descriptions.

Changed: none
diff --git a/entries/tkgl_wikidata/__init__.py b/entries/tkgl_wikidata/__init__.py
index ff1568d..c1cfda5 100644
--- a/entries/tkgl_wikidata/__init__.py
+++ b/entries/tkgl_wikidata/__init__.py
@@ -89,7 +89,6 @@ def read_statements(name, fname):
 @coerce_props()
 @annotate()
 def parse(alts=None):
-    global files
     name = __name__.split(".")[-1]
     for fname, alt, fmt in files:
         if alts is not None and alt not in alts:
[entries] New entry: tkgl_wikidata by Tiago de Paula Peixoto 617e4f1
diff --git a/entries/tkgl_wikidata/__init__.py b/entries/tkgl_wikidata/__init__.py
new file mode 100644
index 0000000..ff1568d
--- /dev/null
+++ b/entries/tkgl_wikidata/__init__.py
@@ -0,0 +1,129 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 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/>.
+
+import pyarrow
+import pyarrow.csv
+import pyarrow.compute
+
+from .. import *
+
+
+title = "Wikidata temporal knowledge graph (tkgl-wikidata, TGB 2.0)"
+description = """A temporal knowledge graph extracted from Wikidata, from the `tkgl-wikidata` dataset of the Temporal Graph Benchmark (TGB 2.0), a superset of `tkgl_smallpedia`: the statements of the Wikidata entities with identifiers below 32 million (i.e. Q1 to Q31999999), and the entities they point to. Each node is an entity of Wikidata, and a directed edge from entity A to entity B is a statement (A, relation, B), with a Wikidata property as relation (e.g. `P39`, "position held", or `P166`, "award received"). Pairs of entities may be connected by several edges.
+
+- `temporal`: the statements with a time (a point in time, or the start of a period), as a year from 0 to 2024 (9,856,203 edges).
+- `static`: the statements of the same entities without a time (71,900,685 edges); the statements that are also temporal ones were removed by TGB.
+
+The data do not include the labels of the entities and relations, which can be looked up in Wikidata. The negative samples of the benchmark (statements that do not exist, used for evaluation) are left out.
+
+The networks have the following properties:
+
+- `wikidata_id`: the Wikidata identifier of the entity, e.g. `Q31`.
+- Edge `relation`: the Wikidata property of the statement, e.g. `P166`.
+- Edge `year` (`temporal` only): the year of the statement."""
+tags = ['Informational', 'Relatedness', 'Unweighted', 'Multigraph', 'Timestamps', 'Metadata']
+url = ['https://tgb.complexdatalab.com/docs/tkg/',
+       'https://github.com/shenyangHuang/TGB']
+citation = [('J. Gastinger, S. Huang, M. Galkin, E. Loghmani, A. Parviz, F. Poursafaei, J. Danovitch, E. Rossi, I. Koutis, H. Stuckenschmidt, R. Rabbany, G. Rabusseau, "TGB 2.0: A Benchmark for Learning on Temporal Knowledge Graphs and Heterogeneous Graphs." Advances in Neural Information Processing Systems 37 (Datasets and Benchmarks Track) (2024)', 'https://doi.org/10.48550/arXiv.2406.09639'),
+            ('D. Vrandečić, M. Krötzsch, "Wikidata: a free collaborative knowledgebase." Communications of the ACM 57(10), 78-85 (2014)', 'https://doi.org/10.1145/2629489')]
+icon_hash = None
+upstream_license = ('CC0 1.0 (Wikidata)', 'https://www.wikidata.org/wiki/Wikidata:Licensing')
+upstream_prefix = 'https://object-arbutus.alliancecan.ca/swift/v1/14c95234f6cd4a21a47deafe20cce2a7/tgb'
+files = [('tkgl-wikidata.zip:tkgl-wikidata_edgelist.csv', 'temporal', None),
+         ('tkgl-wikidata.zip:tkgl-wikidata_static_edgelist.csv', 'static', None)]
+
+def fetch_upstream(force=False):
+    return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+                                force)
+
+# For checks only: if set, only this many lines of each file are read
+_check_rows = None
+
+def read_statements(name, fname):
+    """The statements of the CSV member `fname` ("ts,head,tail,relation_type"
+    or "head,tail,relation_type", with entities "Q<n>" and relations "P<n>"),
+    read in blocks, as arrays of the numbers of the heads, tails and relations,
+    and of the years (or None, if not given)."""
+    cols = {"head": [], "tail": [], "relation_type": [], "ts": []}
+    n = 0
+    with open_upstream_file(name, fname, "rb") as f:
+        reader = pyarrow.csv.open_csv(
+            f, read_options=pyarrow.csv.ReadOptions(block_size=1 << 26),
+            convert_options=pyarrow.csv.ConvertOptions(
+                column_types={"ts": pyarrow.int64(), "head": pyarrow.string(),
+                              "tail": pyarrow.string(),
+                              "relation_type": pyarrow.string()}))
+        for batch in reader:
+            if _check_rows is not None and n >= _check_rows:
+                break
+            n += batch.num_rows
+            for k in cols:
+                if k not in batch.schema.names:
+                    continue
+                c = batch.column(k)
+                if k != "ts":
+                    prefix = "P" if k == "relation_type" else "Q"
+                    assert pyarrow.compute.all(pyarrow.compute.starts_with(c, prefix)).as_py()
+                    c = pyarrow.compute.utf8_slice_codeunits(c, 1)
+                    c = pyarrow.compute.cast(c, pyarrow.int64())
+                cols[k].append(c.to_numpy())
+    return [numpy.concatenate(cols[k]) if cols[k] else None
+            for k in ["head", "tail", "relation_type", "ts"]]
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+    global files
+    name = __name__.split(".")[-1]
+    for fname, alt, fmt in files:
+        if alts is not None and alt not in alts:
+            continue
+        heads, tails, rels, years = read_statements(name, fname)
+        assert (years is not None) == (alt == "temporal")
+        # The entities, numbered in the order of their first appearance (as in
+        # tkgl_smallpedia)
+        ids = numpy.column_stack([heads, tails]).ravel()
+        del heads, tails
+        uids, first, idx = numpy.unique(ids, return_index=True,
+                                        return_inverse=True)
+        del ids
+        order = numpy.argsort(first, kind="stable")
+        del first
+        rank = numpy.empty(len(order), dtype="int64")
+        rank[order] = numpy.arange(len(order))
+        idx = rank[idx]
+        del rank
+        g = Graph(directed=True)
+        g.add_vertex(len(uids))
+        g.add_edge_list(idx.reshape(-1, 2))
+        del idx
+        qid = g.new_vp("int64_t", vals=uids[order])
+        del uids, order
+        g.vp.wikidata_id = g.new_vp("string")
+        map_property_values(qid, g.vp.wikidata_id, lambda x: f"Q{x}")
+        del qid
+        rel = g.new_ep("int", vals=rels)
+        del rels
+        g.ep.relation = g.new_ep("string")
+        map_property_values(rel, g.ep.relation, lambda x: f"P{x}")
+        del rel
+        if years is not None:
+            g.ep.year = g.new_ep("int", vals=years)
+            del years
+        yield alt, g