Data Provenance
Where every dataset in ncaa_bbStats comes from, and on what basis it is
redistributed.
Every dataset shipped in ncaa_bbStats, where it came from, and on what basis
it is redistributed. If you are adding a dataset, add a row here first.
Datasets
Dataset |
Path |
Source |
Terms |
Coverage |
|---|---|---|---|---|
NCAA team statistics |
|
stats.ncaa.org national rankings tables, scraped by |
Official NCAA statistics; factual game records |
2002–2026, Divisions I–III |
MLB draft history |
|
Baseball Almanac, scraped by |
Factual draft records |
1965–2025, 69,169 picks |
Player statistics |
|
See FanGraphs below |
Counting statistics only; see below |
2021–2025, Division I |
League constants |
|
Regressed from |
Package’s own work |
2008–2026 (D-III from 2009) |
Team registry |
|
Built from the caches above plus IPEDS unitids by |
Package’s own work; IPEDS identifiers are U.S. federal public domain |
1,023 programs, 2002–2026 |
MLB draft detail |
|
MLB Stats API, fetched by |
Public MLB Advanced Media API; factual draft records |
2021–2026, 3,685 picks |
RPI / strength of schedule |
|
Warren Nolan, converted by |
Third-party computation, not official NCAA; factual records |
2021–2026, Division I |
Program finances |
|
EADA survey, U.S. Dept. of Education, derived by |
U.S. federal government work; public domain |
2021–2025, carried forward to 2026 |
Draft prospect rankings |
|
MLB Pipeline top-250, converted by |
Third-party rankings, attributed |
2021–2026, 250/year |
Player registry |
|
Resolved from the player cache, anchored to the MLB Stats API by |
Package’s own work |
27,283 players, 2021–2025 |
Draft models |
|
Trained by |
Package’s own work |
Trained 2021–2024, tested 2025 |
Pythagorean exponents |
|
Fitted to NCAA team-season data |
Package’s own work |
31 conferences; experimental |
Team / school name tables |
|
Derived from the caches above by |
Package’s own work |
— |
Facts about sporting events — who played, how many hits they got — are not themselves copyrightable in the United States (Feist Publications v. Rural Telephone Service, 499 U.S. 340 (1991)). What is protectable is a compiler’s original selection, arrangement, and derived analytics. That distinction is what draws the line below.
FanGraphs
The player statistics in this package originate from FanGraphs’ college leaderboards, which sit behind a paid FanGraphs Membership. FanGraphs’ terms of use do not permit redistribution of their bulk leaderboard data, and the research repository these files came from gitignores them for exactly that reason.
Two categories were removed in version 1.2.0:
FanGraphs-derived metrics. wRC+, wOBA, wRAA, wRC, wSB, Spd,
FIP, E-F, and LOB% all depend on FanGraphs’ own NCAA linear weights, league
constants, and park factors. Those are FanGraphs’ analytical product, not facts.
They are replaced by package-original equivalents (below).
FanGraphs identifiers. FanGraphs’ playerid (values like 29547 or
sa3025257) is their internal key. It is replaced by a package-owned
player_id. The mlbamid column is re-sourced from the public MLB Stats API
rather than inherited from the FanGraphs export.
What was kept, and the honest caveat. Raw counting statistics — games, at-bats, hits, doubles, home runs, walks, strikeouts, innings pitched, earned runs — are records of what happened on the field. They are NCAA’s facts, and no compiler acquires exclusive rights in them by publishing them. They are retained.
But their provenance in this package is still a FanGraphs export, even though
the underlying facts are not FanGraphs’. Re-deriving them directly from
stats.ncaa.org individual-player pages is planned, and would remove the
dependency entirely. ncaa_bbStats.team_stats already handles that site’s bot
protection. Until that lands, this section is the accurate description of where
these numbers came from.
Team names are not FanGraphs’. The team name column is filled from
src/data/registry/teams.csv (canonical_name), not from the vendor export.
The vendor’s own column could not be used: it disagrees with itself across the
batting and pitching files for 13 acronyms covering roughly a thousand rows —
TAR is Tarleton State in one and North Carolina in the other, CAM is
Campbell in one and Cambridge in the other — and the 2026 export omits the
column entirely. The registry agrees with the batting file in all 13 cases, so
the pitching values were the wrong ones. Values are the NCAA display label
(“Missouri St.”, “Saint Mary’s (CA)”) rather than the IPEDS legal name.
The qualified flag is keyed on the vendor player id, not on name. The same
player is written Cam Kozeal in one export and Camden Kozeal in the other;
16 rows of the 2026 season differ that way, and by name they look like players
who qualified without appearing in the no-minimum population at all. Keying on
name also conflated the two distinct players named Cole Conn at UIC, marking a
73-plate-appearance season as qualified in 2022 and 2023. Both are fixed in
1.3.0; qualified changes for those two rows relative to 1.2.0.
Version history. Releases 1.0.x and 1.1.0 did not include
src/data/player_stats_cache — MANIFEST.in never listed it — so no published
wheel or source distribution contains FanGraphs data. The files were, however,
committed to the public git repository, and remain reachable in history at
commits c418135, 8c3d55b, 7afa3b1, and a4320ec. History has not been
rewritten.
Version 1.3.0 adds the 2026 season (5,330 batting and 5,404 pitching rows, 308
Division I teams), ingested by tools/add_fg_season.py. Coverage is now
2021–2026.
Package-original metrics
Replacements for the removed FanGraphs metrics, computed from public counting
statistics using linear weights this package derives from its own NCAA team-stats
cache. Full formulas and the regression method are in
docs/advanced_stats.rst; constants ship in src/data/league_constants/.
Run values are fitted per season and division by weighted least squares over team-season totals (R² 0.96–0.98 on runs scored, RMSE about 16 runs against seasons averaging 300), then shrunk toward the division’s pooled estimate. The shrinkage matters: the season-to-season spread of the raw coefficients is about the same size as their standard errors, so most of the movement is sampling noise. Home-run and hit-by-pitch weights shrink fully to the pooled value; singles and walks retain roughly half their season-specific estimate.
The hit-type weights are then projected onto the ordering that physics requires (1B ≤ 2B ≤ 3B ≤ HR) by inverse-variance-weighted isotonic regression. Without it, 34 of 55 division-seasons place the triple above the home run — an artifact of triples occurring in well under 1% of plate appearances, which leaves their coefficient absorbing rally context. Correlations below are unaffected by the projection; it only repairs impossible orderings.
Measured correlation against the metrics they replace, over the qualified Division I population (11,529 batting and 5,642 pitching seasons, 2021–2025). Published so the derivation can be judged as independent work rather than a repackaging:
Metric |
Replaces |
Pearson r |
Spearman |
|---|---|---|---|
|
|
1.0000 |
1.0000 |
|
|
0.9961 |
0.9962 |
|
|
0.9925 |
0.9917 |
|
|
0.9685 |
0.9667 |
|
|
0.9460 |
0.9388 |
|
|
0.8955 |
0.8613 |
|
|
0.9124 |
0.9052 |
The rate statistics that are pure arithmetic — AVG, OBP, SLG, OPS, ISO, BABIP, BB%, K%, ERA, WHIP, K/9, BB/9, K-BB% — reproduce the removed columns exactly (maximum absolute difference 0.000000 across 26,826 batting rows; about 1e-6 for the innings-denominated pitching rates, from rounding in the stored values). This is why the cache stores counting statistics only: nothing was lost.
There is a sharper way to put the wOBA result. cwoba and the metric it
replaces are both linear functions of the same six counting statistics. In any
model that already has singles, doubles, triples, home runs, walks, hit-by-pitch
and plate appearances as inputs, neither adds information — each lies exactly in
the span of the others. What these metrics provide is interpretability, not
signal. The only content not recoverable from the counting statistics is the
park adjustment, which is discussed below.
Known limitations
No park factors.
cwrc_plusassumes a park factor of 1.0 for every program. NCAA park data is not publicly available; deriving it would require game logs. Hitters at extreme-altitude programs (Mountain West, RMAC) are therefore flattered relative to a park-adjusted figure, and magnitudes are not comparable to FanGraphs’wRC+.Batting-side proxies. The team cache has no home-runs-allowed field in any season, and no
BB (Pitching)before 2011 (2012 for Division III). League totals from the batting side stand in. Measured closure error is 0.4–2.1%.No weights before 2008. Seasons 2002–2007 record only at-bats, hits, and runs, which is not enough to fit event weights. Division III also has a gap at 2011, when it stopped reporting walks, hit-by-pitch and sacrifice flies. Advanced metrics return
Nonefor those seasons rather than a fabricated value.Division II has no sacrifice-hit data in any season. This does not affect the metrics: the plate-appearance denominator is
AB + BB + HBP + SF, which excludes sacrifice hits by construction.cspduses Major League calibration constants. Its formula is published and unmodified, but the constants inside it were fitted to Major League play, so the NCAA population does not center on the conventional 5.0 — qualified Division I hitters average about 3.9, and 5.0 is roughly the 80th percentile. Compare players to each other rather than to the usual scale. It is the weakest metric here and is informational only; every input is retained, so prefer those for modelling.cwsbcorrelates least well (r = 0.90) of the run-value metrics, because it is a small-magnitude quantity — a standard deviation of about one run — so modest absolute disagreements read as large relative ones.
Notes on the ported datasets
MLB Stats API. Payloads are trimmed to the fields the package reads. The
blurb field — MLB Pipeline’s editorial scouting prose, and the only field here
with a real authorship claim attached — is deliberately not stored; the
scouting_report_url is kept, so the material remains reachable at the source.
headshotLink is dropped as reconstructible from the player id. Responses carry
MLB Advanced Media’s copyright notice, which applies to their presentation of
these records, not to the facts of who was drafted where.
Warren Nolan RPI. RPI, strength of schedule, and quadrant records are Warren Nolan’s computation from public game results, not official NCAA figures. Do not cite them as NCAA statistics. Coverage is Division I only, from 2021 — the site does not publish earlier years, so this gap is permanent rather than a backlog.
EADA. A work of the U.S. federal government and therefore public domain. Only the twelve derived features ship; the source workbooks are roughly 100 MB each and 4,275 columns wide, and are read from a local download.
Download them from https://ope.ed.gov/athletics/#/datafile/list — take the
combined data file for each academic year, which unpacks to EADA_<YYYY>.xlsx.
Point ncaa_bbStats.program_store --eada-dir at wherever they landed. (The
/athletics/ landing page does not expose the files; the data-file list does.)
Year alignment: EADA_<YYYY>.xlsx covers the academic year ending in YYYY, which
is the spring YYYY baseball season, so it maps onto the season year with no lag.
Institutions file the 2025-26 survey in October 2026, so the 2026 season carries
2025 forward — every such row is flagged carried_forward, and
program_finance() reports it, because a carried-forward figure quietly treated
as current is how wrong conclusions get published.
Percentile features are ranked within a reporting year rather than expressed in raw dollars: budgets inflate a few percent annually, so raw figures would make the carried-forward season look systematically poorer. Rosters outside 15–75 players are treated as unreported — a few institutions file a system-wide row summing every branch campus, which shows up as one program carrying 453 baseball players.
Coverage is 99% of Division I and about 69% of Divisions II and III. The gap is not missing survey data: those programs do not yet have IPEDS unitids in the registry, so the join falls back to name matching. Backfilling them would close it.
MLB Pipeline. Pre-draft prospect rankings, included as a benchmark. Third-party editorial rankings, attributed. High-school prospects have no college program to resolve to and are flagged rather than forced onto one.
View them from here: https://www.mlb.com/milb/prospects/draft/
Conference Pythagorean exponents. Fitted to NCAA team-season data, and
shipped as an experiment rather than as a default. Fitting moves the exponent
between 1.45 and 2.08, but none of the 31 conference fits differs from the
standard 1.83 at p < 0.05 — the p-values run from 0.17 to 0.98. The table ships
so the result is inspectable and so nobody has to re-derive it to reach the same
conclusion; conference_calibrated=True is opt-in everywhere, and the
significant column reads no for every row.
Player identity
player_id is assigned by this package, not inherited from any source. It is
stable within a major version. Splits and merges may occur in minor releases and
are always recorded in src/data/player_registry/player_id_aliases.csv with a
reason; a retired id is never reassigned to a different person. Use
resolve_player_id() to follow an alias chain. Ids are never renumbered in a
patch release.