History of cricsheet
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/cricsheet/__init__.py b/entries/cricsheet/__init__.py
index bfb31fa..5fee184 100644
--- a/entries/cricsheet/__init__.py
+++ b/entries/cricsheet/__init__.py
@@ -64,7 +64,7 @@ url = ['https://cricsheet.org/', 'https://cricsheet.org/downloads/',
'https://cricsheet.org/register/']
citation = [('S. Rushe, "Cricsheet: Freely-available structured data for cricket." (2026)',
'https://cricsheet.org/')]
-icon_hash = None
+date_added = '2026-10-31'
upstream_license = ('Open Data Commons Attribution License (ODC-BY 1.0)',
'https://cricsheet.org/licensing/')
[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/cricsheet/__init__.py b/entries/cricsheet/__init__.py
index 62b2779..bfb31fa 100644
--- a/entries/cricsheet/__init__.py
+++ b/entries/cricsheet/__init__.py
@@ -34,21 +34,31 @@ The players and officials are identified by the identifiers of the Cricsheet reg
The networks have the following properties:
-- `name`: the name of the player in the register (or, for teams, the name of the team; for matches, the names of the teams, "A vs B").
-- `unique_name` (players): the unique name of the player in the register.
-- `identifier` (players): the identifier of the player in the register (e.g. `ba607b88`).
-- `key_cricinfo` (players): the identifier of the player in ESPNcricinfo, or empty.
-- `gender`: the gender of the matches of the player (or team, or match): `male` or `female`.
-- `is_player` (`player_matches`): whether the node is a player (otherwise a match).
-- `team_type` (teams): `international` or `club`.
-- Match properties (edges of `deliveries` and `matches`, and match nodes of `player_matches`): `match_id` (the Cricsheet identifier of the match, as in `https://cricsheet.org/matches/` and the file names), `time` (the date of the first day of the match, in Unix time), `date` (YYYY-MM-DD), `match_type` (`Test`, `ODI`, `T20`, `IT20`, `ODM`, `MDM`), `team_type`, `event` (the name of the competition or tour, or empty), `season`, `venue`, `city`, `winner` (the winning team, or empty), `result` (`win`, or `draw`, `tie`, `no result`), and, for `matches`, `toss_winner`.
-- Edge `innings` (`deliveries`): the number of the innings in the match (from 1).
-- Edge `deliveries` (`deliveries`): the number of deliveries bowled by the bowler to the batter in the innings (including wides and no-balls).
-- Edge `runs` (`deliveries`): the runs scored by the batter off these deliveries.
-- Edge `extras` (`deliveries`): the extras of these deliveries (wides, no-balls, byes, leg byes, penalties).
-- Edge `dismissals` (`deliveries`): 1 if the batter was dismissed by the bowler (bowled, caught, caught and bowled, lbw, stumped, hit wicket) in the innings, otherwise 0.
-- Edge `dismissal` (`deliveries`): the kind of the batter's dismissal on a delivery of this bowler (also run outs and others not credited to the bowler), or empty.
-- Edge `team` (`player_matches`): the team of the player in the match."""
+- (Node) `name`: the name of the player in the register (or, for teams, the name of the team; for matches, the names of the teams, "A vs B").
+- (Node) `unique_name` (players): the unique name of the player in the register.
+- (Node) `identifier` (players): the identifier of the player in the register (e.g. `ba607b88`).
+- (Node) `key_cricinfo` (players): the identifier of the player in ESPNcricinfo, or empty.
+- (Node) `gender`: the gender of the matches of the player (or team, or match): `male` or `female`.
+- (Node) `is_player` (`player_matches`): whether the node is a player (otherwise a match).
+- (Node) `team_type` (teams): `international` or `club`.
+- (Edge) `match_id` (`deliveries`, `matches`): the Cricsheet identifier of the match, as in `https://cricsheet.org/matches/` and the file names.
+- (Edge) `time` (`deliveries`, `matches`): the date of the first day of the match, in Unix time.
+- (Edge) `date` (`deliveries`, `matches`): the date of the match (YYYY-MM-DD).
+- (Edge) `match_type` (`deliveries`, `matches`): `Test`, `ODI`, `T20`, `IT20`, `ODM`, `MDM`.
+- (Edge) `team_type` (`deliveries`, `matches`): `international` or `club`.
+- (Edge) `event` (`deliveries`, `matches`): the name of the competition or tour, or empty.
+- (Edge) `season`, `venue`, `city` (`deliveries`, `matches`): the season, venue and city of the match.
+- (Edge) `winner` (`deliveries`, `matches`): the winning team, or empty.
+- (Edge) `result` (`deliveries`, `matches`): `win`, or `draw`, `tie`, `no result`.
+- (Edge) `toss_winner` (`matches`): the winner of the toss.
+- (Node) `match_id`, `time`, `date`, `match_type`, `team_type`, `event`, `season`, `venue`, `city`, `winner`, `result` (matches, `player_matches`): the match properties, as for the edges of `deliveries` and `matches`.
+- (Edge) `innings` (`deliveries`): the number of the innings in the match (from 1).
+- (Edge) `deliveries` (`deliveries`): the number of deliveries bowled by the bowler to the batter in the innings (including wides and no-balls).
+- (Edge) `runs` (`deliveries`): the runs scored by the batter off these deliveries.
+- (Edge) `extras` (`deliveries`): the extras of these deliveries (wides, no-balls, byes, leg byes, penalties).
+- (Edge) `dismissals` (`deliveries`): 1 if the batter was dismissed by the bowler (bowled, caught, caught and bowled, lbw, stumped, hit wicket) in the innings, otherwise 0.
+- (Edge) `dismissal` (`deliveries`): the kind of the batter's dismissal on a delivery of this bowler (also run outs and others not credited to the bowler), or empty.
+- (Edge) `team` (`player_matches`): the team of the player in the match."""
tags = ['Social', 'Offline', 'Sports', 'Multigraph', 'Bipartite', 'Timestamps', 'Temporal', 'Metadata']
url = ['https://cricsheet.org/', 'https://cricsheet.org/downloads/',
'https://cricsheet.org/register/']
[entries] New entry: cricsheet eb95db9
diff --git a/entries/cricsheet/__init__.py b/entries/cricsheet/__init__.py
new file mode 100644
index 0000000..62b2779
--- /dev/null
+++ b/entries/cricsheet/__init__.py
@@ -0,0 +1,250 @@
+#! /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 calendar
+import csv
+import json
+import zipfile
+
+from .. import *
+
+title = "Cricsheet cricket matches (2001-2026)"
+description = r"""Networks of cricket matches from Cricsheet, the open collection of ball-by-ball data of cricket matches compiled by S. Rushe: international matches (Tests, one-day internationals, T20 internationals and other international matches) and the main domestic and franchise T20 leagues and competitions (e.g. the Indian Premier League, the Big Bash League, the County Championship), of men and women, from 2001 to October 2026. Following its policy, Cricsheet withholds the matches of the Afghanistan men's team and of the Afghanistan Premier League, which are therefore not included. The archives of Cricsheet are updated in place as matches are added; the data are those of the download of 31 October 2026 (with the matches added up to 25 October 2026).
+
+The players and officials are identified by the identifiers of the Cricsheet register (`people.csv`), which also give their names and their identifiers in other databases. There are three networks:
+
+- `deliveries`: the bowler-batter network. A directed edge from player $i$ to player $j$ means that $i$ bowled to $j$ in an innings of a match, with the numbers of deliveries, runs and dismissals; there is one edge per pair of players, match and innings (a multigraph). Super overs are included as innings of their own.
+- `matches`: the team network. Nodes are teams (men's and women's teams of the same name are different nodes), and an edge connects the two teams of a match, with the match's metadata (one edge per match, a multigraph).
+- `player_matches`: the bipartite network of players and matches: an edge connects each player of a match's teams (as listed in the match data, usually the playing eleven) to the match. The property `is_player` tells the two kinds of nodes apart.
+
+The networks have the following properties:
+
+- `name`: the name of the player in the register (or, for teams, the name of the team; for matches, the names of the teams, "A vs B").
+- `unique_name` (players): the unique name of the player in the register.
+- `identifier` (players): the identifier of the player in the register (e.g. `ba607b88`).
+- `key_cricinfo` (players): the identifier of the player in ESPNcricinfo, or empty.
+- `gender`: the gender of the matches of the player (or team, or match): `male` or `female`.
+- `is_player` (`player_matches`): whether the node is a player (otherwise a match).
+- `team_type` (teams): `international` or `club`.
+- Match properties (edges of `deliveries` and `matches`, and match nodes of `player_matches`): `match_id` (the Cricsheet identifier of the match, as in `https://cricsheet.org/matches/` and the file names), `time` (the date of the first day of the match, in Unix time), `date` (YYYY-MM-DD), `match_type` (`Test`, `ODI`, `T20`, `IT20`, `ODM`, `MDM`), `team_type`, `event` (the name of the competition or tour, or empty), `season`, `venue`, `city`, `winner` (the winning team, or empty), `result` (`win`, or `draw`, `tie`, `no result`), and, for `matches`, `toss_winner`.
+- Edge `innings` (`deliveries`): the number of the innings in the match (from 1).
+- Edge `deliveries` (`deliveries`): the number of deliveries bowled by the bowler to the batter in the innings (including wides and no-balls).
+- Edge `runs` (`deliveries`): the runs scored by the batter off these deliveries.
+- Edge `extras` (`deliveries`): the extras of these deliveries (wides, no-balls, byes, leg byes, penalties).
+- Edge `dismissals` (`deliveries`): 1 if the batter was dismissed by the bowler (bowled, caught, caught and bowled, lbw, stumped, hit wicket) in the innings, otherwise 0.
+- Edge `dismissal` (`deliveries`): the kind of the batter's dismissal on a delivery of this bowler (also run outs and others not credited to the bowler), or empty.
+- Edge `team` (`player_matches`): the team of the player in the match."""
+tags = ['Social', 'Offline', 'Sports', 'Multigraph', 'Bipartite', 'Timestamps', 'Temporal', 'Metadata']
+url = ['https://cricsheet.org/', 'https://cricsheet.org/downloads/',
+ 'https://cricsheet.org/register/']
+citation = [('S. Rushe, "Cricsheet: Freely-available structured data for cricket." (2026)',
+ 'https://cricsheet.org/')]
+icon_hash = None
+upstream_license = ('Open Data Commons Attribution License (ODC-BY 1.0)',
+ 'https://cricsheet.org/licensing/')
+
+# (replaced in place as matches are added; downloaded on 2026-10-31)
+upstream_prefix = 'https://cricsheet.org'
+files = [(('downloads/all_json.zip', 'register/people.csv'), 'deliveries', None),
+ (('downloads/all_json.zip', 'register/people.csv'), 'matches', None),
+ (('downloads/all_json.zip', 'register/people.csv'), 'player_matches', None)]
+
+def fetch_upstream(force=False):
+ return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+ force)
+
+BOWLER_KINDS = {"bowled", "caught", "caught and bowled", "lbw", "stumped",
+ "hit wicket"}
+
+# For checks only: if set, only this many matches are read
+_check_rows = None
+
+def _matches(name):
+ "The matches of the archive, as (match id, data), in the order of the ids."
+ with open_upstream_file(name, "downloads/all_json.zip", "rb") as f:
+ with zipfile.ZipFile(f) as z:
+ names = sorted((n for n in z.namelist() if n.endswith(".json")),
+ key=lambda n: (len(n), n))
+ for n in names[:_check_rows]:
+ with z.open(n) as mf:
+ yield n.removesuffix(".json"), json.load(mf)
+
+def _match_info(mid, d):
+ i = d["info"]
+ date = i["dates"][0]
+ y, m, dd = map(int, date.split("-"))
+ out = i.get("outcome", {})
+ res = "win" if "winner" in out else out.get("result", "")
+ return {"match_id": mid, "time": calendar.timegm((y, m, dd, 0, 0, 0)),
+ "date": date, "match_type": i.get("match_type", ""),
+ "team_type": i.get("team_type", ""),
+ "event": i.get("event", {}).get("name", ""),
+ "season": str(i.get("season", "")), "venue": i.get("venue", ""),
+ "city": i.get("city", ""), "winner": out.get("winner", ""),
+ "result": res}
+
+MATCH_PROPS = [("match_id", "string"), ("time", "int64_t"), ("date", "string"),
+ ("match_type", "string"), ("team_type", "string"),
+ ("event", "string"), ("season", "string"), ("venue", "string"),
+ ("city", "string"), ("winner", "string"), ("result", "string")]
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+ name = __name__.split(".")[-1]
+ alts_ = [alt for fnames, alt, fmt in files if alts is None or alt in alts]
+ if not alts_:
+ return
+ with open_upstream_file(name, "register/people.csv", "r") as f:
+ people = {r["identifier"]: r for r in csv.DictReader(f)}
+
+ # the data of all networks, read in one pass over the matches
+ deliv = [] # (bowler, batter, match, innings, n, runs, extras, out, kind)
+ games = [] # (team0, team1, gender, match, toss winner)
+ plays = [] # (player, match, team)
+ matches = [] # match info, by match index
+ gender_of = {}
+ team_type = {}
+ for mid, d in _matches(name):
+ i = d["info"]
+ reg = i.get("registry", {}).get("people", {})
+ def pid(p):
+ return reg.get(p, "name:" + p)
+ mi = len(matches)
+ info = _match_info(mid, d)
+ info["toss_winner"] = i.get("toss", {}).get("winner", "")
+ info["teams"] = " vs ".join(i["teams"])
+ info["gender"] = i["gender"]
+ matches.append(info)
+ gender = i["gender"]
+ teams = i["teams"]
+ for t in teams:
+ team_type[(t, gender)] = i.get("team_type", "")
+ if len(teams) == 2:
+ games.append(((teams[0], gender), (teams[1], gender), mi))
+ if "player_matches" in alts_:
+ for t, ps in i.get("players", {}).items():
+ for p in ps:
+ plays.append((pid(p), mi, t))
+ gender_of[pid(p)] = gender
+ if "deliveries" not in alts_:
+ continue
+ for k, inn in enumerate(d.get("innings", [])):
+ agg = {}
+ for o in inn.get("overs", []):
+ for dl in o["deliveries"]:
+ b, s = pid(dl["bowler"]), pid(dl["batter"])
+ gender_of[b] = gender
+ gender_of[s] = gender
+ a = agg.setdefault((b, s), [0, 0, 0, 0, ""])
+ a[0] += 1
+ a[1] += dl["runs"]["batter"]
+ a[2] += dl["runs"]["extras"]
+ for w in dl.get("wickets", []):
+ if pid(w["player_out"]) == s:
+ a[4] = w["kind"]
+ if w["kind"] in BOWLER_KINDS:
+ a[3] = 1
+ for (b, s), a in agg.items():
+ deliv.append((b, s, mi, k + 1, *a))
+
+ def add_player_props(g, vmap):
+ g.vp.name = g.new_vp("string")
+ g.vp.unique_name = g.new_vp("string")
+ g.vp.identifier = g.new_vp("string")
+ g.vp.key_cricinfo = g.new_vp("string")
+ g.vp.gender = g.new_vp("string")
+ for p, v in vmap.items():
+ r = people.get(p)
+ if r is not None:
+ g.vp.name[v] = r["name"]
+ g.vp.unique_name[v] = r["unique_name"]
+ g.vp.key_cricinfo[v] = r["key_cricinfo"]
+ g.vp.identifier[v] = p
+ else:
+ g.vp.name[v] = p.removeprefix("name:")
+ g.vp.gender[v] = gender_of.get(p, "")
+
+ for alt in alts_:
+ g = Graph(directed=(alt == "deliveries"))
+ if alt == "deliveries":
+ vmap = {}
+ for b, s, *_ in deliv:
+ for p in (b, s):
+ if p not in vmap:
+ vmap[p] = len(vmap)
+ g.add_vertex(len(vmap))
+ add_player_props(g, vmap)
+ for k, t in MATCH_PROPS:
+ g.ep[k] = g.new_ep(t)
+ for k, t in [("innings", "int"), ("deliveries", "int"),
+ ("runs", "int"), ("extras", "int"),
+ ("dismissals", "int"), ("dismissal", "string")]:
+ g.ep[k] = g.new_ep(t)
+ def edges():
+ for b, s, mi, inn, n, r, x, out, kind in deliv:
+ m = matches[mi]
+ yield (vmap[b], vmap[s], *[m[k] for k, t in MATCH_PROPS],
+ inn, n, r, x, out, kind)
+ g.add_edge_list(edges(), eprops=[g.ep[k] for k, t in MATCH_PROPS] +
+ [g.ep[k] for k in ["innings", "deliveries", "runs",
+ "extras", "dismissals",
+ "dismissal"]])
+ elif alt == "matches":
+ vmap = {}
+ for t0, t1, mi in games:
+ for t in (t0, t1):
+ if t not in vmap:
+ vmap[t] = len(vmap)
+ g.add_vertex(len(vmap))
+ g.vp.name = g.new_vp("string")
+ g.vp.gender = g.new_vp("string")
+ g.vp.team_type = g.new_vp("string")
+ for (t, gen), v in vmap.items():
+ g.vp.name[v] = t
+ g.vp.gender[v] = gen
+ g.vp.team_type[v] = team_type[(t, gen)]
+ props = MATCH_PROPS + [("toss_winner", "string")]
+ for k, t in props:
+ g.ep[k] = g.new_ep(t)
+ g.add_edge_list(((vmap[t0], vmap[t1], *[matches[mi][k] for k, t in props])
+ for t0, t1, mi in games),
+ eprops=[g.ep[k] for k, t in props])
+ else:
+ vmap = {}
+ for p, mi, t in plays:
+ if p not in vmap:
+ vmap[p] = len(vmap)
+ np_ = len(vmap)
+ g.add_vertex(np_ + len(matches))
+ add_player_props(g, vmap)
+ g.vp.is_player = g.new_vp("bool")
+ g.vp.is_player.a[:np_] = 1
+ for k, t in MATCH_PROPS:
+ g.vp[k] = g.new_vp(t)
+ for mi, m in enumerate(matches):
+ v = g.vertex(np_ + mi)
+ g.vp.name[v] = m["teams"]
+ g.vp.gender[v] = m["gender"]
+ for k, t in MATCH_PROPS:
+ g.vp[k][v] = m[k]
+ g.ep.team = g.new_ep("string")
+ g.add_edge_list(((vmap[p], np_ + mi, t) for p, mi, t in plays),
+ eprops=[g.ep.team])
+ yield alt, g