Key Takeaways: Traditional Football Statistics

Quick Reference Card

Counting Statistics vs. Rate Statistics

Type Purpose Examples When to Use
Counting Volume measurement Yards, TDs, tackles Comparing players with similar opportunities
Rate Efficiency measurement YPC, Comp%, TD% Comparing across different opportunity levels
Per-Game Normalized volume YPG, PPG Comparing across different game counts

Essential Formulas

Passing Statistics

Completion % = (Completions / Attempts) × 100
Yards per Attempt = Passing Yards / Attempts
TD % = (Passing TDs / Attempts) × 100
INT % = (Interceptions / Attempts) × 100
TD-to-INT Ratio = Touchdowns / Interceptions

NFL Passer Rating Formula

def passer_rating(comp_pct, ypa, td_pct, int_pct):
    """
    Calculate NFL-style passer rating.

    Parameters are percentages (e.g., 65.0 for 65%)
    except ypa which is raw yards per attempt.
    """
    a = max(0, min(((comp_pct - 30) / 20), 2.375))
    b = max(0, min(((ypa - 3) / 4), 2.375))
    c = max(0, min((td_pct / 5), 2.375))
    d = max(0, min((2.375 - (int_pct / 4)), 2.375))

    return ((a + b + c + d) / 6) * 100

Rushing Statistics

Yards per Carry = Rushing Yards / Carries
Yards per Game = Total Yards / Games Played
Yards After Contact = Total YAC / Carries

Receiving Statistics

Catch Rate = Receptions / Targets × 100
Yards per Reception = Receiving Yards / Receptions
Yards per Target = Receiving Yards / Targets

Statistical Benchmarks (FBS)

Quarterback Benchmarks

Metric Poor Average Good Elite
Completion % <55% 55-62% 62-68% >68%
Yards/Attempt <6.0 6.0-7.5 7.5-9.0 >9.0
TD % <3% 3-5% 5-7% >7%
INT % >4% 2.5-4% 1.5-2.5% <1.5%
Passer Rating <100 100-130 130-160 >160

Running Back Benchmarks

Metric Poor Average Good Elite
Yards/Carry <3.5 3.5-4.5 4.5-5.5 >5.5
Yards/Game <50 50-80 80-110 >110
10+ Yard Runs % <8% 8-12% 12-16% >16%

Receiver Benchmarks

Metric Poor Average Good Elite
Catch Rate <55% 55-65% 65-72% >72%
Yards/Reception <10 10-13 13-16 >16
Yards/Target <6.0 6.0-8.0 8.0-10.0 >10.0

Team Statistics Reference

Offensive Benchmarks

Metric Poor Average Good Elite
Points/Game <20 20-30 30-40 >40
Yards/Play <5.0 5.0-6.0 6.0-7.0 >7.0
3rd Down % <35% 35-42% 42-50% >50%
Red Zone TD % <50% 50-60% 60-70% >70%

Defensive Benchmarks

Metric Elite Good Average Poor
Points Allowed/Game <17 17-24 24-30 >30
Yards/Play Allowed <4.5 4.5-5.5 5.5-6.5 >6.5
3rd Down Stop % >65% 58-65% 50-58% <50%
Turnovers Forced/Game >2.0 1.5-2.0 1.0-1.5 <1.0

Common Calculations in Python

Basic Stats Calculator

class FootballStatsCalculator:
    """Quick reference for common calculations."""

    @staticmethod
    def passing_efficiency(comp, att, yards, tds, ints):
        """Return dictionary of passing efficiency metrics."""
        return {
            'comp_pct': comp / att * 100,
            'ypa': yards / att,
            'td_pct': tds / att * 100,
            'int_pct': ints / att * 100,
            'td_int_ratio': tds / max(ints, 1),
            'net_ypa': (yards - 45 * ints) / att  # Adjusted for INTs
        }

    @staticmethod
    def rushing_efficiency(yards, carries, games):
        """Return dictionary of rushing efficiency metrics."""
        return {
            'ypc': yards / carries,
            'ypg': yards / games,
            'carries_pg': carries / games
        }

    @staticmethod
    def receiving_efficiency(rec, targets, yards, games):
        """Return dictionary of receiving efficiency metrics."""
        return {
            'catch_rate': rec / targets * 100,
            'ypr': yards / rec,
            'ypt': yards / targets,
            'rpg': rec / games,
            'ypg': yards / games
        }

Team Metrics Calculator

def calculate_team_metrics(team_data):
    """Calculate comprehensive team metrics."""

    # Offensive efficiency
    total_yards = team_data['pass_yards'] + team_data['rush_yards']
    total_plays = team_data['pass_att'] + team_data['rush_att']

    metrics = {
        'yards_per_play': total_yards / total_plays,
        'points_per_game': team_data['points'] / team_data['games'],
        'third_down_pct': team_data['third_conv'] / team_data['third_att'] * 100,
        'red_zone_td_pct': team_data['rz_td'] / team_data['rz_att'] * 100,
        'turnover_margin': team_data['takeaways'] - team_data['giveaways']
    }

    return metrics

Analysis Decision Tree

Comparing Players/Teams?
├── Same number of games/opportunities?
│   ├── Yes → Counting stats are valid
│   └── No → Use rate stats or per-game stats
│
├── Different eras (years apart)?
│   ├── Yes → Apply era adjustment
│   └── No → Direct comparison valid
│
├── Different conferences?
│   ├── Yes → Consider strength of schedule
│   └── No → Direct comparison more valid
│
└── Different roles/usage?
    ├── Yes → Focus on efficiency metrics
    └── No → Volume comparisons valid

Key Concepts to Remember

1. Context Matters

  • A 300-yard passing game in a blowout loss (garbage time) differs from 300 yards in a close win
  • High volume often comes with decreased efficiency
  • Opponent quality affects all statistics

2. Rate vs. Volume Trade-offs

  • High-volume players may have lower efficiency
  • Limited sample sizes make rate stats unreliable
  • Per-game stats balance volume with opportunity

3. Composite Metrics

  • Single metrics capture one dimension
  • Combine multiple metrics for complete picture
  • Weight metrics based on analysis goals

4. Era Adjustment

  • Passing statistics have inflated over time
  • Compare to era averages, not absolute benchmarks
  • Modern offenses produce more yards but also more plays

5. Limitations of Traditional Stats

  • Don't account for opponent quality
  • Miss play-by-play context
  • Can't measure what didn't happen (throwaways, etc.)
  • Depend on official scorer decisions

Quick Pandas Operations

import pandas as pd

# Calculate multiple rate stats at once
df['comp_pct'] = df['completions'] / df['attempts'] * 100
df['ypa'] = df['yards'] / df['attempts']
df['td_pct'] = df['touchdowns'] / df['attempts'] * 100

# Rank players across multiple categories
for col in ['yards', 'touchdowns', 'comp_pct', 'ypa']:
    df[f'{col}_rank'] = df[col].rank(ascending=False)

# Create composite ranking
rank_cols = [c for c in df.columns if c.endswith('_rank')]
df['composite_rank'] = df[rank_cols].mean(axis=1)
df['final_rank'] = df['composite_rank'].rank()

# Filter by minimum threshold
qualified = df[df['attempts'] >= 100]

# Group by team and aggregate
team_stats = df.groupby('team').agg({
    'yards': 'sum',
    'touchdowns': 'sum',
    'attempts': 'sum'
})
team_stats['team_ypa'] = team_stats['yards'] / team_stats['attempts']

Common Mistakes to Avoid

  1. Comparing without context: Always note games played, opportunities, opponent quality
  2. Ignoring minimum thresholds: Small samples produce misleading rates
  3. Treating all yards equally: A 50-yard TD differs from 50 checkdown yards
  4. Overlooking era effects: Statistics from different years need adjustment
  5. Single-metric evaluation: Use multiple metrics for complete assessment
  6. Confusing correlation with causation: High yards don't cause wins

Chapter Summary

Traditional football statistics provide the foundation for understanding player and team performance. While limited in contextual awareness, they remain essential for:

  • Initial player evaluation and comparison
  • Historical analysis and record tracking
  • Box score analysis and game summaries
  • Building blocks for advanced metrics

Master these fundamentals before moving to advanced metrics like EPA and win probability.