Key Takeaways: Receiving Analytics
One-page reference for Chapter 8 concepts
Core Receiving Metrics
| Metric |
Formula |
Meaning |
| EPA/Target |
Total EPA / Targets |
Efficiency per opportunity |
| Target Share |
Player Targets / Team Targets |
Volume share |
| Catch Rate |
Receptions / Targets |
Catch frequency |
| ADOT |
Total Air Yards / Targets |
Target depth |
| RACR |
Receiving Yards / Air Yards |
Opportunity conversion |
Quick EPA Reference
receiver_stats = (
pbp
.query("pass_attempt == 1")
.groupby('receiver_player_name')
.agg(
targets=('pass_attempt', 'count'),
receptions=('complete_pass', 'sum'),
epa=('epa', 'mean'),
catch_rate=('complete_pass', 'mean')
)
.query("targets >= 50")
)
EPA Interpretation (Receiving)
| EPA/Target |
Interpretation |
| > 0.40 |
Elite |
| 0.20 to 0.40 |
Above average |
| 0.00 to 0.20 |
Average |
| -0.20 to 0.00 |
Below average |
| < -0.20 |
Poor |
Target Share Thresholds
| Target Share |
Role |
| > 25% |
Alpha/WR1 |
| 18-25% |
Strong WR2 |
| 12-18% |
WR3 or TE1 |
| 8-12% |
Rotational |
| < 8% |
Depth |
Air Yards Decomposition
# Air Yards = yards ball travels in air
# YAC = yards gained after catch
# Total Yards = Air Yards (completed) + YAC
air_stats = completions.groupby('receiver_player_name').agg(
air_yards=('air_yards', 'sum'),
yac=('yards_after_catch', 'sum'),
total_yards=('yards_gained', 'sum')
)
RACR Interpretation
| RACR |
Meaning |
| > 1.0 |
Gaining more than targeted (high YAC) |
| = 1.0 |
Perfect conversion |
| < 1.0 |
Not converting opportunities |
Formula: RACR = Receiving Yards / Total Air Yards
Receiver Styles
| Style |
ADOT |
YAC |
Description |
| Field Stretcher |
High |
Low |
Deep threat |
| YAC Monster |
Low |
High |
After-catch specialist |
| Possession |
Medium |
Medium |
Move chains |
| Elite |
High |
High |
Does both |
Situational Filters
# Third down
third_down = passes[passes['down'] == 3]
# Red zone
red_zone = passes[passes['yardline_100'] <= 20]
# Deep targets
deep = passes[passes['air_yards'] >= 20]
Separating Receiver from QB
- Same-QB comparison: Compare receivers with same passer
- Multi-QB analysis: Track receiver across different QBs
- QB-adjusted EPA: Measure vs QB's overall baseline
qb_baseline = passes.groupby('passer_player_name')['epa'].mean()
receiver_over_qb = receiver_epa - qb_baseline
Common Pitfalls
| Pitfall |
Reality |
| Yards = value |
Efficiency matters more |
| High catch rate = elite |
Depends on target difficulty |
| Low ADOT = bad |
Could be YAC specialist |
| Ignore QB quality |
Must account for passer |
Target Quality Indicators
- ADOT: How deep are targets?
- Third down targets: Trusted in key situations?
- Red zone targets: End zone threat?
- Deep target %: Used as downfield threat?
Evaluation Framework
1. Volume (targets, target share)
2. Efficiency (EPA/target, success rate)
3. Style (ADOT, YAC, RACR)
4. Situations (3rd down, red zone, deep)
5. Context (QB quality, scheme)
What Statistics Miss
- Route-running precision
- Release quality
- Contested catch ability
- Blocking contribution
- Play design credit
Preview: Chapter 9
Next: Offensive Line Analytics — evaluating the hardest position group to measure with individual statistics.