logo Netzschleuder network catalog, repository, and centrifuge

History of wiod

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/wiod/__init__.py b/entries/wiod/__init__.py
index 1a03cef..76571bd 100644
--- a/entries/wiod/__init__.py
+++ b/entries/wiod/__init__.py
@@ -45,7 +45,7 @@ citation = [('M. P. Timmer, E. Dietzenbacher, B. Los, R. Stehrer, G. J. de Vries
              'https://doi.org/10.1111/roie.12178'),
             ('WIOD, "World Input-Output Database 2016 Release, 2000-2014." DataverseNL, V2.1 (2025)',
              'https://doi.org/10.34894/PJ2M1C')]
-icon_hash = None
+date_added = '2026-10-27'
 upstream_license = ("CC BY 4.0", "https://creativecommons.org/licenses/by/4.0/")
 # DataverseNL file ids of WIOTS_in_R.zip and WIOTS_PYP_in_EXCEL.zip (version
 # 2.1 of doi:10.34894/PJ2M1C)
[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/wiod/__init__.py b/entries/wiod/__init__.py
index ea60940..1a03cef 100644
--- a/entries/wiod/__init__.py
+++ b/entries/wiod/__init__.py
@@ -27,18 +27,18 @@ The data are the tables in R format (`WIOTS_in_R.zip`) of the release, and the t
 
 The networks have the following properties:
 
-- `year`: graph property, the year of the flows.
-- `name`: the country and the sector code, e.g. `DEU C29`.
-- `country`: the three-letter code of the country (`ROW` for the rest of the world).
-- `sector`: the code of the sector (e.g. `C29`).
-- `sector_name`: the description of the sector (e.g. `Manufacture of motor vehicles, trailers and semi-trailers`).
-- `gross_output`: the output of the industry at basic prices (row `GO` of the table).
-- `value_added`: the value added at basic prices (row `VA`).
-- `intermediate_consumption`: the total intermediate consumption of the industry (row `II_fob`).
-- `taxes_less_subsidies`: the taxes less subsidies on products used by the industry (row `TXSP`).
-- `transport_margins`: the international transport margins (row `IntTTM`).
-- `final_use`: the total final use of the products of the industry, by all countries (the sum of the final use columns).
-- Edge `weight`: the value of the flow, in millions of US dollars (at current prices, or at previous year's prices in the `pyp_<year>` networks; the node properties of values are in the same prices)."""
+- (Node) `year`: graph property, the year of the flows.
+- (Node) `name`: the country and the sector code, e.g. `DEU C29`.
+- (Node) `country`: the three-letter code of the country (`ROW` for the rest of the world).
+- (Node) `sector`: the code of the sector (e.g. `C29`).
+- (Node) `sector_name`: the description of the sector (e.g. `Manufacture of motor vehicles, trailers and semi-trailers`).
+- (Node) `gross_output`: the output of the industry at basic prices (row `GO` of the table).
+- (Node) `value_added`: the value added at basic prices (row `VA`).
+- (Node) `intermediate_consumption`: the total intermediate consumption of the industry (row `II_fob`).
+- (Node) `taxes_less_subsidies`: the taxes less subsidies on products used by the industry (row `TXSP`).
+- (Node) `transport_margins`: the international transport margins (row `IntTTM`).
+- (Node) `final_use`: the total final use of the products of the industry, by all countries (the sum of the final use columns).
+- (Edge) `weight`: the value of the flow, in millions of US dollars (at current prices, or at previous year's prices in the `pyp_<year>` networks; the node properties of values are in the same prices)."""
 tags = ['Economic', 'Trade', 'Production', 'Weighted', 'Metadata']
 url = ['https://doi.org/10.34894/PJ2M1C', 'https://www.rug.nl/ggdc/valuechain/wiod/wiod-2016-release']
 citation = [('M. P. Timmer, E. Dietzenbacher, B. Los, R. Stehrer, G. J. de Vries, "An Illustrated User Guide to the World Input-Output Database: the Case of Global Automotive Production." Review of International Economics 23(3), 575-605 (2015)',
[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/wiod/__init__.py b/entries/wiod/__init__.py
index e7702a4..ea60940 100644
--- a/entries/wiod/__init__.py
+++ b/entries/wiod/__init__.py
@@ -114,7 +114,6 @@ def parse_pyp(f, year):
 @coerce_props(vforce={"name": "string"})
 @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:
[entries] New entry: wiod by Tiago de Paula Peixoto a3d0b41
diff --git a/entries/wiod/__init__.py b/entries/wiod/__init__.py
new file mode 100644
index 0000000..e7702a4
--- /dev/null
+++ b/entries/wiod/__init__.py
@@ -0,0 +1,162 @@
+#! /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 = "World input-output networks of country-sectors (WIOD, 2000-2014)"
+description = r"""Yearly networks of the flows of goods and services between the industries of 43 countries and a model of the rest of the world, from the World Input-Output Tables (WIOT) of the 2016 release of the World Input-Output Database (WIOD), for the years 2000 to 2014, one network per year in current prices (`2000`, ..., `2014`), and one per year in previous year's prices (`pyp_2001`, ..., `pyp_2014`). The tables were compiled from national supply and use tables, national accounts and international trade statistics, harmonized and linked into a single world table. Each node is an industry (one of 56 sectors of the ISIC Rev. 4 classification) of a country (28 EU countries, 15 other major economies, and the rest of the world, `ROW`), and a directed edge $(i, j)$ means that industry $j$ used goods or services produced by industry $i$ as intermediate inputs in that year, weighted by their value, in millions of US dollars at basic prices: at current prices, or, in the `pyp_<year>` networks, at the prices of the previous year (e.g. the flows of 2014 at the prices of 2013). Self-loops are the use of an industry's output by the same industry. Pairs without flows (zeros in the tables) are not connected.
+
+The tables in previous year's prices separate the changes of the flows' volumes from the changes of prices: comparing the table of a year in previous year's prices with the table of the previous year in current prices gives the growth in volume. According to the note on their construction included with the release (written for the 2014 release), they were derived from the tables in current prices with deflators of gross output and value added by industry (from the socio-economic accounts) and of final demand (from national accounts), by a generalized RAS method that scales the rows and columns of each table to the deflated totals, so that each flow has its own implicit deflator. There is no table in previous year's prices for 2000.
+
+The data are the tables in R format (`WIOTS_in_R.zip`) of the release, and the tables in previous year's prices, which are only available as Excel binary spreadsheets (`WIOTS_PYP_in_EXCEL.zip`, read in the same way; a few empty cells in the rows of totals are read as zeros, and the rows of spreadsheet errors below the tables are ignored). The final use of the products of each industry (by households, non-profit institutions, governments, gross fixed capital formation and changes in inventories, of each country) is not included as edges; its total is a node property. The national input-output tables, the supply and use tables and the socio-economic accounts of the release are not included.
+
+The networks have the following properties:
+
+- `year`: graph property, the year of the flows.
+- `name`: the country and the sector code, e.g. `DEU C29`.
+- `country`: the three-letter code of the country (`ROW` for the rest of the world).
+- `sector`: the code of the sector (e.g. `C29`).
+- `sector_name`: the description of the sector (e.g. `Manufacture of motor vehicles, trailers and semi-trailers`).
+- `gross_output`: the output of the industry at basic prices (row `GO` of the table).
+- `value_added`: the value added at basic prices (row `VA`).
+- `intermediate_consumption`: the total intermediate consumption of the industry (row `II_fob`).
+- `taxes_less_subsidies`: the taxes less subsidies on products used by the industry (row `TXSP`).
+- `transport_margins`: the international transport margins (row `IntTTM`).
+- `final_use`: the total final use of the products of the industry, by all countries (the sum of the final use columns).
+- Edge `weight`: the value of the flow, in millions of US dollars (at current prices, or at previous year's prices in the `pyp_<year>` networks; the node properties of values are in the same prices)."""
+tags = ['Economic', 'Trade', 'Production', 'Weighted', 'Metadata']
+url = ['https://doi.org/10.34894/PJ2M1C', 'https://www.rug.nl/ggdc/valuechain/wiod/wiod-2016-release']
+citation = [('M. P. Timmer, E. Dietzenbacher, B. Los, R. Stehrer, G. J. de Vries, "An Illustrated User Guide to the World Input-Output Database: the Case of Global Automotive Production." Review of International Economics 23(3), 575-605 (2015)',
+             'https://doi.org/10.1111/roie.12178'),
+            ('WIOD, "World Input-Output Database 2016 Release, 2000-2014." DataverseNL, V2.1 (2025)',
+             'https://doi.org/10.34894/PJ2M1C')]
+icon_hash = None
+upstream_license = ("CC BY 4.0", "https://creativecommons.org/licenses/by/4.0/")
+# DataverseNL file ids of WIOTS_in_R.zip and WIOTS_PYP_in_EXCEL.zip (version
+# 2.1 of doi:10.34894/PJ2M1C)
+upstream_prefix = 'https://dataverse.nl/api/access/datafile'
+files = [(f'199101:zip:WIOT{y}_October16_ROW.RData', str(y), None) for y in range(2000, 2015)]
+files += [(f'199102:zip:WIOT{y}_PYP_Nov16_ROW.xlsb', f'pyp_{y}', None) for y in range(2001, 2015)]
+
+ROWS = {"GO": "gross_output", "VA": "value_added", "II_fob": "intermediate_consumption",
+        "TXSP": "taxes_less_subsidies", "IntTTM": "transport_margins"}
+
+def fetch_upstream(force=False):
+    return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+                                force)
+
+def parse_pyp(f, year):
+    # The tables in previous year's prices, in the layout of the Excel
+    # version: rows 2-5 are the headers of the columns (code, description,
+    # country and column number), then come the industries (r1-r56 of each
+    # country) and the rows of totals (country TOT), followed by a few rows of
+    # spreadsheet errors (#REF!) without a code, which are skipped
+    import pyxlsb
+    rows = {}
+    with pyxlsb.open_workbook(f) as wb:
+        assert wb.sheets == [str(year)]
+        with wb.get_sheet(wb.sheets[0]) as sh:
+            for i, row in enumerate(sh.rows()):
+                vals = [c.v for c in row]
+                if i in (2, 3, 4, 5):
+                    rows[i] = vals
+                elif i > 5 and vals[0] is not None:
+                    rows[(vals[0], vals[2], vals[3])] = vals
+    ccountry, cnum = rows[4], rows[5]
+    ind = [k for k in rows if isinstance(k, tuple) and k[1] != "TOT" and
+           int(k[2][1:]) <= 56]
+    N = len(ind)
+    icol = [j for j in range(4, len(ccountry)) if ccountry[j] not in (None, "TOT") and
+            int(cnum[j][1:]) <= 56]
+    fucol = [j for j in range(4, len(ccountry)) if ccountry[j] not in (None, "TOT") and
+             int(cnum[j][1:]) > 56]
+    assert N == len(icol)
+    # the columns of the industries are in the same order as the rows
+    assert all(ccountry[j] == k[1] and cnum[j][1:] == k[2][1:]
+               for j, k in zip(icol, ind))
+    def num(x):
+        return x if isinstance(x, float) else 0.
+    W = numpy.array([[num(rows[k][j]) for j in icol] for k in ind])
+    final_use = numpy.array([sum(num(rows[k][j]) for j in fucol) for k in ind])
+    g = Graph(directed=True)
+    g.add_vertex(N)
+    g.gp.year = g.new_gp("int", val=year)
+    g.vp.name = g.new_vp("string", vals=[f"{k[1]} {k[0]}" for k in ind])
+    g.vp.country = g.new_vp("string", vals=[k[1] for k in ind])
+    g.vp.sector = g.new_vp("string", vals=[k[0] for k in ind])
+    g.vp.sector_name = g.new_vp("string", vals=[rows[k][1].strip() for k in ind])
+    for r, p in ROWS.items():
+        k = [k for k in rows if isinstance(k, tuple) and k[0] == r and k[1] == "TOT"]
+        assert len(k) == 1
+        g.vp[p] = g.new_vp("double", vals=[num(rows[k[0]][j]) for j in icol])
+    g.vp.final_use = g.new_vp("double", vals=final_use)
+    s, t = numpy.nonzero(W)
+    g.ep.weight = g.new_ep("double")
+    g.add_edge_list(numpy.column_stack((s, t, W[s, t])), eprops=[g.ep.weight])
+    return g
+
+@cache_network()
+@coerce_props(vforce={"name": "string"})
+@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 alt.startswith("pyp_"):
+            with open_upstream_file(name, fnames, "rb", seekable=True) as f:
+                g = parse_pyp(f, int(alt[4:]))
+            yield alt, g
+            continue
+        with open_upstream_file(name, fnames, "rb") as f:
+            val, attrs = read_rdata(f)["wiot"]
+        cols = dict(zip(attrs["names"], val))
+        del val
+        def col(c):
+            x = cols[c]
+            return x[0] if isinstance(x, tuple) else x
+        codes, descs, countries = (col("IndustryCode"), col("IndustryDescription"),
+                                   col("Country"))
+        rnr = col("RNr")
+        # industries: rows with a country other than TOT and RNr <= 56
+        ind = [i for i in range(len(codes)) if countries[i] != "TOT" and rnr[i] <= 56]
+        N = len(ind)
+        ind_cols = [f"{countries[i]}{int(rnr[i])}" for i in ind]
+        X = numpy.array([col(c) for c in ind_cols]).T       # rows x industries
+        fu_cols = [c for c in attrs["names"][5:]
+                   if c != "TOT" and int(c[3:]) > 56]
+        final_use = numpy.sum([numpy.array(col(c))[ind] for c in fu_cols], axis=0)
+        g = Graph(directed=True)
+        g.add_vertex(N)
+        g.gp.year = g.new_gp("int", val=int(alt))
+        g.vp.name = g.new_vp("string", vals=[f"{countries[i]} {codes[i]}" for i in ind])
+        g.vp.country = g.new_vp("string", vals=[countries[i] for i in ind])
+        g.vp.sector = g.new_vp("string", vals=[codes[i] for i in ind])
+        g.vp.sector_name = g.new_vp("string", vals=[descs[i].strip() for i in ind])
+        for r, p in ROWS.items():
+            i = [k for k in range(len(codes)) if codes[k] == r][0]
+            g.vp[p] = g.new_vp("double", vals=X[i])
+        g.vp.final_use = g.new_vp("double", vals=final_use)
+        W = X[ind]
+        del X, cols
+        s, t = numpy.nonzero(W)
+        g.ep.weight = g.new_ep("double")
+        g.add_edge_list(numpy.column_stack((s, t, W[s, t])), eprops=[g.ep.weight])
+        del W, s, t
+        yield alt, g