NBA — additional Python functions — Analytics: nba_team–nba_tracking
nba_team_season_rates
nba_team_season_rates(seasons: 'int | list[int]', *, league_id: 'str' = '00', season_type: 'str' = 'regular-season', return_as_pandas: 'bool' = False) -> 'pl.DataFrame | pd.DataFrame'
Season team rates from possessions: ORtg/DRtg/net, pace and the four factors, with splits.
One row per team, season and split (all, home, away, close, clutch).
Clutch is a possession in play with 5:00 or less left (starting there, or starting before 5:00
and ending after it; one that ends at exactly 5:00 is out) in the 4th quarter or an overtime, the
score within 5 as it starts (stats.nba.com's clutch window); a close game is one with a clutch
possession. For the WNBA (league_id="10") through 2005, two 20-minute halves, the regulation
window is the last 5:00 of the 2nd half; overtime counts as above. The full definitions are in
sportsdataverse._common.team_season_rates.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | list[int] | A season or list of seasons, named by the year it ends (2026 is 2025-26). The WNBA season is its calendar year. | |
league_id | str | '00' | "00" NBA or "10" WNBA. |
season_type | str | 'regular-season' | "regular-season" (default), "preseason", "playoffs" or "play-in", matched to the schedule's season_type. |
return_as_pandas | bool | False | Return a pandas frame instead of polars. |
Returns
One row per (season, team_id, split). team_id is the stats.nba.com team id (Int64). games, poss / opp_poss (offensive / defensive possessions) and pts / opp_pts are the split's totals. The twelve rates are off_rtg, def_rtg, net_rtg (per 100 possessions), pace (possessions per 48 minutes, 40 in the WNBA), the four factors efg_pct, tov_pct, orb_pct, ft_rate and the same four against (opp_*), all fractions. Each rate has <m>_rank (1 = best; def_rtg, tov_pct, opp_efg_pct, opp_orb_pct and opp_ft_rate rank low first; pace ranks high first), <m>_pct (the Weibull percentile) and <m>_n (the sample: possessions for the ratings, the clock in regulation games for pace, field-goal attempts for eFG% and FT rate, possessions for turnover rate, rebound chances for ORB%). Ranks are within the season and split, among teams with at least half the most games whose <m>_n reaches the league's ~sportsdataverse._common.rate_gates.TEAM_MIN_N gate (a clutch split reaches none), and null under five teams. Empty input returns that schema with zero rows.
| col_name | type | description |
|---|---|---|
season | Int64 | Season, named by the year it ends (2026 is 2025-26). |
team_id | Int64 | stats.nba.com team id (the 10-digit franchise id). |
split | String | Which possessions the row covers: all; home or away (the team's home or road games; neutral-site games are in neither: the curated nba_neutral_site_games list, plus every game dated inside the 2020 bubble (from the schedule's game_date)); close (every possession of a game that had a clutch possession); clutch (a possession in play with 5:00 or less left (starting there, or starting before 5:00 and ending after it) in the 4th quarter (the 2nd half for league_id='10' through 2005, when the WNBA played two 20-minute halves) or an overtime, the score within 5 as it starts). |
games | Int64 | Games with at least one possession in the split. |
poss | Int64 | Offensive possessions in the split, counted from possession rows. |
opp_poss | Int64 | Defensive possessions in the split (the opponents' offensive possessions). |
pts | Int64 | Points scored on the team's offensive possessions in the split. Counted from each possession's made shots and free throws. |
opp_pts | Int64 | Points allowed on the team's defensive possessions in the split. |
off_rtg | Float64 | Offensive rating: points scored per 100 offensive possessions. |
def_rtg | Float64 | Defensive rating: points allowed per 100 defensive possessions. |
net_rtg | Float64 | Net rating: off_rtg minus def_rtg. |
pace | Float64 | Pace: possessions per 48 minutes (40 with league_id="10", the WNBA), the mean of poss and opp_poss over the game clock those possessions used. |
efg_pct | Float64 | Effective field-goal percentage, (FGM + 0.5 * 3PM) / FGA, as a fraction. |
tov_pct | Float64 | Turnovers per offensive possession, as a fraction. |
orb_pct | Float64 | Offensive rebound rate: offensive rebounds over offensive-rebound chances (own OREB plus the defense's DREB), as a fraction. |
ft_rate | Float64 | Free-throw rate, FTA / FGA. |
opp_efg_pct | Float64 | Opponents' effective field-goal percentage, (FGM + 0.5 * 3PM) / FGA, as a fraction. |
opp_tov_pct | Float64 | Opponents' turnovers per possession (turnovers forced), as a fraction. |
opp_orb_pct | Float64 | Opponents' offensive rebound rate, as a fraction (one minus the team's defensive rebound rate). |
opp_ft_rate | Float64 | Opponents' free-throw rate, FTA / FGA. |
off_rtg_rank | Float64 | Rank of off_rtg within the season and split (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose off_rtg_n is at least 1,300 offensive possessions (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
def_rtg_rank | Float64 | Rank of def_rtg within the season and split (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose def_rtg_n is at least 2,000 defensive possessions (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
net_rtg_rank | Float64 | Rank of net_rtg within the season and split (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose net_rtg_n is at least 2,000 possessions (offense plus defense) (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
pace_rank | Float64 | Rank of pace within the season and split (the highest value ranks 1; pace has no better direction; ties average), among teams that played at least half the most games any team played in the split, whose pace_n is at least 5 games (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
efg_pct_rank | Float64 | Rank of efg_pct within the season and split (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose efg_pct_n is at least 1,200 field-goal attempts (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
tov_pct_rank | Float64 | Rank of tov_pct within the season and split (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose tov_pct_n is at least 1,400 offensive possessions (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
orb_pct_rank | Float64 | Rank of orb_pct within the season and split (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose orb_pct_n is at least 410 offensive-rebound chances (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
ft_rate_rank | Float64 | Rank of ft_rate within the season and split (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose ft_rate_n is at least 1,300 field-goal attempts (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_efg_pct_rank | Float64 | Rank of opp_efg_pct within the season and split (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose opp_efg_pct_n is at least 1,900 opponent field-goal attempts (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_tov_pct_rank | Float64 | Rank of opp_tov_pct within the season and split (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose opp_tov_pct_n is at least 960 defensive possessions (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_orb_pct_rank | Float64 | Rank of opp_orb_pct within the season and split (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose opp_orb_pct_n is at least 1,200 opponent offensive-rebound chances (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_ft_rate_rank | Float64 | Rank of opp_ft_rate within the season and split (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the split, whose opp_ft_rate_n is at least 1,500 opponent field-goal attempts (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
off_rtg_pct | Float64 | Percentile of off_rtg within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
def_rtg_pct | Float64 | Percentile of def_rtg within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
net_rtg_pct | Float64 | Percentile of net_rtg within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
pace_pct | Float64 | Percentile of pace within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
efg_pct_pct | Float64 | Percentile of efg_pct within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
tov_pct_pct | Float64 | Percentile of tov_pct within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
orb_pct_pct | Float64 | Percentile of orb_pct within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
ft_rate_pct | Float64 | Percentile of ft_rate within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_efg_pct_pct | Float64 | Percentile of opp_efg_pct within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_tov_pct_pct | Float64 | Percentile of opp_tov_pct within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_orb_pct_pct | Float64 | Percentile of opp_orb_pct within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_ft_rate_pct | Float64 | Percentile of opp_ft_rate within the season and split among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
off_rtg_n | Int64 | Sample size of off_rtg: the team's offensive possessions in the split. |
def_rtg_n | Int64 | Sample size of def_rtg: the team's defensive possessions in the split. |
net_rtg_n | Int64 | Sample size of net_rtg: the team's offensive plus defensive possessions in the split. |
pace_n | Int64 | Sample size of pace: the game clock the split's possessions used, in regulation games (48 minutes, 40 in the WNBA and college), rounded: a full game counts 1, a clutch split's five-minute windows about 0.1 each. |
efg_pct_n | Int64 | Sample size of efg_pct: the team's field-goal attempts in the split. |
tov_pct_n | Int64 | Sample size of tov_pct: the team's offensive possessions in the split. |
orb_pct_n | Int64 | Sample size of orb_pct: the team's offensive-rebound chances in the split. |
ft_rate_n | Int64 | Sample size of ft_rate: the team's field-goal attempts in the split. |
opp_efg_pct_n | Int64 | Sample size of opp_efg_pct: the opponents' field-goal attempts in the split. |
opp_tov_pct_n | Int64 | Sample size of opp_tov_pct: the team's defensive possessions in the split. |
opp_orb_pct_n | Int64 | Sample size of opp_orb_pct: the opponents' offensive-rebound chances in the split. |
opp_ft_rate_n | Int64 | Sample size of opp_ft_rate: the opponents' field-goal attempts in the split. |
Raises
| Exception | Description |
|---|---|
ValueError | If league_id is not "00" or "10", or season_type is not one of the four above. |
Example
from sportsdataverse.nba.nba_team_season_rates import nba_team_season_rates
rates = nba_team_season_rates(2026)
rates.filter(split="all").sort("net_rtg_rank").head()
# WNBA via ``league_id``
wnba = nba_team_season_rates(2025, league_id="10")
nba_team_shot_zones
nba_team_shot_zones(seasons: 'int | list[int]', *, league_id: 'str' = '00', return_as_pandas: 'bool' = False) -> 'pl.DataFrame | pd.DataFrame'
Season shot profile by zone per team, for and allowed: rim / mid / corner 3 / above-the-break 3.
One row per team and season over the regular season: the team's own attempts and, with an
opp_ prefix, its opponents' attempts against it.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | list[int] | A season or list of seasons, named by the year it ends (2026 is 2025-26). The WNBA season is its calendar year. | |
league_id | str | '00' | "00" NBA or "10" WNBA. |
return_as_pandas | bool | False | Return a pandas frame instead of polars. |
Returns
One row per (season, team_id) (the stats.nba.com team id, Int64) with games and the columns of nba_player_shot_zones for the team and again with an opp_ prefix for its opponents (opp_fga, opp_rim_fg_pct, ...), each rate with <m>_n, <m>_rank and <m>_pct, ranked within the season among teams whose <m>_n reaches the gate and null under five teams. <m>_rank is 1 = highest, except the allowed opp_{z}_fg_pct, where 1 is the lowest (the stingiest defense). Empty input returns that schema with zero rows.
| col_name | type | description |
|---|---|---|
season | Int64 | Season, named by the year it ends (2026 is 2025-26). |
team_id | Int64 | stats.nba.com team id. |
games | Int64 | The team's regular-season games with a field-goal attempt by or against it. |
fga | Int64 | Field-goal attempts by the team (regular-season games). |
fgm | Int64 | Field goals made by the team. |
unlocated_fga | Int64 | Attempts by the team with no real location (the WNBA's 1997-2010 hoop-centre placeholders; 0 elsewhere): counted in fga, in no zone. |
rim_fga | Int64 | Attempts by the team at the rim (the restricted area: shot_distance under 4 ft). |
rim_fgm | Int64 | Makes by the team at the rim (the restricted area: shot_distance under 4 ft). |
rim_ast | Int64 | Assisted makes by the team at the rim (the restricted area: shot_distance under 4 ft). |
mid_fga | Int64 | Attempts by the team in the mid zone (every other two: the paint outside the restricted area and the mid-range). |
mid_fgm | Int64 | Makes by the team in the mid zone (every other two: the paint outside the restricted area and the mid-range). |
mid_ast | Int64 | Assisted makes by the team in the mid zone (every other two: the paint outside the restricted area and the mid-range). |
corner_3_fga | Int64 | Attempts by the team from the corner (a three from the baseline band, y_legacy <= 87.5, below the break). |
corner_3_fgm | Int64 | Makes by the team from the corner (a three from the baseline band, y_legacy <= 87.5, below the break). |
corner_3_ast | Int64 | Assisted makes by the team from the corner (a three from the baseline band, y_legacy <= 87.5, below the break). |
above_break_3_fga | Int64 | Attempts by the team from above the break (every other three). |
above_break_3_fgm | Int64 | Makes by the team from above the break (every other three). |
above_break_3_ast | Int64 | Assisted makes by the team from above the break (every other three). |
opp_fga | Int64 | Allowed: Field-goal attempts by the team's opponents (regular-season games). |
opp_fgm | Int64 | Allowed: Field goals made by the team's opponents. |
opp_unlocated_fga | Int64 | Allowed: Attempts by the team's opponents with no real location (the WNBA's 1997-2010 hoop-centre placeholders; 0 elsewhere): counted in opp_fga, in no zone. |
opp_rim_fga | Int64 | Allowed: Attempts by the team's opponents at the rim (the restricted area: shot_distance under 4 ft). |
opp_rim_fgm | Int64 | Allowed: Makes by the team's opponents at the rim (the restricted area: shot_distance under 4 ft). |
opp_rim_ast | Int64 | Allowed: Assisted makes by the team's opponents at the rim (the restricted area: shot_distance under 4 ft). |
opp_mid_fga | Int64 | Allowed: Attempts by the team's opponents in the mid zone (every other two: the paint outside the restricted area and the mid-range). |
opp_mid_fgm | Int64 | Allowed: Makes by the team's opponents in the mid zone (every other two: the paint outside the restricted area and the mid-range). |
opp_mid_ast | Int64 | Allowed: Assisted makes by the team's opponents in the mid zone (every other two: the paint outside the restricted area and the mid-range). |
opp_corner_3_fga | Int64 | Allowed: Attempts by the team's opponents from the corner (a three from the baseline band, y_legacy <= 87.5, below the break). |
opp_corner_3_fgm | Int64 | Allowed: Makes by the team's opponents from the corner (a three from the baseline band, y_legacy <= 87.5, below the break). |
opp_corner_3_ast | Int64 | Allowed: Assisted makes by the team's opponents from the corner (a three from the baseline band, y_legacy <= 87.5, below the break). |
opp_above_break_3_fga | Int64 | Allowed: Attempts by the team's opponents from above the break (every other three). |
opp_above_break_3_fgm | Int64 | Allowed: Makes by the team's opponents from above the break (every other three). |
opp_above_break_3_ast | Int64 | Allowed: Assisted makes by the team's opponents from above the break (every other three). |
rim_fg_pct | Float64 | rim_fgm / rim_fga; null with no attempt. |
rim_freq | Float64 | rim_fga / (fga - unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
rim_ast_pct | Float64 | Share of rim_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
mid_fg_pct | Float64 | mid_fgm / mid_fga; null with no attempt. |
mid_freq | Float64 | mid_fga / (fga - unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
mid_ast_pct | Float64 | Share of mid_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
corner_3_fg_pct | Float64 | corner_3_fgm / corner_3_fga; null with no attempt. |
corner_3_freq | Float64 | corner_3_fga / (fga - unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
corner_3_ast_pct | Float64 | Share of corner_3_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
above_break_3_fg_pct | Float64 | above_break_3_fgm / above_break_3_fga; null with no attempt. |
above_break_3_freq | Float64 | above_break_3_fga / (fga - unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
above_break_3_ast_pct | Float64 | Share of above_break_3_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
opp_rim_fg_pct | Float64 | Allowed: opp_rim_fgm / opp_rim_fga; null with no attempt. |
opp_rim_freq | Float64 | Allowed: opp_rim_fga / (opp_fga - opp_unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
opp_rim_ast_pct | Float64 | Allowed: Share of opp_rim_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
opp_mid_fg_pct | Float64 | Allowed: opp_mid_fgm / opp_mid_fga; null with no attempt. |
opp_mid_freq | Float64 | Allowed: opp_mid_fga / (opp_fga - opp_unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
opp_mid_ast_pct | Float64 | Allowed: Share of opp_mid_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
opp_corner_3_fg_pct | Float64 | Allowed: opp_corner_3_fgm / opp_corner_3_fga; null with no attempt. |
opp_corner_3_freq | Float64 | Allowed: opp_corner_3_fga / (opp_fga - opp_unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
opp_corner_3_ast_pct | Float64 | Allowed: Share of opp_corner_3_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
opp_above_break_3_fg_pct | Float64 | Allowed: opp_above_break_3_fgm / opp_above_break_3_fga; null with no attempt. |
opp_above_break_3_freq | Float64 | Allowed: opp_above_break_3_fga / (opp_fga - opp_unlocated_fga): the zone's share of the located attempts (the four zones add up to 1); null with none. |
opp_above_break_3_ast_pct | Float64 | Allowed: Share of opp_above_break_3_fgm that were assisted, over the makes (every make's assist is in its description); null with none. |
rim_fg_pct_n | Int64 | Sample size of rim_fg_pct: rim_fga. |
rim_freq_n | Int64 | Sample size of rim_freq: located attempts (fga - unlocated_fga). |
rim_ast_pct_n | Int64 | Sample size of rim_ast_pct: makes in the zone. |
mid_fg_pct_n | Int64 | Sample size of mid_fg_pct: mid_fga. |
mid_freq_n | Int64 | Sample size of mid_freq: located attempts (fga - unlocated_fga). |
mid_ast_pct_n | Int64 | Sample size of mid_ast_pct: makes in the zone. |
corner_3_fg_pct_n | Int64 | Sample size of corner_3_fg_pct: corner_3_fga. |
corner_3_freq_n | Int64 | Sample size of corner_3_freq: located attempts (fga - unlocated_fga). |
corner_3_ast_pct_n | Int64 | Sample size of corner_3_ast_pct: makes in the zone. |
above_break_3_fg_pct_n | Int64 | Sample size of above_break_3_fg_pct: above_break_3_fga. |
above_break_3_freq_n | Int64 | Sample size of above_break_3_freq: located attempts (fga - unlocated_fga). |
above_break_3_ast_pct_n | Int64 | Sample size of above_break_3_ast_pct: makes in the zone. |
opp_rim_fg_pct_n | Int64 | Sample size of opp_rim_fg_pct: opp_rim_fga. |
opp_rim_freq_n | Int64 | Sample size of opp_rim_freq: located attempts (opp_fga - opp_unlocated_fga). |
opp_rim_ast_pct_n | Int64 | Sample size of opp_rim_ast_pct: makes in the zone. |
opp_mid_fg_pct_n | Int64 | Sample size of opp_mid_fg_pct: opp_mid_fga. |
opp_mid_freq_n | Int64 | Sample size of opp_mid_freq: located attempts (opp_fga - opp_unlocated_fga). |
opp_mid_ast_pct_n | Int64 | Sample size of opp_mid_ast_pct: makes in the zone. |
opp_corner_3_fg_pct_n | Int64 | Sample size of opp_corner_3_fg_pct: opp_corner_3_fga. |
opp_corner_3_freq_n | Int64 | Sample size of opp_corner_3_freq: located attempts (opp_fga - opp_unlocated_fga). |
opp_corner_3_ast_pct_n | Int64 | Sample size of opp_corner_3_ast_pct: makes in the zone. |
opp_above_break_3_fg_pct_n | Int64 | Sample size of opp_above_break_3_fg_pct: opp_above_break_3_fga. |
opp_above_break_3_freq_n | Int64 | Sample size of opp_above_break_3_freq: located attempts (opp_fga - opp_unlocated_fga). |
opp_above_break_3_ast_pct_n | Int64 | Sample size of opp_above_break_3_ast_pct: makes in the zone. |
rim_fg_pct_rank | Float64 | Rank of rim_fg_pct within the season (the highest ranks 1; ties average), among teams whose rim_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
rim_freq_rank | Float64 | Rank of rim_freq within the season (the highest ranks 1; ties average), among teams whose rim_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
rim_ast_pct_rank | Float64 | Rank of rim_ast_pct within the season (the highest ranks 1; ties average), among teams whose rim_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
mid_fg_pct_rank | Float64 | Rank of mid_fg_pct within the season (the highest ranks 1; ties average), among teams whose mid_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
mid_freq_rank | Float64 | Rank of mid_freq within the season (the highest ranks 1; ties average), among teams whose mid_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
mid_ast_pct_rank | Float64 | Rank of mid_ast_pct within the season (the highest ranks 1; ties average), among teams whose mid_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
corner_3_fg_pct_rank | Float64 | Rank of corner_3_fg_pct within the season (the highest ranks 1; ties average), among teams whose corner_3_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
corner_3_freq_rank | Float64 | Rank of corner_3_freq within the season (the highest ranks 1; ties average), among teams whose corner_3_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
corner_3_ast_pct_rank | Float64 | Rank of corner_3_ast_pct within the season (the highest ranks 1; ties average), among teams whose corner_3_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
above_break_3_fg_pct_rank | Float64 | Rank of above_break_3_fg_pct within the season (the highest ranks 1; ties average), among teams whose above_break_3_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
above_break_3_freq_rank | Float64 | Rank of above_break_3_freq within the season (the highest ranks 1; ties average), among teams whose above_break_3_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
above_break_3_ast_pct_rank | Float64 | Rank of above_break_3_ast_pct within the season (the highest ranks 1; ties average), among teams whose above_break_3_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_rim_fg_pct_rank | Float64 | Rank of opp_rim_fg_pct within the season (the lowest ranks 1, the stingiest defense; ties average), among teams whose opp_rim_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_rim_freq_rank | Float64 | Rank of opp_rim_freq within the season (the highest ranks 1; ties average), among teams whose opp_rim_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_rim_ast_pct_rank | Float64 | Rank of opp_rim_ast_pct within the season (the highest ranks 1; ties average), among teams whose opp_rim_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_mid_fg_pct_rank | Float64 | Rank of opp_mid_fg_pct within the season (the lowest ranks 1, the stingiest defense; ties average), among teams whose opp_mid_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_mid_freq_rank | Float64 | Rank of opp_mid_freq within the season (the highest ranks 1; ties average), among teams whose opp_mid_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_mid_ast_pct_rank | Float64 | Rank of opp_mid_ast_pct within the season (the highest ranks 1; ties average), among teams whose opp_mid_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_corner_3_fg_pct_rank | Float64 | Rank of opp_corner_3_fg_pct within the season (the lowest ranks 1, the stingiest defense; ties average), among teams whose opp_corner_3_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_corner_3_freq_rank | Float64 | Rank of opp_corner_3_freq within the season (the highest ranks 1; ties average), among teams whose opp_corner_3_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_corner_3_ast_pct_rank | Float64 | Rank of opp_corner_3_ast_pct within the season (the highest ranks 1; ties average), among teams whose opp_corner_3_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_above_break_3_fg_pct_rank | Float64 | Rank of opp_above_break_3_fg_pct within the season (the lowest ranks 1, the stingiest defense; ties average), among teams whose opp_above_break_3_fg_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_above_break_3_freq_rank | Float64 | Rank of opp_above_break_3_freq within the season (the highest ranks 1; ties average), among teams whose opp_above_break_3_freq_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
opp_above_break_3_ast_pct_rank | Float64 | Rank of opp_above_break_3_ast_pct within the season (the highest ranks 1; ties average), among teams whose opp_above_break_3_ast_pct_n reaches the rate's split-half gate (TEAM_MIN_N); null under the gate, for a rate with no gate (never half signal), or with fewer than five teams ranked. |
rim_fg_pct_pct | Float64 | Percentile of rim_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
rim_freq_pct | Float64 | Percentile of rim_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
rim_ast_pct_pct | Float64 | Percentile of rim_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
mid_fg_pct_pct | Float64 | Percentile of mid_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
mid_freq_pct | Float64 | Percentile of mid_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
mid_ast_pct_pct | Float64 | Percentile of mid_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
corner_3_fg_pct_pct | Float64 | Percentile of corner_3_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
corner_3_freq_pct | Float64 | Percentile of corner_3_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
corner_3_ast_pct_pct | Float64 | Percentile of corner_3_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
above_break_3_fg_pct_pct | Float64 | Percentile of above_break_3_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
above_break_3_freq_pct | Float64 | Percentile of above_break_3_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
above_break_3_ast_pct_pct | Float64 | Percentile of above_break_3_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_rim_fg_pct_pct | Float64 | Percentile of opp_rim_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_rim_freq_pct | Float64 | Percentile of opp_rim_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_rim_ast_pct_pct | Float64 | Percentile of opp_rim_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_mid_fg_pct_pct | Float64 | Percentile of opp_mid_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_mid_freq_pct | Float64 | Percentile of opp_mid_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_mid_ast_pct_pct | Float64 | Percentile of opp_mid_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_corner_3_fg_pct_pct | Float64 | Percentile of opp_corner_3_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_corner_3_freq_pct | Float64 | Percentile of opp_corner_3_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_corner_3_ast_pct_pct | Float64 | Percentile of opp_corner_3_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_above_break_3_fg_pct_pct | Float64 | Percentile of opp_above_break_3_fg_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_above_break_3_freq_pct | Float64 | Percentile of opp_above_break_3_freq within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
opp_above_break_3_ast_pct_pct | Float64 | Percentile of opp_above_break_3_ast_pct within the season among the same ranked rows: 100 * (n + 1 - rank) / (n + 1), n the number ranked; null when the rank is null. |
Raises
| Exception | Description |
|---|---|
ValueError | If league_id is not "00" or "10" (checked before any data is loaded). |
Example
from sportsdataverse.nba.nba_shot_zone_profiles import nba_team_shot_zones
teams = nba_team_shot_zones(2025)
teams.sort("opp_rim_freq").select("team_id", "opp_rim_freq", "opp_rim_fg_pct").head()
# WNBA via ``league_id``
wnba = nba_team_shot_zones(2025, league_id="10")
nba_team_strength
nba_team_strength(seasons: 'int | list[int]', *, league_id: 'str' = '00', season_type: 'str' = 'regular-season', return_as_pandas: 'bool' = False) -> 'pl.DataFrame | pd.DataFrame'
Team strength from possessions: adjusted ratings, SOS, SOV, pace and the four factors.
One row per team and season. The adjusted ratings are a ridge regression of points per 100
on each possession on offense, defense and home terms (penalty
~sportsdataverse._common.team_strength.RIDGE_LAMBDA, fit by season-disjoint CV):
points scored / allowed per 100 against an average opponent on a neutral court. SOS is the
mean opponent adj_net_rtg over the team's games, SOV the same over its wins.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | list[int] | A season or list of seasons, named by the year it ends (2026 is 2025-26). The WNBA season is its calendar year. | |
league_id | str | '00' | "00" NBA or "10" WNBA. |
season_type | str | 'regular-season' | "regular-season" (default), "preseason", "playoffs" or "play-in", matched to the schedule's season_type. The ridge, the rates and the games all use it. |
return_as_pandas | bool | False | Return a pandas frame instead of polars. |
Returns
One row per (season, team_id); team_id is the stats.nba.com team id (Int64). games, poss / opp_poss, pts / opp_pts are the season totals from the possessions; wins / losses come from the schedule's final scores. The rated metrics are adj_off_rtg, adj_def_rtg, adj_net_rtg, sos, sov and the BB-D3 rates (off_rtg, def_rtg, net_rtg, pace, the four factors and the four against). Each has <m>_rank (1 = best; adj_def_rtg, def_rtg, tov_pct and the opponent shooting, rebounding and free-throw rates rank low first; sos ranks the hardest schedule first), <m>_pct (the Weibull percentile) and <m>_n (possessions for the ratings, completed games against a rated opponent for SOS, the clock in regulation games for pace, wins over a rated opponent for SOV). Ranks are within the season, among teams with at least half the most games, the BB-D3 rates' also behind their ~sportsdataverse._common.rate_gates.TEAM_MIN_N gate, and null under five teams. Empty input returns that schema with zero rows.
| col_name | type | description |
|---|---|---|
season | Int64 | Season, named by the year it ends (2026 is 2025-26). |
team_id | Int64 | stats.nba.com team id (the 10-digit franchise id). |
games | Int64 | Games with at least one possession in the season (from the possession release). |
wins | Int64 | Wins in the season type's completed games (the schedule's final scores). |
losses | Int64 | Losses in the season type's completed games. |
poss | Int64 | Offensive possessions in the season, counted from possession rows. |
opp_poss | Int64 | Defensive possessions in the season (the opponents' offensive possessions). |
pts | Int64 | Points scored on the team's offensive possessions in the season. Counted from each possession's made shots and free throws. |
opp_pts | Int64 | Points allowed on the team's defensive possessions in the season. |
adj_off_rtg | Float64 | Adjusted offensive rating: points per 100 possessions against an average defense on a neutral court. The ridge intercept plus the team's offense coefficient (points per 100 on each possession on offense, defense and home terms; penalty RIDGE_LAMBDA). |
adj_def_rtg | Float64 | Adjusted defensive rating: points allowed per 100 possessions against an average offense on a neutral court. The ridge intercept plus the team's defense coefficient; lower is better. |
adj_net_rtg | Float64 | Adjusted net rating: adj_off_rtg minus adj_def_rtg. |
sos | Float64 | Strength of schedule: the mean adj_net_rtg of the opponents of the team's completed games, one weight per game (an opponent met four times counts four times). |
sov | Float64 | Strength of victory: the mean adj_net_rtg of the opponents the team beat, one weight per win; null with no win. |
off_rtg | Float64 | Offensive rating: points scored per 100 offensive possessions. |
def_rtg | Float64 | Defensive rating: points allowed per 100 defensive possessions. |
net_rtg | Float64 | Net rating: off_rtg minus def_rtg. |
pace | Float64 | Pace: possessions per 48 minutes (40 with league_id="10", the WNBA), the mean of poss and opp_poss over the game clock those possessions used. |
efg_pct | Float64 | Effective field-goal percentage, (FGM + 0.5 * 3PM) / FGA, as a fraction. |
tov_pct | Float64 | Turnovers per offensive possession, as a fraction. |
orb_pct | Float64 | Offensive rebound rate: offensive rebounds over offensive-rebound chances (own OREB plus the defense's DREB), as a fraction. |
ft_rate | Float64 | Free-throw rate, FTA / FGA. |
opp_efg_pct | Float64 | Opponents' effective field-goal percentage, (FGM + 0.5 * 3PM) / FGA, as a fraction. |
opp_tov_pct | Float64 | Opponents' turnovers per possession (turnovers forced), as a fraction. |
opp_orb_pct | Float64 | Opponents' offensive rebound rate, as a fraction (one minus the team's defensive rebound rate). |
opp_ft_rate | Float64 | Opponents' free-throw rate, FTA / FGA. |
adj_off_rtg_rank | Float64 | Rank of adj_off_rtg within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season; null for a non-qualifier, a null value, or fewer than five qualifiers. |
adj_def_rtg_rank | Float64 | Rank of adj_def_rtg within the season (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the season; null for a non-qualifier, a null value, or fewer than five qualifiers. |
adj_net_rtg_rank | Float64 | Rank of adj_net_rtg within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season; null for a non-qualifier, a null value, or fewer than five qualifiers. |
sos_rank | Float64 | Rank of sos within the season (the highest value ranks 1; the hardest schedule ranks 1; ties average), among teams that played at least half the most games any team played in the season; null for a non-qualifier, a null value, or fewer than five qualifiers. |
sov_rank | Float64 | Rank of sov within the season (the highest value ranks 1; the strongest wins rank 1; ties average), among teams that played at least half the most games any team played in the season; null for a non-qualifier, a null value, or fewer than five qualifiers. |
off_rtg_rank | Float64 | Rank of off_rtg within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose off_rtg_n is at least 1,300 offensive possessions (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
def_rtg_rank | Float64 | Rank of def_rtg within the season (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose def_rtg_n is at least 2,000 defensive possessions (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
net_rtg_rank | Float64 | Rank of net_rtg within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose net_rtg_n is at least 2,000 possessions (offense plus defense) (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
pace_rank | Float64 | Rank of pace within the season (the highest value ranks 1; pace has no better direction; ties average), among teams that played at least half the most games any team played in the season, whose pace_n is at least 5 games (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
efg_pct_rank | Float64 | Rank of efg_pct within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose efg_pct_n is at least 1,200 field-goal attempts (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
tov_pct_rank | Float64 | Rank of tov_pct within the season (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose tov_pct_n is at least 1,400 offensive possessions (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
orb_pct_rank | Float64 | Rank of orb_pct within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose orb_pct_n is at least 410 offensive-rebound chances (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
ft_rate_rank | Float64 | Rank of ft_rate within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose ft_rate_n is at least 1,300 field-goal attempts (the sample at which the rate is half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_efg_pct_rank | Float64 | Rank of opp_efg_pct within the season (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose opp_efg_pct_n is at least 1,900 opponent field-goal attempts (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_tov_pct_rank | Float64 | Rank of opp_tov_pct within the season (the highest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose opp_tov_pct_n is at least 960 defensive possessions (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_orb_pct_rank | Float64 | Rank of opp_orb_pct within the season (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose opp_orb_pct_n is at least 1,200 opponent offensive-rebound chances (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
opp_ft_rate_rank | Float64 | Rank of opp_ft_rate within the season (the lowest value ranks 1; ties average), among teams that played at least half the most games any team played in the season, whose opp_ft_rate_n is at least 1,500 opponent field-goal attempts (the sample at which the rate was, on the fit seasons, half signal, rate_gates); null for a non-qualifier, a sample under that gate, a null rate, or fewer than five qualifiers. |
adj_off_rtg_pct | Float64 | Percentile of adj_off_rtg within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
adj_def_rtg_pct | Float64 | Percentile of adj_def_rtg within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
adj_net_rtg_pct | Float64 | Percentile of adj_net_rtg within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
sos_pct | Float64 | Percentile of sos within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
sov_pct | Float64 | Percentile of sov within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
off_rtg_pct | Float64 | Percentile of off_rtg within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
def_rtg_pct | Float64 | Percentile of def_rtg within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
net_rtg_pct | Float64 | Percentile of net_rtg within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
pace_pct | Float64 | Percentile of pace within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
efg_pct_pct | Float64 | Percentile of efg_pct within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
tov_pct_pct | Float64 | Percentile of tov_pct within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
orb_pct_pct | Float64 | Percentile of orb_pct within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
ft_rate_pct | Float64 | Percentile of ft_rate within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_efg_pct_pct | Float64 | Percentile of opp_efg_pct within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_tov_pct_pct | Float64 | Percentile of opp_tov_pct within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_orb_pct_pct | Float64 | Percentile of opp_orb_pct within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
opp_ft_rate_pct | Float64 | Percentile of opp_ft_rate within the season among the same qualified teams: 100 * (n + 1 - rank) / (n + 1), n the number ranked, so the best team is under 100 and nobody is 0; null when the rank is null. |
adj_off_rtg_n | Int64 | Sample size of adj_off_rtg: the team's offensive possessions in the season. |
adj_def_rtg_n | Int64 | Sample size of adj_def_rtg: the team's defensive possessions in the season. |
adj_net_rtg_n | Int64 | Sample size of adj_net_rtg: the team's offensive plus defensive possessions in the season. |
sos_n | Int64 | Sample size of sos: the completed games against a rated opponent. |
sov_n | Int64 | Sample size of sov: the wins against a rated opponent. |
off_rtg_n | Int64 | Sample size of off_rtg: the team's offensive possessions in the season. |
def_rtg_n | Int64 | Sample size of def_rtg: the team's defensive possessions in the season. |
net_rtg_n | Int64 | Sample size of net_rtg: the team's offensive plus defensive possessions in the season. |
pace_n | Int64 | Sample size of pace: the game clock the season's possessions used, in regulation games (48 minutes, 40 in the WNBA and college), rounded: about the games played, overtime adding a little. |
efg_pct_n | Int64 | Sample size of efg_pct: the team's field-goal attempts in the season. |
tov_pct_n | Int64 | Sample size of tov_pct: the team's offensive possessions in the season. |
orb_pct_n | Int64 | Sample size of orb_pct: the team's offensive-rebound chances in the season. |
ft_rate_n | Int64 | Sample size of ft_rate: the team's field-goal attempts in the season. |
opp_efg_pct_n | Int64 | Sample size of opp_efg_pct: the opponents' field-goal attempts in the season. |
opp_tov_pct_n | Int64 | Sample size of opp_tov_pct: the team's defensive possessions in the season. |
opp_orb_pct_n | Int64 | Sample size of opp_orb_pct: the opponents' offensive-rebound chances in the season. |
opp_ft_rate_n | Int64 | Sample size of opp_ft_rate: the opponents' field-goal attempts in the season. |
Raises
| Exception | Description |
|---|---|
ValueError | If league_id is not "00" or "10", or season_type is not one of the four above (checked before any data is loaded). |
Example
from sportsdataverse.nba.nba_team_strength import nba_team_strength
strength = nba_team_strength(2026)
strength.sort("adj_net_rtg_rank").select("team_id", "adj_net_rtg", "sos", "sov").head()
# WNBA via ``league_id``
wnba = nba_team_strength(2025, league_id="10")
nba_tracking_drive_value
nba_tracking_drive_value(seasons: "'int | str | list'", *, league_id: 'str' = '00', 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]'"
Drive value over expected + rim-pressure, per player-season.
Fetches the Drives leaguedashptstats measure and computes
drive_pts_oe = drive_pts - drives * bucket_pts_per_drive. rim_pressure
is the z-score of drive_fta / drives within the player's role bucket
(a proxy for foul-drawing pressure independent of scoring efficiency).
drive_ast/drive_tov are passed through unchanged.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '00' | "00" NBA (default), "10" WNBA, "20" 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, which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.nba import nba_tracking_drive_value
df = nba_tracking_drive_value(2024)
print(df.sort("drive_pts_oe", descending=True).head())
nba_tracking_pass_value
nba_tracking_pass_value(seasons: "'int | str | list'", *, league_id: 'str' = '00', 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]'"
Expected-assists / passer value: ast_oe per player-season.
Fetches the Passing leaguedashptstats measure (one call) and computes
ast_oe = ast - passes * bucket_assist_rate. When
fetch_potential_assists=True, also fetches nba_stats_playerdashptpass
for the top-max_players passers (capped, optional -- never a hard
dependency) and recomputes the residual against the richer
potential_assists denominator for that subset; max_players=0
(default) makes exactly one request total. ast_pts_created is passed
through directly from the Passing measure (it is already computed there;
not re-derived).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '00' | "00" NBA (default), "10" WNBA, "20" 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, which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.nba import nba_tracking_pass_value
df = nba_tracking_pass_value(2024)
print(df.sort("ast_oe", descending=True).head())
# With potential-assist enrichment for the top 50 passers
df = nba_tracking_pass_value(2024, fetch_potential_assists=True, max_players=50)
nba_tracking_reb_oe
nba_tracking_reb_oe(seasons: "'int | str | list'", *, league_id: 'str' = '00', 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]'"
Rebounding-over-expected: reb_oe plus OREB/DREB splits, per player-season.
Fetches the Rebounding leaguedashptstats measure, attaches a
guard/wing/big role bucket, and computes
reb_oe = reb - reb_chances * bucket_rate (contest-difficulty-adjusted
when the endpoint carries separate contested/uncontested CHANCE columns;
the live stats.nba.com payload currently does not, so this degrades
gracefully to the plain rate -- see the fixtures README for the finding).
OREB/DREB residuals are computed identically against their own chance
columns. Baselines are recomputed from the same season slice on every
call -- there is no fitted constant or bundled artifact.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season (int ending-year or "YYYY-YY" string) or a list of seasons to concatenate. | |
league_id | str | '00' | "00" NBA (default), "10" WNBA, "20" G-League. |
per_mode | str | 'Totals' | per_mode_simple passed to the fetch (default "Totals"). |
by_position | bool | True | Compute the baseline within guard/wing/big buckets (default). False forces one league-wide bucket. |
positions | Optional[DataFrame] | None | Optional pre-fetched positions frame (see _attach_role_bucket); mostly for injecting a fixture in tests. |
return_as_pandas | bool | False | Return a pandas.DataFrame instead of polars. |
_get_fn | Optional[Callable[..., dict]] | None | Injectable replacement for nba_stats_leaguedashptstats returning the raw payload dict directly -- offline testing hook. |
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, which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.nba import nba_tracking_reb_oe
df = nba_tracking_reb_oe(2024)
print(df.sort("reb_oe", descending=True).head())
# League-wide baseline (no position split)
df_all = nba_tracking_reb_oe(2024, by_position=False)
# Pandas output
df_pd = nba_tracking_reb_oe(2024, return_as_pandas=True)
nba_tracking_rim_protect_value
nba_tracking_rim_protect_value(seasons: "'int | str | list'", *, league_id: 'str' = '00', 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]'"
Rim-protection / shot-defend points-saved over expected, per player-season.
Fetches the Defense leaguedashptstats measure -- which on the live
stats.nba.com payload exposes only rim-band defended shooting
(def_rim_fgm/def_rim_fga/def_rim_fg_pct, no separate overall
figure -- see the fixtures README) -- and computes
rim_protect_pts_saved = (normal_fg_pct - d_fg_pct) * d_fga * 2 where
normal_fg_pct is the bucket-mean defended rate (there is no
shooters'-own-average column on this endpoint, so the bucket mean is the
baseline; this is the same attempts-weighted construction as every other
model, just sign-flipped so a defender who holds shooters BELOW the
bucket mean gets a positive points-saved value).
source="shotdefend" swaps in the Less-Than-6-Ft band from
nba_stats_playerdashptshotdefend for the top-max_players defenders
by attempt volume (capped, optional -- never a hard dependency);
max_players=0 (default) uses the leaguedash figures for everyone.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
seasons | int | str | list | A single season or list of seasons. | |
league_id | str | '00' | "00" NBA (default), "10" WNBA, "20" 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, which answers HTTP 403 to the datacenter IP the docs are built on; the function works from a residential IP.
Example
from sportsdataverse.nba import nba_tracking_rim_protect_value
df = nba_tracking_rim_protect_value(2024)
print(df.sort("rim_protect_pts_saved", descending=True).head())