Key Takeaways: Team Efficiency Metrics

One-page reference for Chapter 12 concepts


Core Team Metrics

# Team Offensive EPA
off_epa = plays.groupby('posteam')['epa'].mean()

# Team Defensive EPA (lower is better)
def_epa = plays.groupby('defteam')['epa'].mean()

# Net EPA
net_epa = off_epa - def_epa

Net EPA Interpretation

Net EPA Team Quality
> 0.15 Elite
0.08 to 0.15 Very Good
0.00 to 0.08 Above Average
-0.08 to 0.00 Below Average
< -0.08 Poor

Success Rate

# Success = EPA > 0
success_rate = (plays['epa'] > 0).mean()

# By down
first_down_success = plays[plays['down'] == 1]['epa'].apply(lambda x: x > 0).mean()
Down League Avg Good Elite
1st 48% 52%+ 55%+
2nd 42% 46%+ 50%+
3rd 38% 42%+ 46%+

Explosiveness

# Explosive plays
explosive_pass = (pass_plays['yards_gained'] >= 20).mean()
explosive_rush = (rush_plays['yards_gained'] >= 10).mean()

# High EPA rate
high_epa_rate = (plays['epa'] > 1.0).mean()

Success-Explosiveness Quadrants

Quadrant Characteristics
Elite High success + high explosive
Consistent High success, moderate explosive
Explosive Moderate success, high explosive
Struggling Low both

Efficiency vs Wins Correlations

Metric Correlation with Wins
Net EPA/play ~0.75-0.85
Offensive EPA ~0.55-0.65
Defensive EPA ~0.50-0.60
Success Rate ~0.65-0.75
Point Differential ~0.90+

Pass vs Rush Efficiency

pass_epa = passes['epa'].mean()  # Typically ~0.05
rush_epa = rushes['epa'].mean()  # Typically ~-0.03

# Pass advantage
pass_premium = pass_epa - rush_epa  # ~0.05-0.08

League-wide, passing is more efficient than rushing.


Defensive Efficiency

# Pass defense (lower is better)
pass_def_epa = passes.groupby('defteam')['epa'].mean()

# Run defense (lower is better)
run_def_epa = rushes.groupby('defteam')['epa'].mean()

# Success allowed
success_allowed = (plays['epa'] > 0).mean()

Year-to-Year Stability

Metric Stability (r)
Offensive EPA 0.50-0.60
Defensive EPA 0.40-0.50
Pass EPA 0.55-0.65
Rush EPA 0.25-0.35
Success Rate 0.45-0.55

Key: Passing metrics are most stable/predictive.


Composite Rating Formula

# Normalize to 0-100
off_score = normalize(off_epa)
def_score = normalize(-def_epa)  # Invert

# Weighted composite
composite = (
    off_score * 0.35 +
    def_score * 0.35 +
    success_score * 0.15 +
    def_success_score * 0.15
)

Garbage Time Filter

# Remove extreme win probabilities
meaningful_plays = plays[
    (plays['wp'] >= 0.05) &
    (plays['wp'] <= 0.95)
]

Limitations

Limitation Impact
No opponent adjustment Raw EPA favors easy schedules
Ignores situation Context matters
No special teams Missing ~15% of game
Weather effects Not captured
Garbage time Can inflate/deflate

Practical Applications

Use Case Best Metric
Overall quality Net EPA / Composite
Consistency Success Rate
Big play ability Explosive Rate
Future projection Pass EPA (most stable)
Defense evaluation Def EPA + Success Allowed

Key Insights

  1. Net EPA predicts wins better than traditional stats
  2. Passing > Rushing in efficiency league-wide
  3. Success + Explosiveness together identify elite teams
  4. Passing stability > rushing stability for predictions
  5. Filter garbage time for meaningful analysis

Preview: Chapter 13

Next: Pace and Play Calling - optimal play selection and tempo analysis.