The idea

Fourth-down debates are usually reduced to labels like “aggressive” or “conservative.” Those labels are easy to repeat, but they do not explain where a coach’s decisions actually differ from the best available recommendation.

I built 4th Down Decision Audit to answer a more useful question:

In which situations does a coach systematically deviate from the model, and how costly are those decisions?

The project was inspired by the gap between fourth-down analytics research and the way fans, analysts, and teams discuss coaching decisions. A simple go-for- it rate cannot distinguish a smart aggressive decision from an aggressive mistake, or a justified punt from a high-confidence missed opportunity.

How it works

Historical fourth-down situations are scored offline using the open-source nfl4th model and the nflverse data ecosystem.

For each eligible fourth down, the audit compares the modeled win probability of going for it, attempting a field goal, and punting:

$$ \text{decision loss}_{pp} = 100 \times (\text{optimal WP} - \text{actual-action WP}) $$

The pipeline then:

  • classifies the actual decision as go, field goal, or punt;
  • identifies the offensive coach;
  • separates conservative misses from over-aggressive misses;
  • distinguishes high-confidence disagreements from toss-up decisions;
  • aggregates results into coach-season leaderboards and decision fingerprints;
  • exports static JSON data for the interactive dashboard.

The 2025 headline finding is that Mike Tomlin passed on 12 high-confidence go opportunities, the most among the audited coach-season records.

The product includes a headline insight, coach leaderboard, coach fingerprint, representative plays, and a historical-analogue scenario explorer.

How I built it

The analytical pipeline uses R for offline nfl4th scoring and Python with Polars, PyArrow, NumPy, and Pydantic for filtering, quality checks, aggregation, and JSON export.

The frontend is built with Next.js, TypeScript, Tailwind CSS, and Recharts. Docker Compose packages the analytics pipeline and dashboard into a reproducible cross-platform workflow. The deployed dashboard is a static Next.js export hosted on Netlify.

Challenges

The hardest part was not displaying the numbers; it was making sure the numbers represented the right decisions.

Fourth-down data contains ambiguous plays such as fake punts, fake field goals, penalties, no-plays, and unusual special-teams situations. I had to create a conservative action classifier and exclude uncertain rows from the primary leaderboard.

Coach attribution was another challenge because coaching changes can occur during a season. The pipeline uses game-level coach information rather than assigning an entire season to one coach.

I also had to handle model uncertainty. A one-tenth percentage-point difference should not be described like a decisive mistake, so the dashboard explicitly separates toss-ups, medium-confidence decisions, and high- confidence misses.

Finally, packaging R, Python, Node, and frontend dependencies consistently across Linux and Windows led to the Docker workflow and committed analytical artifacts.

What I learned

I learned that a strong sports analytics project needs more than a model and a chart. It needs a clear decision definition, transparent filters, sample-size rules, quality checks, and careful language around uncertainty.

The most important lesson was to treat the dashboard as an audit product rather than a prediction demo. The goal is not to label a coach permanently, but to show the specific situations where a coaching staff may want to review its process.

Built With

Share this project:

Updates

Submission history