About
Why this site exists
SportsDataTutorials publishes under its own name, not a person's. It is owned by an independent publisher; how this site is made explains how the tutorials are made: from public data, under the owner's direction. Where a tutorial says "we", it means the site, working through the code alongside you.
The site exists because so many tutorials fail the people following them. The code dies on line three with a version error nobody warned about - or worse, it "works" but quietly prints numbers that couldn't possibly be right, with no way to tell. So the rule here is simple: nothing is hand-waved. Every tutorial's code is run against a real data source, and every chart and table you see is the genuine output of that run. If a result looks weird, it's because the data is weird, not because a clean answer was faked.
That honesty cuts both ways. The NBA's stats API blocks requests from data centers, including the machine that builds this site, so the tutorials say exactly what happens, show the fallback, and explain how the same script pulls live data when you run it from your own laptop. A little lost polish is better than pretending something works when it doesn't.
Editor
C. B. Zakarian (a pen name) is the owner and editor of SportsDataTutorials. C. B. Zakarian holds a Ph.D. in Information Systems, with a focus on data science, from the University of North Carolina at Greensboro (2016), and is an assistant professor.
C. B. Zakarian decides what SportsDataTutorials publishes and when, and the figures on each page are checked against the sources it names before publication. Pages the editor has reviewed in full show the date of that review, and errors are corrected when they are found.
How the site thinks about teaching this
You don't learn analytics from a textbook or a 40-hour course. You learn it by shipping small, real things: pull a week of data, make one honest chart, notice three things you didn't expect, then do it again on a question you actually care about. So every tutorial here is built around one finished artifact - a leaderboard, a shot chart, a model - that you'll have working by the end, with opinions included, the gotchas called out before they bite you, and no pretending the messy parts don't exist.
Where the data comes from
Everything here runs on free, well-respected public sources:
- Baseball – Statcast via
pybaseball(Baseball Savant), with caching turned on to be a good guest. - Basketball – the NBA's stats API via
nba_api, with Basketball-Reference as a documented fallback. - Soccer – StatsBomb Open Data (attribution required, and given) and Understat's expected-goals data.
- American football – nflverse play-by-play, read with
nfl_data_py. - Hockey – the NHL's public API at
api-web.nhle.com. - Sample NBA shot data – the public NBA_Shots_04_25 shot-log dataset, which is where the bundled shot CSVs come from.
- Baseball standings and soccer fixtures – the MLB Stats API and ESPN's public scoreboard, which produce the bundled CSVs.
The example code caches requests, sends polite headers, and keeps request rates reasonable - partly so you pick up good habits, and partly because these sources are free and should stay that way for the next person.
How a tutorial gets published
Every tutorial starts as a script, not as prose. The script is run against the real source, and the build system captures its printed output and its charts straight from that run into the page — so a printed table here is stdout from a file you can download, and every chart is the image that file wrote. When the run changes, the page changes with it. Nothing is retyped from memory, and no figure gets published that no script produced.
Found a mistake?
Say so — it is better to hear it than not. Email contact@sportsdatatutorials.com and it will be fixed.