Chapter 38 Intermediate ~50 min read

Four Factors Analysis

Deep dive into Dean Oliver's Four Factors framework for understanding team performance.

The Four Factors Framework

Dean Oliver's Four Factors represent the most influential analytical framework in basketball history. By identifying the key determinants of team success—effective field goal percentage, turnover rate, offensive/defensive rebounding rate, and free throw rate—Oliver provided a structure for understanding what actually drives winning basketball.

Factor Weights and Importance

Oliver's original research suggested approximate weights: eFG% matters most (~40% of variance), followed by turnover rate (~25%), rebounding rate (~20%), and free throw rate (~15%). These weights vary somewhat by sample and era, but shooting efficiency consistently emerges as the most important factor.

def calculate_four_factors(team_stats):
    """Calculate Dean Oliver's Four Factors"""
    efg_pct = (team_stats['FGM'] + 0.5 * team_stats['FG3M']) / team_stats['FGA']

    tov_pct = team_stats['TOV'] / (team_stats['FGA'] + 0.44 * team_stats['FTA'] + team_stats['TOV'])

    orb_pct = team_stats['OREB'] / (team_stats['OREB'] + team_stats['OPP_DREB'])

    ft_rate = team_stats['FTM'] / team_stats['FGA']

    return {
        'eFG_PCT': round(efg_pct * 100, 1),
        'TOV_PCT': round(tov_pct * 100, 1),
        'ORB_PCT': round(orb_pct * 100, 1),
        'FT_RATE': round(ft_rate * 100, 1)
    }

Practical Application

Four Factors analysis enables diagnostic evaluation of team performance. A team struggling offensively can examine which factors are below average to identify improvement areas. A team overperforming expectations might be unsustainably excellent in one factor that will regress. The framework provides actionable structure for performance analysis.

Offensive vs. Defensive Factors

Teams typically have different profiles on offense and defense. A team might emphasize three-point shooting on offense while defending the rim on defense. Comparing factor profiles across phases reveals strategic identity and helps predict how teams will match up against specific opponents.

Implementation in R

# Four Factors analysis and visualization
library(tidyverse)
library(ggplot2)

analyze_four_factors <- function(team_stats) {
  team_stats %>%
    mutate(
      # Calculate all four factors
      efg_pct = (fgm + 0.5 * fg3m) / fga,
      tov_pct = tov / (fga + 0.44 * fta + tov),
      orb_pct = oreb / (oreb + opp_dreb),
      ft_rate = ftm / fga,

      # Defensive four factors
      opp_efg_pct = (opp_fgm + 0.5 * opp_fg3m) / opp_fga,
      opp_tov_pct = opp_tov / (opp_fga + 0.44 * opp_fta + opp_tov),
      drb_pct = dreb / (dreb + opp_oreb),
      opp_ft_rate = opp_ftm / opp_fga,

      # Net factors
      net_efg = efg_pct - opp_efg_pct,
      net_tov = opp_tov_pct - tov_pct,
      net_reb = orb_pct - (1 - drb_pct),
      net_ft = ft_rate - opp_ft_rate
    )
}

team_stats <- read_csv("team_stats.csv")
four_factors <- analyze_four_factors(team_stats)

# Visualize four factors
four_factors_long <- four_factors %>%
  select(team_name, net_efg, net_tov, net_reb, net_ft) %>%
  pivot_longer(-team_name, names_to = "factor", values_to = "value")

ggplot(four_factors_long, aes(x = reorder(team_name, -value),
                               y = value, fill = factor)) +
  geom_bar(stat = "identity", position = "dodge") +
  coord_flip() +
  labs(title = "Net Four Factors by Team") +
  theme_minimal()

Implementation in R

# Four Factors analysis and visualization
library(tidyverse)
library(ggplot2)

analyze_four_factors <- function(team_stats) {
  team_stats %>%
    mutate(
      # Calculate all four factors
      efg_pct = (fgm + 0.5 * fg3m) / fga,
      tov_pct = tov / (fga + 0.44 * fta + tov),
      orb_pct = oreb / (oreb + opp_dreb),
      ft_rate = ftm / fga,

      # Defensive four factors
      opp_efg_pct = (opp_fgm + 0.5 * opp_fg3m) / opp_fga,
      opp_tov_pct = opp_tov / (opp_fga + 0.44 * opp_fta + opp_tov),
      drb_pct = dreb / (dreb + opp_oreb),
      opp_ft_rate = opp_ftm / opp_fga,

      # Net factors
      net_efg = efg_pct - opp_efg_pct,
      net_tov = opp_tov_pct - tov_pct,
      net_reb = orb_pct - (1 - drb_pct),
      net_ft = ft_rate - opp_ft_rate
    )
}

team_stats <- read_csv("team_stats.csv")
four_factors <- analyze_four_factors(team_stats)

# Visualize four factors
four_factors_long <- four_factors %>%
  select(team_name, net_efg, net_tov, net_reb, net_ft) %>%
  pivot_longer(-team_name, names_to = "factor", values_to = "value")

ggplot(four_factors_long, aes(x = reorder(team_name, -value),
                               y = value, fill = factor)) +
  geom_bar(stat = "identity", position = "dodge") +
  coord_flip() +
  labs(title = "Net Four Factors by Team") +
  theme_minimal()
Chapter Summary

You've completed Chapter 38: Four Factors Analysis.