logo Netzschleuder network catalog, repository, and centrifuge

History of endow_sites

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/endow_sites/__init__.py b/entries/endow_sites/__init__.py
index 1ae4daa..57f4c01 100644
--- a/entries/endow_sites/__init__.py
+++ b/entries/endow_sites/__init__.py
@@ -70,7 +70,7 @@ citation = [('S. M. Mattison, N. G. MacLaren, R. Liu, A. Z. Reynolds, G. D. Baca
              'https://doi.org/10.1098/rstb.2021.0433'),
             ('D. Redhead, A. Dalla Ragione and C. T. Ross, "Friendship and partner choice in rural Colombia." Evolution and Human Behavior 44(5), 430-441 (2023)',
              'https://doi.org/10.1016/j.evolhumbehav.2022.08.004')]
-icon_hash = None
+date_added = '2026-10-31'
 upstream_license = ('Mosuo: MIT; Colombia (STRAND): BSD-3-Clause; others: none given',
                     'https://endowproject.github.io/publications/')
 
[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/endow_sites/__init__.py b/entries/endow_sites/__init__.py
index e75a55a..1ae4daa 100644
--- a/entries/endow_sites/__init__.py
+++ b/entries/endow_sites/__init__.py
@@ -40,10 +40,19 @@ Several other studies on the publications page were checked: their network data
 
 The networks have the following properties:
 
-- `name`: the identifier of the individual or household in the data.
-- Edge `layer`: the question or relation of the edge (see above).
-- Edge `weight`: the relatedness for `relatedness` edges, and 1 for the others.
-- Other vertex properties, depending on the community, as given in the data: for the Mosuo, `household`, `relationship_to_head`, `birth_year`, `age`, `gender`, `marital_status`, `years_of_education`, `occupation`, `group`, `status`, `wealth`, `ability_to_work`, `location`; for Pemba, `wives` (number of wives of the household in 2018), `wealth` (direct material wealth), `log_wealth`, `status` (a member holds a position) and `khazi` (a member belongs to the labor cooperative); for Matlab, `household_size`, `head_age`, `status`, `salaried`, `land`, `wealth_usd`; for the Shodagor, `household`; for Colombia, `ethnicity`, `sex`, `age`, `bmi`, `pa`."""
+- (Node) `name`: the identifier of the individual or household in the data.
+- (Edge) `layer`: the question or relation of the edge (see above).
+- (Edge) `weight`: the relatedness for `relatedness` edges, and 1 for the others.
+- (Node) Other properties, depending on the community, as given in the data:
+  - (Node) `household`, `relationship_to_head`, `birth_year`, `age`, `gender`, `marital_status`, `years_of_education`, `occupation`, `group`, `status`, `wealth`, `ability_to_work`, `location` (Mosuo): as given in the data.
+  - (Node) `wives` (Pemba): number of wives of the household in 2018.
+  - (Node) `wealth` (Pemba): direct material wealth.
+  - (Node) `log_wealth` (Pemba): as given in the data.
+  - (Node) `status` (Pemba): a member holds a position.
+  - (Node) `khazi` (Pemba): a member belongs to the labor cooperative.
+  - (Node) `household_size`, `head_age`, `status`, `salaried`, `land`, `wealth_usd` (Matlab): as given in the data.
+  - (Node) `household` (Shodagor): as given in the data.
+  - (Node) `ethnicity`, `sex`, `age`, `bmi`, `pa` (Colombia): as given in the data."""
 tags = ['Social', 'Offline', 'Multilayer', 'Multigraph', 'Metadata']
 url = ['https://endowproject.github.io/publications/',
        'https://github.com/smattison/Social-Sciences-Data',
[entries] New entry: endow_sites by Tiago de Paula Peixoto f802908
diff --git a/entries/endow_sites/__init__.py b/entries/endow_sites/__init__.py
new file mode 100644
index 0000000..e75a55a
--- /dev/null
+++ b/entries/endow_sites/__init__.py
@@ -0,0 +1,273 @@
+#! /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 csv
+import re
+
+from .. import *
+
+_MOSUO = "smattison/Social-Sciences-Data/b3b2b7290fc90c7db0991ec63fd1ce9f63359be2/Data"
+_PEMBA = "DanielRedhead/Pemba-wealth/810b28aae1cb0768c51b3c431f9dc91b4601da2a/processed-data"
+_MATLAB = "JoonHwang-psu/MatlabMultinetwork/054263ef3b75eb6550019e1168788c185f00b6b8"
+_SHODAGOR = "kstarkweather8/WomensNetworks_2022/269d08bf750ed538ff9b0e58ad140b82a2dcb424"
+_COLOMBIA = "ctross/STRAND/9bf51b2b108b3a309cbac62b70bb6f01f9ce37de/data"
+
+title = "ENDOW project community networks"
+description = r"""Social networks of rural communities studied in the ENDOW project ("Evolutionary and Dynamic Origins of Wealth"), a cross-cultural project that collected comparable data on kinship, cooperation, social support and wealth in more than 20 communities around the world (funded by the US National Science Foundation, award 1743019). The project's own repositories contain only simulated ("faux") data; the networks here are those that the authors of the studies that use ENDOW data (listed on the project's publications page) released openly, one network per community:
+
+- `mosuo_labai` and `mosuo_yongning`: two communities of Mosuo agriculturalists in Yunnan, China, the patrilineal Labai and the matrilineal Yongning (Mattison et al. 2021). Nodes are individuals, and edges are the nominations of the respondents (one per household) for the questions of the survey (the layers): who they borrow money from and lend it to, borrow farm equipment from and lend it to, who helps with the harvest, home repairs, slaughtering, childcare and the preparation of community meals, who pays school fees, with whom the women and the men of the household spend time after dinner, kin relations (`Relations`), influential people outside the community, government and NGO contacts, and who they ride with. Some questions were answered by the respondent on behalf of other household members (e.g. the men's and women's evening company); the edges are as recorded, from the respondent. Two identifiers are corrected as in the authors' code (`YN9076` to `YN2000`, and `YN2016` to `YN2017`).
+- `pemba_mitini` and `pemba_mitini_sharing`: the village of Mitini, on the island of Pemba, Zanzibar (Redhead et al. 2023). In `pemba_mitini`, the nodes are the households (`pesu...`), and the layers `work_women` and `work_men` (with whom the women and the men commonly work) and `friends_women` and `friends_men` (with whom they spend free time) go from the nominating household to the nominated one. In `pemba_mitini_sharing`, the nodes are the "sharing units" of the food sharing data (`pessu...`; some of them merge two households, e.g. `pessu101108` for households 101 and 108), with the layers `food_help_received` (which households commonly help you with food) and `food_given` (to which households do you often give food), from the nominating unit to the nominated one, and `relatedness`, the mean genetic relatedness between the units (undirected, given as weighted edges in one direction); the household attributes are given for the units that are single households. The two networks are kept apart because their nodes differ.
+- `matlab_bangladesh`: the households of a village in Matlab, Bangladesh (Hwang et al. 2026). Layers: `financial` (cash), `material` and `labor` support, as recorded (the authors note that the direction of the `labor` edges is the reverse of the flow of the help), and `kinship` between households.
+- `shodagor`: Shodagor women (a community of semi-nomadic traders and fishers in Bangladesh) and their partners in childcare and work, as recorded (Starkweather et al. 2022), with `relatedness` (weighted) edges.
+- `colombia`: friendship nominations in rural Colombia (Afrocolombian, Emberá and Mestizo individuals), from the data published with the STRAND package by C. T. Ross (`Colombia_Data`, a sample of 149 individuals of the study of Redhead, Dalla Ragione and Ross 2023), with `relatedness` (weighted) edges.
+
+Several other studies on the publications page were checked: their network data are not openly available (only on request, e.g. the South Indian Tamil data of E. A. Power, the fishing communities of Barnes et al. 2020; or not released), or the studies do not concern networks. Physical distances between households, given as matrices, are not included.
+
+The networks have the following properties:
+
+- `name`: the identifier of the individual or household in the data.
+- Edge `layer`: the question or relation of the edge (see above).
+- Edge `weight`: the relatedness for `relatedness` edges, and 1 for the others.
+- Other vertex properties, depending on the community, as given in the data: for the Mosuo, `household`, `relationship_to_head`, `birth_year`, `age`, `gender`, `marital_status`, `years_of_education`, `occupation`, `group`, `status`, `wealth`, `ability_to_work`, `location`; for Pemba, `wives` (number of wives of the household in 2018), `wealth` (direct material wealth), `log_wealth`, `status` (a member holds a position) and `khazi` (a member belongs to the labor cooperative); for Matlab, `household_size`, `head_age`, `status`, `salaried`, `land`, `wealth_usd`; for the Shodagor, `household`; for Colombia, `ethnicity`, `sex`, `age`, `bmi`, `pa`."""
+tags = ['Social', 'Offline', 'Multilayer', 'Multigraph', 'Metadata']
+url = ['https://endowproject.github.io/publications/',
+       'https://github.com/smattison/Social-Sciences-Data',
+       'https://github.com/DanielRedhead/Pemba-wealth',
+       'https://github.com/JoonHwang-psu/MatlabMultinetwork',
+       'https://github.com/kstarkweather8/WomensNetworks_2022',
+       'https://github.com/ctross/STRAND']
+citation = [('S. M. Mattison, N. G. MacLaren, R. Liu, A. Z. Reynolds, G. D. Baca, P. M. Mattison, M. Zhang, C.-Y. Sum, M. K. Shenk, T. Blumenfield, C. von Rueden and K. Wander, "Gender Differences in Social Networks Based on Prevailing Kinship Norms in the Mosuo of China." Social Sciences 10(7), 253 (2021)',
+             'https://doi.org/10.3390/socsci10070253'),
+            ('D. Redhead, E. Maliti, J. B. Andrews and M. Borgerhoff Mulder, "The interdependence of relational and material wealth inequality in Pemba, Zanzibar." Phil. Trans. R. Soc. B 378, 20220288 (2023)',
+             'https://doi.org/10.1098/rstb.2022.0288'),
+            ('J. Hwang, N. G. MacLaren, D. Nolin, S. Cully, N. Alam and M. K. Shenk, "Reciprocal exchanges across multilayered networks show an emerging patron-client system led by salaried households." Evolutionary Human Sciences 8, e29 (2026)',
+             'https://doi.org/10.1017/ehs.2026.10061'),
+            ('K. E. Starkweather, A. Z. Reynolds, F. Zohora and N. Alam, "Shodagor women traders cooperate across domains of work and childcare to solve an adaptive problem." Phil. Trans. R. Soc. B 378, 20210433 (2022)',
+             'https://doi.org/10.1098/rstb.2021.0433'),
+            ('D. Redhead, A. Dalla Ragione and C. T. Ross, "Friendship and partner choice in rural Colombia." Evolution and Human Behavior 44(5), 430-441 (2023)',
+             'https://doi.org/10.1016/j.evolhumbehav.2022.08.004')]
+icon_hash = None
+upstream_license = ('Mosuo: MIT; Colombia (STRAND): BSD-3-Clause; others: none given',
+                    'https://endowproject.github.io/publications/')
+
+upstream_prefix = 'https://raw.githubusercontent.com'
+files = [((f"{_MOSUO}/LB_Edgelist.csv", f"{_MOSUO}/LB_Indiv.csv"), "mosuo_labai", None),
+         ((f"{_MOSUO}/YN_Edgelist.csv", f"{_MOSUO}/YN_Indiv.csv"), "mosuo_yongning", None),
+         (tuple(f"{_PEMBA}/{f}.csv" for f in
+                ["su_sharing1", "su_sharing2", "su_female_q", "su_male_q",
+                 "su_female_k", "su_male_k", "su_relatedness", "sharing_unit"]),
+          "pemba_mitini", None),
+         (tuple(f"{_PEMBA}/{f}.csv" for f in
+                ["su_sharing1", "su_sharing2", "su_female_q", "su_male_q",
+                 "su_female_k", "su_male_k", "su_relatedness", "sharing_unit"]),
+          "pemba_mitini_sharing", None),
+         (tuple(f"{_MATLAB}/{f}.csv" for f in
+                ["BD_Edgelist_Q1Q2_NHB", "BD_Edgelist_Q3Q4_NHB",
+                 "BD_Edgelist_Q5Q6_NHB", "BD_Edgelist_kinship_NHB",
+                 "BD_SharingUnit_NHB"]), "matlab_bangladesh", None),
+         (tuple(f"{_SHODAGOR}/{f}.csv" for f in
+                ["ChildcareEdges_deidentified", "WorkEdges_deidentified",
+                 "RelatednessEdges_deidentified", "Nodelist_deidentified"]),
+          "shodagor", None),
+         ((f"{_COLOMBIA}/Colombia_Data.RData",), "colombia", 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", encoding="utf-8-sig") as f:
+        return list(csv.reader(f))
+
+def _na(x):
+    return "" if x in ("NA", None) else x
+
+class _Net:
+    "A multilayer network under construction, with named nodes."
+    def __init__(self):
+        self.nodes = {}
+        self.attrs = {}
+        self.edges = []
+    def node(self, x):
+        if x not in self.nodes:
+            self.nodes[x] = len(self.nodes)
+        return self.nodes[x]
+    def edge(self, s, t, layer, w=1.):
+        self.edges.append((self.node(s), self.node(t), layer, w))
+    def graph(self, keys):
+        g = Graph(directed=True)
+        g.add_vertex(len(self.nodes))
+        g.vp.name = g.new_vp("string", vals=list(self.nodes))
+        for k in keys:
+            g.vp[k] = g.new_vp("string")
+        for x, d in self.attrs.items():
+            v = self.nodes.get(x)
+            if v is None:
+                continue
+            for k in keys:
+                g.vp[k][v] = _na(d.get(k, ""))
+        g.ep.layer = g.new_ep("string")
+        g.ep.weight = g.new_ep("double")
+        g.add_edge_list(self.edges, eprops=[g.ep.layer, g.ep.weight])
+        return g
+
+MOSUO_ATTRS = {"SharingUnitID": "household", "RelationshipToHH": "relationship_to_head",
+               "BirthYear": "birth_year", "Age": "age", "Gender": "gender",
+               "MaritalStatus": "marital_status", "YearsOfEdu": "years_of_education",
+               "YearsofEdu": "years_of_education", "Occupation": "occupation",
+               "GroupID": "group", "Status": "status", "WealthMeasure": "wealth",
+               "AbilityToWork": "ability_to_work", "Location": "location"}
+
+def _matrix(rows):
+    "A matrix (header row and row names) as (row ids, column ids, values)."
+    cols = rows[0][1:]
+    return [r[0] for r in rows[1:]], cols, [r[1:] for r in rows[1:]]
+
+def _mosuo(name, fnames, alt):
+    net = _Net()
+    ind = _rows(name, fnames[1])
+    head = ind[0]
+    for r in ind[1:]:
+        d = dict(zip(head, r))
+        net.attrs[d["IndivID"]] = {MOSUO_ATTRS[k]: v for k, v in d.items()
+                                  if k in MOSUO_ATTRS}
+        net.node(d["IndivID"])
+    fix = {"YN9076": "YN2000", "YN2016": "YN2017"} if alt == "mosuo_yongning" else {}
+    for layer, ego, alter in _rows(name, fnames[0])[1:]:
+        net.edge(fix.get(ego, ego), fix.get(alter, alter), layer)
+    return net.graph(sorted(set(MOSUO_ATTRS.values())))
+
+def _pemba(name, fnames, sharing):
+    """The networks of Pemba: the food sharing networks and the relatedness
+    are between "sharing units" ("pessu...", some of which merge several
+    households), the others between households ("pesu...")."""
+    net = _Net()
+    su = _rows(name, fnames[7])
+    head = su[0]
+    keys = {"nwives2018": "wives", "su_direct_wealth": "wealth",
+            "log_wealth": "log_wealth", "status": "status", "khazi": "khazi"}
+    attrs = {}
+    for r in su[1:]:
+        d = dict(zip(head, r))
+        attrs[d["su_id"]] = {keys[k]: v for k, v in d.items() if k in keys}
+    if sharing:
+        layers = [(0, "food_help_received"), (1, "food_given")]
+    else:
+        layers = [(2, "work_women"), (3, "work_men"), (4, "friends_women"),
+                  (5, "friends_men")]
+        for x in attrs:
+            net.node(x)
+    for k, layer in layers:
+        ids, cols, vals = _matrix(_rows(name, fnames[k]))
+        for i in ids:
+            net.node(i)
+        for i, row in zip(ids, vals):
+            for j, x in zip(cols, row):
+                if x not in ("0", "NA", "") and float(x) != 0:
+                    net.edge(i, j, layer)
+    if sharing:
+        ids, cols, vals = _matrix(_rows(name, fnames[6]))
+        for a, (i, row) in enumerate(zip(ids, vals)):
+            for b, (j, x) in enumerate(zip(cols, row)):
+                if b > a and x not in ("NA", "") and float(x) > 0:
+                    net.edge(i, j, "relatedness", float(x))
+        # the sharing units that are single households ("pessuNNN"), with
+        # the attributes of the household ("pesuNNN")
+        for x in net.nodes:
+            m = re.fullmatch(r"pessu(\d{3})", x)
+            if m and f"pesu{m.group(1)}" in attrs:
+                net.attrs[x] = attrs[f"pesu{m.group(1)}"]
+    else:
+        net.attrs = attrs
+    return net.graph(sorted(keys.values()))
+
+def _matlab(name, fnames):
+    net = _Net()
+    su = _rows(name, fnames[4])
+    head = su[0]
+    keys = {"HH_size": "household_size", "head_age": "head_age",
+            "status": "status", "salaried": "salaried", "land": "land",
+            "WEALTH_TOTAL_VAL_USD": "wealth_usd"}
+    for r in su[1:]:
+        d = dict(zip(head, r))
+        net.node(d["name"])
+        net.attrs[d["name"]] = {keys[k]: v for k, v in d.items() if k in keys}
+    for fn, layer in zip(fnames[:4], ["financial", "material", "labor", "kinship"]):
+        for r in _rows(name, fn)[1:]:
+            if len(r) >= 2:
+                net.edge(r[0], r[1], layer)
+    return net.graph(sorted(keys.values()))
+
+def _shodagor(name, fnames):
+    net = _Net()
+    for r in _rows(name, fnames[3])[1:]:
+        net.node(r[0])
+        net.attrs[r[0]] = {"household": r[1]}
+    for fn, layer in zip(fnames[:2], ["childcare", "work"]):
+        for r in _rows(name, fn)[1:]:
+            net.edge(r[0], r[1], layer)
+    for r in _rows(name, fnames[2])[1:]:
+        net.edge(r[0], r[1], "relatedness", float(r[2]))
+    return net.graph(["household"])
+
+def _colombia(name, fnames):
+    with open_upstream_file(name, fnames[0], "rb") as f:
+        d, attrs = read_rdata(f)["Colombia_Data"]
+    parts = dict(zip(attrs["names"], d))
+    def matrix(x):
+        vals, a = x
+        n = a["dim"][0]
+        ids = a["dimnames"][0]
+        # (R matrices are stored by column)
+        return ids, numpy.array(vals, dtype=float).reshape((n, n), order="F")
+    net = _Net()
+    ids, fr = matrix(parts["Friends"])
+    for i in ids:
+        net.node(i)
+    for a, b in zip(*numpy.nonzero(fr)):
+        net.edge(ids[a], ids[b], "friendship", 1.)
+    rids, rel = matrix(parts["Relatedness"])
+    for a, b in zip(*numpy.nonzero(numpy.triu(rel, 1) > 0)):
+        net.edge(rids[a], rids[b], "relatedness", float(rel[a, b]))
+    ind, iattrs = parts["Individual"]
+    rown = iattrs["row.names"]
+    keys = ["ethnicity", "sex", "age", "bmi", "pa"]
+    for k, (col, vals) in enumerate(zip(iattrs["names"], ind)):
+        for x, v in zip(rown, vals):
+            net.attrs.setdefault(x, {})[keys[k]] = "" if v is None else str(v)
+    return net.graph(keys)
+
+@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 alt.startswith("mosuo"):
+            g = _mosuo(name, fnames, alt)
+        elif alt.startswith("pemba_mitini"):
+            g = _pemba(name, fnames, alt == "pemba_mitini_sharing")
+        elif alt == "matlab_bangladesh":
+            g = _matlab(name, fnames)
+        elif alt == "shodagor":
+            g = _shodagor(name, fnames)
+        else:
+            g = _colombia(name, fnames)
+        yield alt, g