Traditional Stats Foundation

Beginner 10 min read 0 views Nov 27, 2025
# Traditional Stats Foundation ## Introduction Box score statistics are the fundamental building blocks of basketball analysis. This guide covers traditional stats, their calculation, and interpretation. ## Core Box Score Metrics ### Counting Stats - **Points (PTS)** - Total points scored - **Rebounds (REB)** - Total rebounds (offensive + defensive) - **Assists (AST)** - Passes leading to made field goals - **Steals (STL)** - Defensive deflections resulting in possession - **Blocks (BLK)** - Shots blocked - **Turnovers (TOV)** - Lost possessions ## Python Implementation ```python import pandas as pd import numpy as np class BoxScoreAnalyzer: def __init__(self, box_score_data): """Initialize with box score DataFrame""" self.data = box_score_data def calculate_advanced_metrics(self): """Calculate advanced metrics from traditional box score""" df = self.data.copy() # True Shooting Percentage df['TS%'] = (df['PTS'] / (2 * (df['FGA'] + 0.44 * df['FTA']))) * 100 # Effective Field Goal Percentage df['eFG%'] = ((df['FGM'] + 0.5 * df['3PM']) / df['FGA']) * 100 # Usage Rate (simplified version) if 'MIN' in df.columns and 'TEAM_MIN' in df.columns: df['USG%'] = ((df['FGA'] + 0.44 * df['FTA'] + df['TOV']) * (df['TEAM_MIN'] / 5) / (df['MIN'] * (df['TEAM_FGA'] + 0.44 * df['TEAM_FTA'] + df['TEAM_TOV']))) * 100 # Assist Ratio df['AST_RATIO'] = (df['AST'] / df['FGA']) * 100 # Rebound Percentage (simplified) df['REB%'] = (df['REB'] / df['MIN']) * 48 return df def calculate_four_factors(self, team_stats): """Calculate Dean Oliver's Four Factors""" factors = {} # 1. Shooting (eFG%) factors['eFG%'] = ((team_stats['FGM'] + 0.5 * team_stats['3PM']) / team_stats['FGA']) * 100 # 2. Turnovers (TOV%) factors['TOV%'] = (team_stats['TOV'] / (team_stats['FGA'] + 0.44 * team_stats['FTA'] + team_stats['TOV'])) * 100 # 3. Rebounding (ORB%) if 'OPP_DRB' in team_stats: factors['ORB%'] = (team_stats['ORB'] / (team_stats['ORB'] + team_stats['OPP_DRB'])) * 100 # 4. Free Throws (FT Rate) factors['FT_RATE'] = team_stats['FTA'] / team_stats['FGA'] return factors def calculate_player_efficiency_rating(self, player_stats, team_stats, league_stats): """Calculate Player Efficiency Rating (PER)""" # Simplified PER calculation factor = (2/3) - (0.5 * (league_stats['AST'] / league_stats['FGM'])) / \ (2 * (league_stats['FGM'] / league_stats['FTM'])) VOP = league_stats['PTS'] / (league_stats['FGA'] - league_stats['ORB'] + league_stats['TOV'] + 0.44 * league_stats['FTA']) DRB_pct = (league_stats['TRB'] - league_stats['ORB']) / league_stats['TRB'] uPER = (1 / player_stats['MIN']) * ( player_stats['3PM'] + (2/3) * player_stats['AST'] + (2 - factor * (team_stats['AST'] / team_stats['FGM'])) * player_stats['FGM'] + (player_stats['FTM'] * 0.5 * (1 + (1 - (team_stats['AST'] / team_stats['FGM'])) + (2/3) * (team_stats['AST'] / team_stats['FGM']))) - VOP * player_stats['TOV'] - VOP * DRB_pct * (player_stats['FGA'] - player_stats['FGM']) - VOP * 0.44 * (0.44 + (0.56 * DRB_pct)) * (player_stats['FTA'] - player_stats['FTM']) + VOP * (1 - DRB_pct) * (player_stats['TRB'] - player_stats['ORB']) + VOP * DRB_pct * player_stats['ORB'] + VOP * player_stats['STL'] + VOP * DRB_pct * player_stats['BLK'] - player_stats['PF'] * ((league_stats['FTM'] / league_stats['PF']) - 0.44 * (league_stats['FTA'] / league_stats['PF']) * VOP) ) return uPER def summarize_game_performance(self, player_id): """Generate performance summary for a player""" player = self.data[self.data['PLAYER_ID'] == player_id].iloc[0] summary = { 'player_name': player['PLAYER_NAME'], 'minutes': player['MIN'], 'points': player['PTS'], 'rebounds': player['REB'], 'assists': player['AST'], 'fg_pct': (player['FGM'] / player['FGA'] * 100) if player['FGA'] > 0 else 0, 'plus_minus': player['+/-'] if '+/-' in player else None } return summary # Usage # analyzer = BoxScoreAnalyzer(box_score_df) # advanced_stats = analyzer.calculate_advanced_metrics() # print(advanced_stats[['PLAYER_NAME', 'PTS', 'TS%', 'eFG%']].head()) ``` ## R Implementation ```r library(dplyr) library(tidyr) calculate_advanced_metrics <- function(box_score_data) { box_score_data %>% mutate( # True Shooting Percentage TS_PCT = (PTS / (2 * (FGA + 0.44 * FTA))) * 100, # Effective Field Goal Percentage eFG_PCT = ((FGM + 0.5 * three_PM) / FGA) * 100, # Assist Ratio AST_RATIO = (AST / FGA) * 100, # Rebound Rate per 48 minutes REB_RATE = (REB / MIN) * 48, # Points per shot attempt PPS = PTS / (FGA + 0.44 * FTA) ) } calculate_four_factors <- function(team_stats) { list( # Shooting eFG_PCT = ((team_stats$FGM + 0.5 * team_stats$three_PM) / team_stats$FGA) * 100, # Turnovers TOV_PCT = (team_stats$TOV / (team_stats$FGA + 0.44 * team_stats$FTA + team_stats$TOV)) * 100, # Rebounding ORB_PCT = if("OPP_DRB" %in% names(team_stats)) { (team_stats$ORB / (team_stats$ORB + team_stats$OPP_DRB)) * 100 } else { NA }, # Free Throws FT_RATE = team_stats$FTA / team_stats$FGA ) } summarize_player_performance <- function(box_score_data, player_id) { player <- box_score_data %>% filter(PLAYER_ID == player_id) if (nrow(player) == 0) { return(NULL) } player <- player[1, ] list( player_name = player$PLAYER_NAME, minutes = player$MIN, points = player$PTS, rebounds = player$REB, assists = player$AST, fg_pct = if(player$FGA > 0) (player$FGM / player$FGA * 100) else 0, plus_minus = if("PLUS_MINUS" %in% names(player)) player$PLUS_MINUS else NA ) } # Usage # advanced_stats <- calculate_advanced_metrics(box_score_df) # four_factors <- calculate_four_factors(team_stats_df) ``` ## Key Efficiency Metrics ### Shooting Efficiency - **FG%** - Field Goal Percentage - **3P%** - Three Point Percentage - **FT%** - Free Throw Percentage - **eFG%** - Effective Field Goal Percentage (accounts for 3PT value) - **TS%** - True Shooting Percentage (accounts for FTs) ### Dean Oliver's Four Factors 1. **Shooting (40%)** - eFG% 2. **Turnovers (25%)** - TOV% 3. **Rebounding (20%)** - ORB%, DRB% 4. **Free Throws (15%)** - FT/FGA ## Per-Minute and Per-Possession Metrics - **Per 36 Minutes** - Standardize counting stats - **Per 100 Possessions** - Pace-adjusted metrics - **Usage Rate** - Percentage of team plays used - **Player Efficiency Rating (PER)** - All-in-one efficiency metric ## Best Practices 1. Always consider pace and minutes played 2. Use rate stats over counting stats for comparisons 3. Context matters (opponent strength, home/away) 4. Combine traditional and advanced metrics 5. Account for position and role

Discussion

Have questions or feedback? Join our community discussion on Discord or GitHub Discussions.