Field Goal and Free Throw Percentages

Beginner 10 min read 0 views Nov 27, 2025
# Shooting Percentages Shooting percentages are fundamental efficiency metrics in basketball that measure a player's accuracy from different areas of the court. The three primary shooting percentages are Field Goal Percentage (FG%), Three-Point Percentage (3P%), and Free Throw Percentage (FT%). ## Field Goal Percentage (FG%) ### Calculation Field Goal Percentage measures the ratio of successful field goal attempts to total field goal attempts: ``` FG% = (Field Goals Made / Field Goals Attempted) × 100 ``` **Example:** - Player makes 450 field goals out of 900 attempts - FG% = (450 / 900) × 100 = 50.0% ### League Averages and Benchmarks **NBA League Averages (2023-24 season):** - League average FG%: ~46-47% - Center position: ~55-58% (highest due to proximity to basket) - Guard positions: ~43-46% **Performance Tiers:** - Elite: 55%+ (typically centers and efficient scorers) - Very Good: 50-55% (high-efficiency players) - Above Average: 47-50% - Average: 44-47% - Below Average: <44% **Notable Context:** - Centers like Rudy Gobert and Jarrett Allen often exceed 65% due to dunks and layups - Guards rarely exceed 50% due to longer-distance shots - Era matters: 1980s-90s averages were lower (~47%) vs modern analytics era (~48%) ## Three-Point Percentage (3P%) ### Calculation Three-Point Percentage measures accuracy from beyond the three-point arc: ``` 3P% = (Three-Pointers Made / Three-Pointers Attempted) × 100 ``` **Example:** - Player makes 180 three-pointers out of 480 attempts - 3P% = (180 / 480) × 100 = 37.5% ### League Averages and Benchmarks **NBA League Averages (2023-24 season):** - League average 3P%: ~36-37% - High-volume shooters (6+ attempts/game): ~37-38% - Low-volume shooters (<3 attempts/game): ~35-36% **Performance Tiers:** - Elite: 40%+ (top-tier shooters) - Very Good: 38-40% - Above Average: 36-38% - Average: 34-36% - Below Average: <34% **Historical Context:** - 1980s: ~28% league average (three-point line introduced 1979-80) - 1990s: ~35% league average - 2000s: ~35-36% - 2010s-present: ~36-37% (with increased volume) **Notable Shooters:** - Steve Kerr: 45.4% career (all-time leader, min. 250 makes) - Stephen Curry: ~43% career on high volume - Seth Curry: ~44% career ## Free Throw Percentage (FT%) ### Calculation Free Throw Percentage measures accuracy from the free throw line: ``` FT% = (Free Throws Made / Free Throws Attempted) × 100 ``` **Example:** - Player makes 340 free throws out of 400 attempts - FT% = (340 / 400) × 100 = 85.0% ### League Averages and Benchmarks **NBA League Averages:** - League average FT%: ~77-78% - Guards: ~80-82% - Forwards: ~75-78% - Centers: ~70-73% **Performance Tiers:** - Elite: 90%+ (elite free throw shooters) - Very Good: 85-90% - Above Average: 80-85% - Average: 75-80% - Below Average: 70-75% - Poor: <70% **Historical Excellence:** - Stephen Curry: ~91% career - Steve Nash: 90.4% career - Mark Price: 90.4% career - Wilt Chamberlain: 51.1% career (historically poor for a star) ## Code Examples ### Python: Calculate Shooting Percentages ```python import pandas as pd import numpy as np def calculate_shooting_percentages(df): """ Calculate FG%, 3P%, and FT% from basketball statistics. Parameters: df (DataFrame): DataFrame with columns FGM, FGA, TPM, TPA, FTM, FTA Returns: DataFrame: Original data with added percentage columns """ # Avoid division by zero df['FG%'] = np.where(df['FGA'] > 0, (df['FGM'] / df['FGA']) * 100, 0) df['3P%'] = np.where(df['TPA'] > 0, (df['TPM'] / df['TPA']) * 100, 0) df['FT%'] = np.where(df['FTA'] > 0, (df['FTM'] / df['FTA']) * 100, 0) return df # Example usage player_stats = pd.DataFrame({ 'Player': ['Player A', 'Player B', 'Player C'], 'FGM': [450, 380, 520], 'FGA': [900, 850, 1000], 'TPM': [180, 95, 45], 'TPA': [480, 280, 125], 'FTM': [340, 280, 420], 'FTA': [400, 350, 580] }) player_stats = calculate_shooting_percentages(player_stats) print(player_stats[['Player', 'FG%', '3P%', 'FT%']].round(1)) ``` ### Python: Analyze Shooting Efficiency ```python import matplotlib.pyplot as plt import seaborn as sns def categorize_shooting(fg_pct, three_pct, ft_pct): """Categorize shooting performance.""" categories = { 'FG%': 'Elite' if fg_pct >= 55 else 'Very Good' if fg_pct >= 50 else 'Above Avg' if fg_pct >= 47 else 'Average' if fg_pct >= 44 else 'Below Avg', '3P%': 'Elite' if three_pct >= 40 else 'Very Good' if three_pct >= 38 else 'Above Avg' if three_pct >= 36 else 'Average' if three_pct >= 34 else 'Below Avg', 'FT%': 'Elite' if ft_pct >= 90 else 'Very Good' if ft_pct >= 85 else 'Above Avg' if ft_pct >= 80 else 'Average' if ft_pct >= 75 else 'Below Avg' } return categories # Example: Visualize shooting percentages def plot_shooting_comparison(df): """Create visualization comparing shooting percentages.""" fig, axes = plt.subplots(1, 3, figsize=(15, 5)) # FG% distribution axes[0].hist(df['FG%'], bins=20, edgecolor='black', alpha=0.7) axes[0].axvline(df['FG%'].mean(), color='red', linestyle='--', label=f'Mean: {df["FG%"].mean():.1f}%') axes[0].set_xlabel('Field Goal %') axes[0].set_ylabel('Frequency') axes[0].set_title('FG% Distribution') axes[0].legend() # 3P% distribution axes[1].hist(df['3P%'], bins=20, edgecolor='black', alpha=0.7, color='orange') axes[1].axvline(df['3P%'].mean(), color='red', linestyle='--', label=f'Mean: {df["3P%"].mean():.1f}%') axes[1].set_xlabel('Three-Point %') axes[1].set_ylabel('Frequency') axes[1].set_title('3P% Distribution') axes[1].legend() # FT% distribution axes[2].hist(df['FT%'], bins=20, edgecolor='black', alpha=0.7, color='green') axes[2].axvline(df['FT%'].mean(), color='red', linestyle='--', label=f'Mean: {df["FT%"].mean():.1f}%') axes[2].set_xlabel('Free Throw %') axes[2].set_ylabel('Frequency') axes[2].set_title('FT% Distribution') axes[2].legend() plt.tight_layout() plt.show() # Example usage # plot_shooting_comparison(player_stats) ``` ### Python: Advanced Analysis with Context ```python def calculate_true_shooting_context(df): """ Calculate shooting percentages with volume context. High volume on good percentages is more valuable. """ # Add volume tiers df['3PA_per_game'] = df['TPA'] / df['Games'] df['Volume_Tier'] = pd.cut(df['3PA_per_game'], bins=[0, 3, 6, 10, 100], labels=['Low', 'Medium', 'High', 'Very High']) # Calculate percentages df = calculate_shooting_percentages(df) # Weighted efficiency score (considers volume) df['Shooting_Score'] = ( df['FG%'] * 0.4 + # FG% weighted 40% df['3P%'] * 0.35 + # 3P% weighted 35% df['FT%'] * 0.25 # FT% weighted 25% ) return df ``` ### R: Calculate and Visualize Shooting Percentages ```r library(dplyr) library(ggplot2) library(tidyr) # Calculate shooting percentages calculate_shooting_pct <- function(df) { df %>% mutate( FG_pct = ifelse(FGA > 0, (FGM / FGA) * 100, 0), TP_pct = ifelse(TPA > 0, (TPM / TPA) * 100, 0), FT_pct = ifelse(FTA > 0, (FTM / FTA) * 100, 0) ) } # Example data player_stats <- data.frame( Player = c("Player A", "Player B", "Player C"), FGM = c(450, 380, 520), FGA = c(900, 850, 1000), TPM = c(180, 95, 45), TPA = c(480, 280, 125), FTM = c(340, 280, 420), FTA = c(400, 350, 580) ) # Calculate percentages player_stats <- calculate_shooting_pct(player_stats) # Print results player_stats %>% select(Player, FG_pct, TP_pct, FT_pct) %>% mutate(across(where(is.numeric), round, 1)) # Visualize shooting percentages shooting_long <- player_stats %>% select(Player, FG_pct, TP_pct, FT_pct) %>% pivot_longer(cols = c(FG_pct, TP_pct, FT_pct), names_to = "Shot_Type", values_to = "Percentage") ggplot(shooting_long, aes(x = Player, y = Percentage, fill = Shot_Type)) + geom_bar(stat = "identity", position = "dodge") + geom_hline(yintercept = c(47, 37, 77), linetype = "dashed", color = c("red", "blue", "green")) + labs(title = "Player Shooting Percentages Comparison", subtitle = "Dashed lines represent league averages", y = "Percentage (%)", fill = "Shot Type") + scale_fill_manual(values = c("FG_pct" = "#E41A1C", "TP_pct" = "#377EB8", "FT_pct" = "#4DAF4A"), labels = c("FG%", "3P%", "FT%")) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5, face = "bold"), plot.subtitle = element_text(hjust = 0.5)) ``` ### R: Statistical Analysis of Shooting Trends ```r library(broom) # Analyze shooting percentage trends over time analyze_shooting_trends <- function(df) { # Linear regression for each shooting type fg_model <- lm(FG_pct ~ Season, data = df) tp_model <- lm(TP_pct ~ Season, data = df) ft_model <- lm(FT_pct ~ Season, data = df) # Get tidy results results <- bind_rows( tidy(fg_model) %>% mutate(Type = "FG%"), tidy(tp_model) %>% mutate(Type = "3P%"), tidy(ft_model) %>% mutate(Type = "FT%") ) return(results) } # Categorize shooting performance categorize_shooter <- function(fg_pct, tp_pct, ft_pct) { tibble( FG_Category = case_when( fg_pct >= 55 ~ "Elite", fg_pct >= 50 ~ "Very Good", fg_pct >= 47 ~ "Above Average", fg_pct >= 44 ~ "Average", TRUE ~ "Below Average" ), TP_Category = case_when( tp_pct >= 40 ~ "Elite", tp_pct >= 38 ~ "Very Good", tp_pct >= 36 ~ "Above Average", tp_pct >= 34 ~ "Average", TRUE ~ "Below Average" ), FT_Category = case_when( ft_pct >= 90 ~ "Elite", ft_pct >= 85 ~ "Very Good", ft_pct >= 80 ~ "Above Average", ft_pct >= 75 ~ "Average", TRUE ~ "Below Average" ) ) } ``` ## Limitations and Considerations ### 1. Volume Context Missing **The Problem:** Shooting percentages don't account for volume. A player shooting 50% on 5 attempts per game is different from 50% on 20 attempts per game. **Example:** - Player A: 2/4 FG per game (50%) - Limited sample, fewer defensive pressures - Player B: 10/20 FG per game (50%) - High volume, faces more defensive attention **Solution:** Always consider attempts alongside percentages. Use metrics like True Shooting Percentage (TS%) for better context. ### 2. Shot Difficulty Not Captured **The Problem:** Not all shots are equal. A center dunking (65% FG%) faces easier shots than a guard taking contested jumpers (45% FG%). **Factors Affecting Difficulty:** - Distance from basket - Defender proximity - Shot clock time remaining - Game situation (late clock, end of game) - Play type (catch-and-shoot vs off-the-dribble) **Example:** - Stephen Curry: 47% FG% on high-difficulty, contested threes - Rudy Gobert: 67% FG% on dunks and layups - Gobert's percentage is higher but Curry's shots create more value ### 3. Position and Role Bias **The Problem:** Different positions have vastly different shooting percentage expectations. **Position Benchmarks:** - Centers: 55-60% FG% (close to basket) - Power Forwards: 48-53% FG% - Small Forwards: 45-50% FG% - Shooting Guards: 44-48% FG% - Point Guards: 43-47% FG% **Solution:** Compare players to positional averages, not league-wide averages. ### 4. Sample Size Issues **The Problem:** Small sample sizes create misleading percentages, especially for three-point shooting. **Example:** - Early season: Player goes 8/15 from three (53.3%) - Full season: Player regresses to 120/320 (37.5%) **Guidelines:** - Minimum 100 attempts for reliable 3P% - Minimum 200 attempts for reliable FG% - Minimum 50 attempts for reliable FT% - Use confidence intervals for small samples ### 5. Era and Pace Adjustments **The Problem:** League-wide shooting percentages have changed over time due to rule changes, defensive schemes, and playing style. **Historical Context:** - 1970s-80s: More physical defense, lower percentages - 1990s-2000s: Hand-checking banned (1994), slightly higher percentages - 2010s-present: Analytics revolution, more efficient shot selection **Solution:** Compare to era-adjusted averages, not all-time averages. ### 6. Game Context Ignored **The Problem:** Percentages don't show when shots are taken (garbage time vs clutch moments). **Clutch Shooting:** - Some players shoot better/worse in high-pressure situations - 4th quarter and overtime percentages often differ from overall - Playoff percentages typically drop 2-3% due to defensive intensity ### 7. Two-Point vs Three-Point Mix **The Problem:** FG% doesn't distinguish between twos and threes. A player shooting 33% from three (0.99 points per attempt) has the same FG% as someone shooting 33% from two (0.66 points per attempt). **Example:** - Player A: 45% FG% (all twos) = 0.90 points per attempt - Player B: 45% FG% (all threes) = 1.35 points per attempt - Player B is far more efficient despite identical FG% **Solution:** Use True Shooting Percentage (TS%) or Effective Field Goal Percentage (eFG%). ### 8. Free Throw Context **The Problem:** FT% doesn't show when free throws are taken or how players are fouled. **Considerations:** - And-one free throws (after made FG) vs shooting fouls - Intentional fouls (hack-a-Shaq strategy) - Technical and flagrant free throws - Fatigue effects (late-game free throws) ### 9. Regression to the Mean **The Problem:** Extreme shooting percentages (very high or low) tend to regress toward career averages over time. **Example:** - Hot streak: 55% from three over 10 games - Expected: Regression toward 37% career average - Don't overreact to short-term shooting fluctuations ### 10. Defensive Impact Not Measured **The Problem:** Shooting percentages are offensive metrics only. A poor shooter who plays elite defense can still be valuable. **Example:** - Ben Simmons: Poor FT% (60%) but elite defender - Trae Young: Excellent shooting but defensive liability - Raw shooting percentages don't capture overall player value ## Best Practices for Using Shooting Percentages 1. **Always Include Volume:** Report attempts alongside percentages 2. **Use Sample Size Thresholds:** Don't overweight small samples 3. **Compare to Position:** Use positional benchmarks, not league-wide 4. **Consider Era:** Adjust for historical context 5. **Combine with Advanced Metrics:** Use TS%, eFG%, and other efficiency stats 6. **Account for Shot Quality:** Factor in shot difficulty when possible 7. **Watch for Trends:** Look at multi-year patterns, not single seasons 8. **Context Matters:** Consider game situations, defensive schemes, and roles ## Summary Shooting percentages are essential basketball metrics, but they require context: - **FG%:** Useful but doesn't distinguish shot value (twos vs threes) - **3P%:** Critical in modern NBA; 37% is average, 40%+ is elite - **FT%:** Most stable metric; 80%+ expected for guards, 70%+ for bigs **Key Takeaways:** - Volume matters as much as percentage - Position and role create different expectations - Combine with advanced metrics (TS%, eFG%) for complete picture - Sample size is crucial for reliability - Shot difficulty varies dramatically by player and role For comprehensive player evaluation, use shooting percentages as one component alongside advanced efficiency metrics, defensive statistics, and contextual factors.

Discussion

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