WNBA — additional Python functions — Analytics
make_prob_by_context
make_prob_by_context(ptshots: 'pl.DataFrame', *, return_as_pandas: 'bool' = False) -> "'dict[str, Union[pl.DataFrame, pd.DataFrame]]'"
Marginal FG% tables by defender distance and by shot clock.
The public API exposes defender-distance and shot-clock only as aggregate
bucket tables (playerdashptshots), not per-shot fields, so this
aggregates Σfgm/Σfga across players within each bucket.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
ptshots | DataFrame | The stacked playerdashptshots fixture — one frame with a result_set tag (ClosestDefenderShooting / ShotClockShooting) plus bucket, fga, fgm. | |
return_as_pandas | bool | False | Return pandas DataFrames instead of polars. |
Returns
{"defender": frame, "shot_clock": frame} each with rows per bucket (bucket, fga, fgm, fg_pct). Missing result sets return the zero-row schema.
Example
from sportsdataverse.nba.nba_shot_value import make_prob_by_context
tables = make_prob_by_context(ptshots)
tables["defender"].sort("fg_pct")
make_prob_joint
make_prob_joint(defender: 'pl.DataFrame', shot_clock: 'pl.DataFrame', overall_fg_pct: 'float', *, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
Independence-combined defender x shot-clock make probability.
Combines the two marginal FG% tables under a conditional-independence
assumption via odds multipliers: odds(p) = p/(1-p);
odds_joint = odds_overall * (odds_def/odds_overall) * (odds_clock/odds_overall); joint = odds_joint/(1+odds_joint). This
assumes defender distance and shot-clock effects are independent given the
league baseline — a simplification (a late clock correlates with tighter
defense), documented here so callers weigh it.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
defender | DataFrame | The "defender" marginal table from make_prob_by_context (bucket, fg_pct). | |
shot_clock | DataFrame | The "shot_clock" marginal table (bucket, fg_pct). | |
overall_fg_pct | float | The league overall FG% baseline. | |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
One row per (close_def_dist_range, shot_clock_range): close_def_dist_range:Utf8, shot_clock_range:Utf8, joint_fg_pct:Float64. Empty inputs return the zero-row schema.
No returns table is published for this function: no capture: its inputs come from make_prob_by_context on stats.nba.com tracking data, which answers HTTP 403 to the datacenter IP the docs are built on.
Example
from sportsdataverse.nba.nba_shot_value import make_prob_by_context, make_prob_joint
t = make_prob_by_context(ptshots)
joint = make_prob_joint(t["defender"], t["shot_clock"], 0.47)
score_shot_xpoints
score_shot_xpoints(shots: 'pl.DataFrame', league_avgs: 'pl.DataFrame', *, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
Score each shot with expected points from the league-average baseline.
Joins the per-shot frame to the zone baseline (falling back to the
within-shot_zone_range mean when a zone triple is unmatched) and adds
shot_value (3 for a 3PT shot else 2), xpoints = base_fg_pct * shot_value, and actual_points = shot_made_flag * shot_value.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
shots | DataFrame | Per-shot Shot_Chart_Detail frame (needs shot_type + the three zone keys + shot_made_flag). | |
league_avgs | DataFrame | The LeagueAverages frame (see xpoints_baseline). | |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
The input shots plus shot_value:Int64, base_fg_pct:Float64, xpoints:Float64, actual_points:Float64. Empty input returns the augmented schema with zero rows.
No returns table is published for this function: no capture: its input is the shots frame of wnba_shot_value, which reads stats.nba.com shotchartdetail; that host answers HTTP 403 to the datacenter IP the docs are built on.
Example
from sportsdataverse.nba.nba_shot_value import score_shot_xpoints
scored = score_shot_xpoints(shots, league_avgs)
# Pipeline next step (one line)
scored.group_by("player_id").agg(pl.col("xpoints").sum())
shooter_talent
shooter_talent(scored_shots: 'pl.DataFrame', *, league_id: 'str' = '00', min_attempts: 'int' = 50, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
Regressed shooter true-talent: make%-above-expected, shrunk to the mean.
Aggregates score_shot_xpoints output per shooter and regresses the
raw over-expected rate toward zero by n/(n+k) (k = get_shrinkage_k(league_id), fitted split-half). As-of leakage
boundary: to score a shooter's talent for shots after date D, pass
only that shooter's shots before D -- this function does not enforce the
cut itself.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
scored_shots | DataFrame | score_shot_xpoints output (needs player_id, shot_made_flag, base_fg_pct, xpoints, actual_points). | |
league_id | str | '00' | "00" NBA, "10" WNBA, "20" G-League. |
min_attempts | int | 50 | Drop shooters with fewer attempts (unstable estimate). |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
One row per player_id: player_id:Int64, n_att:Int64, actual_makes:Int64, exp_makes:Float64, points_above_expected:Float64, raw_above_pct:Float64, talent_pct:Float64. Empty input returns the zero-row schema.
No returns table is published for this function: no capture: its input is the shots frame of wnba_shot_value, which reads stats.nba.com shotchartdetail; that host answers HTTP 403 to the datacenter IP the docs are built on.
Example
from sportsdataverse.nba.nba_shot_value import score_shot_xpoints, shooter_talent
talent = shooter_talent(score_shot_xpoints(shots, league_avgs))
# Pipeline next step (one line)
talent.sort("talent_pct", descending=True).head(15)
shot_selection_quality
shot_selection_quality(scored_shots: 'pl.DataFrame', *, min_attempts: 'int' = 50, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
Player shot-selection quality: mean expected value vs the league mean.
xev_per_shot is a player's mean xpoints (the value of the LOOKS
they take, independent of makes); selection_quality is that minus the
league-wide mean xpoints over the same frame -- a rim-and-three diet
scores positive, a mid-range diet negative.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
scored_shots | DataFrame | score_shot_xpoints output (needs player_id, xpoints). | |
min_attempts | int | 50 | Drop players with fewer attempts. |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
One row per player_id: player_id:Int64, n_att:Int64, xev_per_shot:Float64, league_xev_per_shot:Float64, selection_quality:Float64. Empty input returns the zero-row schema.
No returns table is published for this function: no capture: its input is the shots frame of wnba_shot_value, which reads stats.nba.com shotchartdetail; that host answers HTTP 403 to the datacenter IP the docs are built on.
Example
from sportsdataverse.nba.nba_shot_value import score_shot_xpoints, shot_selection_quality
sel = shot_selection_quality(score_shot_xpoints(shots, league_avgs))
# Pipeline next step (one line)
sel.sort("selection_quality", descending=True).head(15)
wnba_availability
wnba_availability(seasons: "'int | list[int]'", *, return_as_pandas: 'bool' = False) -> "'pl.DataFrame | pd.DataFrame'"
WNBA availability -- the NBA core bound to league="wnba".
See sportsdataverse.nba.nba_availability.nba_availability for the
full contract; avail_pct is availability, not skill.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | list[int] | A season (start year) or list of seasons. | |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
Frame player_id:Utf8, season:Int64, avail_pct:Float64.
No returns table is published for this function: no capture: it reads stats.wnba.com, which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_availability
proj = wnba_availability(2023)
wnba_expected_turnovers
wnba_expected_turnovers(season: 'str', *, base: "'Optional[pl.DataFrame]'" = None, player_mix: "'Optional[pl.DataFrame]'" = None, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA expected turnovers / ball-security skill (league_id="10").
Thin wrapper binding
sportsdataverse.nba.nba_expected_turnovers.nba_expected_turnovers
to the women's league.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
season | str | Season string, e.g. "2024". | |
base | Optional[DataFrame] | None | Injected nba_stats_leaguedashplayerstats (Base) frame. |
player_mix | Optional[DataFrame] | None | Injected Synergy player-level offensive mix. |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
Same schema as sportsdataverse.nba.nba_expected_turnovers.nba_expected_turnovers.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_expected_turnovers
t = wnba_expected_turnovers("2024")
print(t.sort("ball_security_skill", descending=True).head())
wnba_foul_drawing
wnba_foul_drawing(season: 'str', *, base: "'Optional[pl.DataFrame]'" = None, advanced: "'Optional[pl.DataFrame]'" = None, player_mix: "'Optional[pl.DataFrame]'" = None, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA foul-drawing / FT-generation (league_id="10").
Thin wrapper binding
sportsdataverse.nba.nba_foul_drawing.nba_foul_drawing to the
women's league.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
season | str | Season string, e.g. "2024". | |
base | Optional[DataFrame] | None | Injected nba_stats_leaguedashplayerstats (Base) frame. |
advanced | Optional[DataFrame] | None | Injected Advanced-measure frame. |
player_mix | Optional[DataFrame] | None | Injected Synergy player-level offensive mix. |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
Same schema as sportsdataverse.nba.nba_foul_drawing.nba_foul_drawing.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_foul_drawing
f = wnba_foul_drawing("2024")
print(f.sort("foul_draw_skill", descending=True).head())
wnba_matchup_drapm
wnba_matchup_drapm(season: 'str', *, matchups: "'Optional[pl.DataFrame]'" = None, config: "'Optional[PlaytypeConfig]'" = None, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA matchup defensive RAPM (league_id="10").
Thin wrapper binding
sportsdataverse.nba.nba_matchup_drapm.nba_matchup_drapm to the
women's league.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
season | str | Season string, e.g. "2024". | |
matchups | Optional[DataFrame] | None | Injected nba_stats_leagueseasonmatchups-shaped frame. |
config | Optional[PlaytypeConfig] | None | ~sportsdataverse.nba.nba_playtype_constants.PlaytypeConfig override. |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
Same schema as sportsdataverse.nba.nba_matchup_drapm.nba_matchup_drapm.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_matchup_drapm
d = wnba_matchup_drapm("2024")
print(d.sort("matchup_drapm", descending=True).head())
wnba_player_props
wnba_player_props(season: 'int', game_id: 'str', home_team_id: 'str', away_team_id: 'str', *, league_id: 'str' = '00', return_as_pandas: 'bool' = False) -> 'Union[pl.DataFrame, pd.DataFrame]'
WNBA player props (league_id='10'). See sportsdataverse.nba.nba_player_props.nba_player_props.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
season | int | ||
game_id | str | ||
home_team_id | str | ||
away_team_id | str | ||
league_id | str | '00' | |
return_as_pandas | bool | False |
Returns
One row per player on either team: player_id, team_id, stat_pts_exp, stat_reb_exp, stat_ast_exp, stat_fg3m_exp, pace_proj. Empty input returns that schema with zero rows.
| col_name | type | description |
|---|---|---|
player_id | character | Unique player identifier. |
team_id | character | Unique team identifier. |
stat_pts_exp | double | |
stat_reb_exp | double | |
stat_ast_exp | double | |
stat_fg3m_exp | double | |
pace_proj | double |
wnba_playtype_ratings
wnba_playtype_ratings(season: 'str', *, off_team: "'Optional[pl.DataFrame]'" = None, def_team: "'Optional[pl.DataFrame]'" = None, schedule: "'Optional[pl.DataFrame]'" = None, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA Synergy play-type-adjusted offense/defense (league_id="10").
Thin wrapper binding
sportsdataverse.nba.nba_playtype.nba_playtype_ratings to the
women's league. Synergy coverage is sparse for the WNBA; an empty upstream
fetch degrades to a zero-row frame (never raises).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
season | str | Season string, e.g. "2024". | |
off_team | Optional[DataFrame] | None | Injected Synergy offensive team frame (bypasses the live fetch). |
def_team | Optional[DataFrame] | None | Injected Synergy defensive team frame. |
schedule | Optional[DataFrame] | None | Injected team_id/opp_team_id schedule frame. |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
Same schema as sportsdataverse.nba.nba_playtype.nba_playtype_ratings.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_playtype_ratings
r = wnba_playtype_ratings("2024")
print(r.sort("adj_off", descending=True).head())
wnba_referee_assignments
wnba_referee_assignments(date: 'str | _dt.date', *, raw: 'bool' = False, return_as_pandas: 'bool' = False, proxy: 'dict | None' = None) -> 'dict[str, Any]'
Fetch and parse WNBA referee assignments for a given date from official.nba.com.
Retrieves the referee crew assignments and replay center officials for all WNBA
games on a given date. The crew_position column (1–4) represents the feed's
slot order; slot 1 is inferred to be the crew chief. The season column is
the WNBA single-year season (feed year converted as-is). This is a thin shim
over sportsdataverse.nba.nba_officiating.nba_referee_assignments that
sets league="wnba".
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
date | str | date | The date to fetch assignments for (str in "YYYY-MM-DD" format or datetime.date). | |
raw | bool | False | If True, return the raw JSON payload (dict) with all three leagues instead of parsed DataFrames. |
return_as_pandas | bool | False | If True, return pandas DataFrames instead of polars. |
proxy | dict | None | None | Optional proxy dict passed through to the HTTP layer. |
Returns
A dict with keys "officials" and "replay_center" mapping to DataFrames. If raw=True, returns the full three-league JSON payload instead.
| col_name | type | description |
|---|---|---|
officials.league | character | League the assignment belongs to: nba, gl (G League), or wnba. |
officials.game_id | character | 10-digit game id (zero-padded) for the assigned game. |
officials.game_date | date | Game date parsed from the feed's MM/DD/YYYY format. |
officials.season | integer | Season end year, converted from the feed's |
officials.season_type | character | Season type decoded from the feed's season code first digit: preseason, regular, all-star, playoffs, play-in, or nba-cup-final. |
officials.game_code | character | League game code in YYYYMMDD/AWYHOM format, matching the away and home team abbreviations. |
officials.home_team_id | integer | 10-digit team id of the home team. |
officials.home_team_abbr | character | Three-letter abbreviation of the home team. |
officials.away_team_id | integer | 10-digit team id of the away team. |
officials.away_team_abbr | character | Three-letter abbreviation of the away team. |
officials.crew_position | integer | Feed's official slot order (1-4); slot 1 is inferred to be the crew chief since the API does not label roles. |
officials.official_id | integer | Numeric official id from the feed (source field official{n}_code); expected to match stats.nba.com's OFFICIAL_ID. |
officials.official_name | character | Official's display name for this crew slot. |
officials.jersey_num | character | Official's jersey number as a string, from the feed's official{n}_JNum field. |
replay_center.league | character | League the replay-center staffing belongs to: nba, gl, or wnba. |
replay_center.game_date | date | Date the replay-center official worked; a date-level staffing record, not tied to one game. |
replay_center.official_id | integer | Numeric replay-center official id from the feed. |
replay_center.official_name | character | Replay-center official's display name for that date. |
Example
from sportsdataverse.wnba.wnba_officiating import wnba_referee_assignments
result = wnba_referee_assignments("2026-06-13")
officials = result["officials"]
print(f"Found {officials.height} official slots")
wnba_shot_value
wnba_shot_value(player_ids: "'list[int]'", season: 'str', *, include_context: 'bool' = False, return_as_pandas: 'bool' = False) -> "'dict[str, Union[pl.DataFrame, pd.DataFrame]]'"
WNBA one-call shot-value spine (league_id="10").
Thin wrapper binding sportsdataverse.nba.nba_shot_value.nba_shot_value
to the women's league; fetches each player's shotchartdetail, scores
per-shot expected points from the free LeagueAverages zone table, and
returns the scored shots plus shooter talent, selection quality, and
zone-value maps (and the defender/shot-clock context tables when
include_context=True). Women's court geometry + shrinkage constant are
keyed "10" in nba_shot_value_constants.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
player_ids | list[int] | Player ids to fetch. | |
season | str | Season string, e.g. "2024". | |
include_context | bool | False | Also fetch + return the playerdashptshots defender/shot-clock context tables. |
return_as_pandas | bool | False | Return pandas frames instead of polars. |
Returns
{"shots", "talent", "selection", "zones"} (plus "context" when requested). An empty fetch returns a dict of zero-row frames.
Example
from sportsdataverse.wnba import wnba_shot_value
out = wnba_shot_value([1628886], "2024")
out["talent"].head()
wnba_team_clutch
wnba_team_clutch(season: 'int', *, league_id: 'str' = '00', return_as_pandas: 'bool' = False) -> 'Union[pl.DataFrame, pd.DataFrame]'
WNBA clutch skill (league_id='10'). See sportsdataverse.nba.nba_clutch.nba_team_clutch.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
season | int | ||
league_id | str | '00' | |
return_as_pandas | bool | False |
Returns
One row per team: season, team_id, clutch_net_rating, adj_net_rtg, clutch_delta, clutch_skill_shrunk, clutch_poss. Empty input returns that schema with zero rows.
No returns table is published for this function: no capture: it reads stats.wnba.com, which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
wnba_tracking_drive_value
wnba_tracking_drive_value(seasons: "'int | str | list'", *, league_id: 'str' = '10', per_mode: 'str' = 'Totals', by_position: 'bool' = True, positions: 'Optional[pl.DataFrame]' = None, return_as_pandas: 'bool' = False, _get_fn: 'Optional[Callable[..., dict]]' = None) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA drive value + rim-pressure (league_id="10" by-reference shim).
See sportsdataverse.nba.nba_tracking_value.nba_tracking_drive_value
for the full recipe.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '10' | Defaults to "10" (WNBA); pass "20" here for G-League. |
per_mode | str | 'Totals' | per_mode_simple passed to the fetch (default "Totals"). |
by_position | bool | True | Compute the baseline within role buckets (default); False forces one league-wide bucket. |
positions | Optional[DataFrame] | None | Optional pre-fetched positions frame. |
return_as_pandas | bool | False | Return a pandas.DataFrame instead of polars. |
_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_leaguedashptstats. |
Returns
One row per player-season: season:Int64, player_id:Utf8, player_name:Utf8, team_id:Utf8, position_bucket:Utf8, gp:Int64, min:Float64, drives:Float64, drive_pts:Float64, drive_baseline_rate:Float64, drive_expected:Float64, drive_pts_oe:Float64, drive_pts_oe_per_36:Float64, drive_fta:Float64, rim_pressure:Float64, drive_ast:Float64, drive_tov:Float64, league_id:Utf8. Empty/malformed input returns a zero-row frame with this schema.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_tracking_drive_value
df = wnba_tracking_drive_value(2024)
print(df.sort("drive_pts_oe", descending=True).head())
wnba_tracking_pass_value
wnba_tracking_pass_value(seasons: "'int | str | list'", *, league_id: 'str' = '10', per_mode: 'str' = 'Totals', by_position: 'bool' = True, positions: 'Optional[pl.DataFrame]' = None, fetch_potential_assists: 'bool' = False, max_players: 'int' = 0, return_as_pandas: 'bool' = False, _get_fn: 'Optional[Callable[..., dict]]' = None, _pass_get_fn: 'Optional[Callable[..., dict]]' = None) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA expected-assists / passer value (league_id="10" by-reference shim).
See sportsdataverse.nba.nba_tracking_value.nba_tracking_pass_value
for the full recipe (Passing-measure proxy + optional playerdashptpass
enrichment).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '10' | Defaults to "10" (WNBA); pass "20" here for G-League. |
per_mode | str | 'Totals' | per_mode_simple passed to the fetch (default "Totals"). |
by_position | bool | True | Compute the baseline within role buckets (default); False forces one league-wide bucket. |
positions | Optional[DataFrame] | None | Optional pre-fetched positions frame. |
fetch_potential_assists | bool | False | Enrich the top passers with playerdashptpass potential-assist counts. |
max_players | int | 0 | Cap on per-player enrichment fetches; 0 disables enrichment regardless of fetch_potential_assists. |
return_as_pandas | bool | False | Return a pandas.DataFrame instead of polars. |
_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_leaguedashptstats. |
_pass_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_playerdashptpass. |
Returns
One row per player-season: season:Int64, player_id:Utf8, player_name:Utf8, team_id:Utf8, position_bucket:Utf8, gp:Int64, min:Float64, ast:Float64, passes:Float64, ast_baseline_rate:Float64, ast_expected:Float64, ast_oe:Float64, ast_oe_per_36:Float64, ast_pts_created:Float64, league_id:Utf8. Empty/malformed input returns a zero-row frame with this schema.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_tracking_pass_value
df = wnba_tracking_pass_value(2024)
print(df.sort("ast_oe", descending=True).head())
wnba_tracking_reb_oe
wnba_tracking_reb_oe(seasons: "'int | str | list'", *, league_id: 'str' = '10', per_mode: 'str' = 'Totals', by_position: 'bool' = True, positions: 'Optional[pl.DataFrame]' = None, return_as_pandas: 'bool' = False, _get_fn: 'Optional[Callable[..., dict]]' = None) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA rebounding-over-expected (league_id="10" by-reference shim).
See sportsdataverse.nba.nba_tracking_value.nba_tracking_reb_oe
for the full recipe (contest-difficulty-adjusted expected rebounds,
role-bucket baseline).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '10' | Defaults to "10" (WNBA); pass "20" here for G-League. |
per_mode | str | 'Totals' | per_mode_simple passed to the fetch (default "Totals"). |
by_position | bool | True | Compute the baseline within role buckets (default); False forces one league-wide bucket. |
positions | Optional[DataFrame] | None | Optional pre-fetched positions frame. |
return_as_pandas | bool | False | Return a pandas.DataFrame instead of polars. |
_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_leaguedashptstats. |
Returns
One row per player-season: season:Int64, player_id:Utf8, player_name:Utf8, team_id:Utf8, position_bucket:Utf8, gp:Int64, min:Float64, reb:Float64, reb_chances:Float64, reb_baseline_rate:Float64, reb_expected:Float64, reb_oe:Float64, reb_oe_per_36:Float64, oreb_oe:Float64, dreb_oe:Float64, league_id:Utf8. Empty/malformed input returns a zero-row frame with this schema.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_tracking_reb_oe
df = wnba_tracking_reb_oe(2024)
print(df.sort("reb_oe", descending=True).head())
wnba_tracking_rim_protect_value
wnba_tracking_rim_protect_value(seasons: "'int | str | list'", *, league_id: 'str' = '10', per_mode: 'str' = 'Totals', by_position: 'bool' = True, positions: 'Optional[pl.DataFrame]' = None, source: 'str' = 'leaguedash', max_players: 'int' = 0, return_as_pandas: 'bool' = False, _get_fn: 'Optional[Callable[..., dict]]' = None, _defend_get_fn: 'Optional[Callable[..., dict]]' = None) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA rim-protection / shot-defend points-saved (league_id="10"
by-reference shim).
See sportsdataverse.nba.nba_tracking_value.nba_tracking_rim_protect_value
for the full recipe (bucket-mean defended-rate baseline; optional
playerdashptshotdefend rim-band enrichment).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '10' | Defaults to "10" (WNBA); pass "20" here for G-League. |
per_mode | str | 'Totals' | per_mode_simple passed to the fetch (default "Totals"). |
by_position | bool | True | Compute the baseline within role buckets (default); False forces one league-wide bucket. |
positions | Optional[DataFrame] | None | Optional pre-fetched positions frame. |
source | str | 'leaguedash' | "leaguedash" (default) or "shotdefend". |
max_players | int | 0 | Cap on per-player shotdefend enrichment fetches; ignored unless source="shotdefend". |
return_as_pandas | bool | False | Return a pandas.DataFrame instead of polars. |
_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_leaguedashptstats. |
_defend_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_playerdashptshotdefend. |
Returns
One row per player-season: season:Int64, player_id:Utf8, player_name:Utf8, team_id:Utf8, position_bucket:Utf8, gp:Int64, min:Float64, d_fga:Float64, d_fgm:Float64, d_fg_pct:Float64, normal_fg_pct:Float64, rim_protect_pts_saved:Float64, rim_protect_pts_saved_per_36:Float64, source:Utf8, league_id:Utf8. Empty/malformed input returns a zero-row frame with this schema.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_tracking_rim_protect_value
df = wnba_tracking_rim_protect_value(2024)
print(df.sort("rim_protect_pts_saved", descending=True).head())
wnba_tracking_shot_diet_value
wnba_tracking_shot_diet_value(seasons: "'int | str | list'", *, league_id: 'str' = '10', per_mode: 'str' = 'Totals', by_position: 'bool' = True, positions: 'Optional[pl.DataFrame]' = None, return_as_pandas: 'bool' = False, _get_fn: 'Optional[Callable[..., dict]]' = None) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA catch-&-shoot vs pull-up points-over-expected (league_id="10"
by-reference shim).
See sportsdataverse.nba.nba_tracking_value.nba_tracking_shot_diet_value
for the full recipe.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '10' | Defaults to "10" (WNBA); pass "20" here for G-League. |
per_mode | str | 'Totals' | per_mode_simple passed to each fetch (default "Totals"). |
by_position | bool | True | Compute each measure's baseline within role buckets (default); False forces one league-wide bucket. |
positions | Optional[DataFrame] | None | Optional pre-fetched positions frame. |
return_as_pandas | bool | False | Return a pandas.DataFrame instead of polars. |
_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_leaguedashptstats. |
Returns
One row per player-season: season:Int64, player_id:Utf8, player_name:Utf8, team_id:Utf8, position_bucket:Utf8, cs_fga:Float64, cs_pts:Float64, cs_pts_oe:Float64, pu_fga:Float64, pu_pts:Float64, pu_pts_oe:Float64, shot_diet_delta:Float64, league_id:Utf8. Empty/malformed input returns a zero-row frame with this schema.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_tracking_shot_diet_value
df = wnba_tracking_shot_diet_value(2024)
print(df.sort("cs_pts_oe", descending=True).head())
wnba_tracking_touch_value
wnba_tracking_touch_value(seasons: "'int | str | list'", *, league_id: 'str' = '10', per_mode: 'str' = 'Totals', by_position: 'bool' = True, positions: 'Optional[pl.DataFrame]' = None, return_as_pandas: 'bool' = False, _get_fn: 'Optional[Callable[..., dict]]' = None) -> "'Union[pl.DataFrame, pd.DataFrame]'"
WNBA touch / possession-time value (league_id="10" by-reference shim).
See sportsdataverse.nba.nba_tracking_value.nba_tracking_touch_value
for the full recipe.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '10' | Defaults to "10" (WNBA); pass "20" here for G-League. |
per_mode | str | 'Totals' | per_mode_simple passed to the fetch (default "Totals"). |
by_position | bool | True | Compute the baseline within role buckets (default); False forces one league-wide bucket. |
positions | Optional[DataFrame] | None | Optional pre-fetched positions frame. |
return_as_pandas | bool | False | Return a pandas.DataFrame instead of polars. |
_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_leaguedashptstats. |
Returns
One row per player-season: season:Int64, player_id:Utf8, player_name:Utf8, team_id:Utf8, position_bucket:Utf8, gp:Int64, min:Float64, touches:Float64, pts:Float64, touch_baseline_rate:Float64, touch_expected:Float64, pts_per_touch_oe:Float64, time_of_poss:Float64, time_of_poss_eff:Float64, league_id:Utf8. Empty/malformed input returns a zero-row frame with this schema.
No returns table is published for this function: no capture: it reads stats.nba.com (WNBA league id 10), which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.wnba import wnba_tracking_touch_value
df = wnba_tracking_touch_value(2024)
print(df.sort("pts_per_touch_oe", descending=True).head())
zone_value_map
zone_value_map(scored_shots: 'pl.DataFrame', *, return_as_pandas: 'bool' = False) -> "'Union[pl.DataFrame, pd.DataFrame]'"
Per-player per-zone value map: points and expected points per shot.
Collapses shot_zone_basic to a canonical zone via ZONE_COLLAPSE
(the two corner-3 zones merge) and aggregates realized vs expected points
per shot in each zone.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
scored_shots | DataFrame | score_shot_xpoints output (needs player_id, shot_zone_basic, shot_made_flag, actual_points, xpoints). | |
return_as_pandas | bool | False | Return a pandas DataFrame instead of polars. |
Returns
One row per (player_id, zone): player_id:Int64, zone:Utf8, att:Int64, makes:Int64, pts:Float64, pps:Float64, xpps:Float64, pps_above_expected:Float64 (pps = points per shot, xpps = expected). Empty input returns the zero-row schema.
No returns table is published for this function: no capture: its input is the shots frame of wnba_shot_value, which reads stats.nba.com shotchartdetail; that host answers HTTP 403 to the datacenter IP the docs are built on.
Example
from sportsdataverse.nba.nba_shot_value import score_shot_xpoints, zone_value_map
zmap = zone_value_map(score_shot_xpoints(shots, league_avgs))
# Pipeline next step (one line)
zmap.filter(pl.col("zone") == "corner_3").sort("pps_above_expected", descending=True)