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.
# 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
- Net EPA predicts wins better than traditional stats
- Passing > Rushing in efficiency league-wide
- Success + Explosiveness together identify elite teams
- Passing stability > rushing stability for predictions
- Filter garbage time for meaningful analysis
Preview: Chapter 13
Next: Pace and Play Calling - optimal play selection and tempo analysis.