Does winning the toss matter at IPL venues? A Cricsheet project
In this article (7 sections)
Related programme: the Data Science course (6 months; ₹1,30,000 (inclusive of GST) · EMI from ₹5,000/month).
Commentators say the toss decides matches at some grounds. This project tests that claim with Cricsheet's IPL match files. It estimates how often the toss winner goes on to win, overall and at each venue, with confidence intervals and a correction for testing many venues at once. It also estimates venue par first-innings scores, so you can check whether "toss matters here" really means "chasing is easier here". It is a small-sample inference problem dressed as cricket, which is exactly why data science interviewers like it.
The data, and the file you will actually parse
From Cricsheet's downloads, take ipl_csv2.zip. Each match has an <id>_info.csv, which is not a table. Every line has the form info,<key>,<value>, and some keys repeat, such as two team lines, several umpire lines, and a player line per player.
The keys you need are venue, city, date, toss_winner, toss_decision (bat or field), winner, winner_runs or winner_wickets, and the special cases outcome, method and eliminator. For par scores you also need the deliveries file.
In the copy we downloaded (1,243 matches):
- 25 matches carried an
outcomeline, used for ties and no-results. - 23 carried
method"D/L". - 16 carried
eliminator, the team that won a tied match through a super over.
Decide up front how each of these enters your analysis. Check Cricsheet's site for its current usage terms, and credit it in your README.
Venue names are the main cleaning job
The same ground appears under several names in the real files. Delhi's ground appears as "Feroz Shah Kotla", "Arun Jaitley Stadium" and "Arun Jaitley Stadium, Delhi". Bengaluru's appears as "M Chinnaswamy Stadium", "M.Chinnaswamy Stadium" and "M Chinnaswamy Stadium, Bengaluru". Build a hand-checked alias table. Do not rely on fuzzy matching alone, because two different grounds in one city can look alike.
Framing the hypothesis
- H0: P(toss winner wins) = 0.5.
- Unit: matches with a result. Report how many you excluded as no-results.
- Ties: count them as won by the super-over winner (the
eliminator), or exclude them. Pick one and show the other in a footnote. - Rain-affected matches (D/L): include them in the main analysis and exclude them in a sensitivity check.
- Venue-level claims: each venue is its own test, so with a dozen or more grounds, some will look significant by chance. Use a Holm or Bonferroni correction, or report shrunk estimates.
Code: parse info files, then estimate with intervals
The info-file text and match results below are synthetic. They follow the real file's line format, but the venues, teams and outcomes are invented.
import math
import random
import pandas as pd
def parse_info(text):
rec = {"team": []}
for line in text.strip().splitlines():
parts = line.split(",", 2)
if parts[0] != "info" or len(parts) < 3:
continue
key, value = parts[1], parts[2].strip('"')
if key == "team":
rec["team"].append(value)
elif key not in ("player", "registry", "umpire"):
rec[key] = value
return rec
sample = '''version,2.3.0
info,team,Team X
info,team,Team Y
info,venue,"Ground One, City"
info,toss_winner,Team Y
info,toss_decision,field
info,winner,Team Y
info,winner_wickets,6'''
print(parse_info(sample))
random.seed(5)
venues = {"Ground One": 0.60, "Ground Two": 0.50, "Ground Three": 0.45, "Ground Four": 0.52}
rows = []
for venue, p in venues.items():
for _ in range(random.randint(40, 90)):
rows.append({"venue": venue, "toss_winner_won": random.random() < p})
m = pd.DataFrame(rows)
def wilson(k, n, z=1.96):
phat = k / n
denom = 1 + z * z / n
centre = (phat + z * z / (2 * n)) / denom
half = z * math.sqrt(phat * (1 - phat) / n + z * z / (4 * n * n)) / denom
return round(centre - half, 3), round(centre + half, 3)
def binom_two_sided_p(k, n):
probs = [math.comb(n, i) * 0.5 ** n for i in range(n + 1)]
return min(1.0, sum(pr for pr in probs if pr <= probs[k] + 1e-12))
out = m.groupby("venue")["toss_winner_won"].agg(["sum", "count"])
out["rate"] = (out["sum"] / out["count"]).round(3)
out["ci95"] = [wilson(k, n) for k, n in zip(out["sum"], out["count"])]
out["p_raw"] = [round(binom_two_sided_p(k, n), 4) for k, n in zip(out["sum"], out["count"])]
# Holm correction across venues
order = out["p_raw"].sort_values().index
mtests = len(out)
adj, running = {}, 0.0
for i, v in enumerate(order):
running = max(running, min(1.0, (mtests - i) * out.loc[v, "p_raw"]))
adj[v] = round(running, 4)
out["p_holm"] = pd.Series(adj)
print(out)
k, n = int(m["toss_winner_won"].sum()), len(m)
print("overall:", round(k / n, 3), wilson(k, n))The exact binomial p-value is written out with math.comb so the method is transparent, with no statistics library needed. On real data, one venue may show a raw p-value below 0.05 that is no longer significant after Holm. That is the most common and most useful finding in this project.
Separating "toss" from "chasing"
A toss advantage at a venue may just be a chasing advantage, since toss winners usually choose to field. So estimate two more things:
- Venue par score: the median first-innings total, restricted to completed 20-over first innings. Take innings totals from the deliveries file, excluding super overs (innings 3 and above).
- Chasing win rate: at each venue, how often the team batting second wins, whatever happened at the toss.
If the chasing rate explains the toss effect, your conclusion changes from "the toss matters" to "fielding first matters". A logistic regression of the win on toss_won, batting_second and venue fixed effects makes this explicit. Report it with standard errors and warn about collinearity, since most toss winners field.
What you deliver
- 1A forest plot of toss-winner win rate by venue, with Wilson intervals and a 0.5 reference line. Venues are ordered by number of matches, and each is labelled with n.
- 2A table of venue, matches, par first-innings score, chasing win rate, toss rate and Holm-adjusted p-value.
- 3A season split for the Delhi ground, to see whether its pattern is stable over time.
- 4A README with the source, format, venue alias table, rules for ties, no-results and D/L, multiple-testing correction and limitations (conditions change with dew, pitch relaying and team strength).
Interview questions to prepare
- Why a Wilson interval rather than the normal approximation?
- What is the difference between Holm and Bonferroni, and why use either?
- If toss winners field 80% of the time, what problem does that create for your regression?
- A venue shows 60% with n = 45. What would you tell a team analyst?
- How would a hierarchical model help here, compared with Holm?
Our Data Science programme teaches inference with small samples like these. The death-over bowling project is a simpler companion on the same data.
Pankit Kumar has 10 years in Data Science & AI, building and shipping production systems in regulated pharma and clinical environments. He is a freelance trainer at Boston Institute of Analytics, AnalytixLabs and Scaler, and has taught this material to thousands of working professionals.
This article is part of our Data Science programme — 6 months. From data foundations to machine learning, deep learning and deployment.
Explore Data Science