Skip to main content

Overview

Team statistics provide aggregated performance metrics at the team level, including offensive shooting by defender distance, defensive opponent shooting allowed, and shot zone analytics. All data is available for both regular season and playoffs from 2014-2025.

Data Files

Team Shooting

Team offensive shooting by defender distance
  • team_shooting.csv (Regular Season)
  • team_shooting_ps.csv (Playoffs)

Opponent Shooting

Opponent shooting allowed (defensive stats)
  • opp_team_shooting.csv (Regular Season)
  • opp_team_shooting_ps.csv (Playoffs)

Team Shot Zones

Shot distribution by court zones
  • team_shotzone.csv / team_shotzone_ps.csv

Shot Zones vs Opponents

Opponent shot zones allowed
  • team_shotzone_vs.csv / team_shotzone_vs_ps.csv

Schema: Team Shooting

File: team_shooting.csv / team_shooting_ps.csv
Generated by: team_shooting.py
Records: ~5,000+ team-season-shot coverage combinations

Core Fields

TEAM
string
required
Team abbreviation (ATL, BOS, BKN, CHA, CHI, CLE, DAL, DEN, DET, GSW, HOU, IND, LAC, LAL, MEM, MIA, MIL, MIN, NOP, NYK, OKC, ORL, PHI, PHX, POR, SAC, SAS, TOR, UTA, WAS)
TEAMNAME
string
required
Full team name (e.g., “Los Angeles Lakers”, “Golden State Warriors”)
year
integer
required
Season ending year (2014-2025)
shot_coverage
string
required
Defender proximity: very_tight, tight, open, wide_open

Sample Data

TEAM,GP,G,Freq%,FGM,FGA,FG%,eFG%,2FG Freq%,2FGM,2FGA,2FG%,3FG Freq%,3PM,3PA,3P%,shot_coverage,year,TEAMNAME
ATL,81,81,28.5,806,1784,45.2,59.0,9.0,314,564,55.7,19.5,492,1220,40.3,wide_open,2014,Atlanta Hawks
LAC,82,82,26.8,759,1734,43.8,54.4,11.1,390,722,54.0,15.6,369,1012,36.5,wide_open,2014,Los Angeles Clippers

Schema: Opponent Team Shooting

File: opp_team_shooting.csv / opp_team_shooting_ps.csv
Purpose: Track shooting performance allowed by each team’s defense
Fields are identical to team_shooting.csv, but values represent opponent performance against the defense rather than offensive production.
This dataset inverts the perspective:
  • Lower FG% = Better team defense
  • Higher Freq% on contested shots = Effective defensive pressure
  • Compare opp_team_shooting.csv with team_shooting.csv to analyze offensive efficiency vs defensive efficiency

Team Shot Zone Schema

Files:
  • team_shotzone.csv / team_shotzone_vs.csv (Regular Season)
  • team_shotzone_ps.csv / team_shotzone_vs_ps.csv (Playoffs)
team_shotzone.csv = Team offensive zones
team_shotzone_vs.csv = Opponent shot zones allowed (defensive)

Usage Examples

Compare Team Three-Point Shooting on Open Shots

import pandas as pd

df = pd.read_csv('team_shooting.csv')

# 2024 season, open + wide open shots
open_threes = df[
    (df['year'] == 2024) & 
    (df['shot_coverage'].isin(['open', 'wide_open']))
].groupby('TEAM').agg({
    '3PM': 'sum',
    '3PA': 'sum'
}).reset_index()

open_threes['3P%'] = (open_threes['3PM'] / open_threes['3PA'] * 100).round(1)
print(open_threes.sort_values('3P%', ascending=False))

Defensive Analysis: Best Teams at Contesting Shots

import pandas as pd

df = pd.read_csv('opp_team_shooting.csv')

# Compare opponent FG% on contested vs open shots
defense_2024 = df[df['year'] == 2024].pivot_table(
    index='TEAM',
    columns='shot_coverage',
    values='FG%'
).reset_index()

defense_2024['Contest_Impact'] = defense_2024['wide_open'] - defense_2024['very_tight']
print(defense_2024.sort_values('very_tight')[['TEAM', 'very_tight', 'wide_open', 'Contest_Impact']])

Shot Selection Analysis

import pandas as pd

team_off = pd.read_csv('team_shooting.csv')

# Warriors shot selection distribution in 2024
gsw = team_off[(team_off['TEAM'] == 'GSW') & (team_off['year'] == 2024)]

print("Golden State Warriors Shot Distribution 2024:")
for _, row in gsw.iterrows():
    print(f"{row['shot_coverage']:12} - Freq: {row['Freq%']:5.1f}% | 3PT Freq: {row['3FG Freq%']:5.1f}% | eFG%: {row['eFG%']:.1f}")

Offensive vs Defensive Efficiency

import pandas as pd

off = pd.read_csv('team_shooting.csv')
opp = pd.read_csv('opp_team_shooting.csv')

# Calculate net efficiency for each team
off_totals = off[off['year'] == 2024].groupby('TEAM')['eFG%'].mean()
opp_totals = opp[opp['year'] == 2024].groupby('TEAM')['eFG%'].mean()

net_efficiency = pd.DataFrame({
    'Off_eFG%': off_totals,
    'Def_eFG%': opp_totals,
    'Net_eFG%': off_totals - opp_totals
}).sort_values('Net_eFG%', ascending=False)

print("Top 10 Teams by Net eFG% (2024):")
print(net_efficiency.head(10))

Historical Team Names

The Charlotte franchise changed from Charlotte Bobcats to Charlotte Hornets in 2014. Both are represented as CHA in the TEAM column.

Team Abbreviations Reference

AbbreviationTeam Name
ATLAtlanta Hawks
BOSBoston Celtics
BKNBrooklyn Nets
CHACharlotte Hornets (Bobcats pre-2014)
CHIChicago Bulls
CLECleveland Cavaliers
DALDallas Mavericks
DENDenver Nuggets
DETDetroit Pistons
GSWGolden State Warriors
HOUHouston Rockets
INDIndiana Pacers
LACLos Angeles Clippers
LALLos Angeles Lakers
MEMMemphis Grizzlies
MIAMiami Heat
MILMilwaukee Bucks
MINMinnesota Timberwolves
NOPNew Orleans Pelicans
NYKNew York Knicks
OKCOklahoma City Thunder
ORLOrlando Magic
PHIPhiladelphia 76ers
PHXPhoenix Suns
PORPortland Trail Blazers
SACSacramento Kings
SASSan Antonio Spurs
TORToronto Raptors
UTAUtah Jazz
WASWashington Wizards

Data Collection Scripts

team_shooting.py

Scrapes NBA.com API for team shooting by defender distance

team_average_scrape.py

Additional team aggregate statistics

Notes

  • Regular Season: 82 games per team (some seasons 66 games due to lockout)
  • Playoffs: Variable games based on playoff progression
  • All percentage fields on 0-100 scale
  • Data coverage: 2014-2025 seasons

Build docs developers (and LLMs) love