You want data that tells a story.
NFL statistics hold a lot of narratives waiting to be seen – from a quarterback’s career-defining season to a defence’s gradual improvement.
And we’ll find these stories with Python.
Every football season generates mountains of raw data. You need the right tools to make sense of it all. Through Python, you’ll learn to process team standings, parse play-by-play data, and create visualizations that reveal patterns human eyes might miss.
Your analysis can answer questions like:
- Which teams perform best in close games?
- Do certain coaching decisions correlate with winning?
- What statistical factors predict playoff success?
The skills we’ll learn here are not just for NFL standings and NFL-related data analysis.
It will also help you with data cleaning, statistical analysis, and visualization techniques apply to any field where numbers tell a story.
Let’s get started.
Read: NumPy and Linear Regression: Efficient Python Techniques for Large Datasets
Step 1: Set up your environment
First, we’ll need to install the required packages. The nfl_data_py package provides easy access to NFL statistics, while pandas and plotly will handle our data manipulation and visualization needs.
pip install nfl_data_py pandas plotly numpy seaborn matplotlib
Let’s import our required libraries and set up the basic environment:
# Step 1: Import necessary libraries
import pandas as pd
import nfl_data_py as nfl
import plotly.graph_objects as go
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
from datetime import datetime
Also read: [Fix] ImportError: cannot import name ‘get_config’ from ‘tensorflow.python.eager.context’
Step 2: Collecting and prepare data for analysis
We’ll start by importing team descriptions and weekly player data. Then, we’ll ensure we have team details merged properly by using recent_team and team_abbr.
# Step 2: Collect and Prepare Data
teams_df = nfl.import_team_desc()
weekly_data = nfl.import_weekly_data([2024])
# Display columns in weekly_data and teams_df
print("Columns in weekly_data:", weekly_data.columns)
print("Columns in teams_df:", teams_df.columns)
# Merge data on 'recent_team' in weekly_data and 'team_abbr' in teams_df
weekly_data = weekly_data.merge(
teams_df[['team_abbr', 'team_name']],
left_on='recent_team',
right_on='team_abbr',
how='left'
)
print("Sample of Merged Data:\n", weekly_data.head()) # Confirm merge output# Step 2: Collect and Prepare Data
teams_df = nfl.import_team_desc()
weekly_data = nfl.import_weekly_data([2024])
# Display columns in weekly_data and teams_df
print("Columns in weekly_data:", weekly_data.columns)
print("Columns in teams_df:", teams_df.columns)
# Merge data on 'recent_team' in weekly_data and 'team_abbr' in teams_df
weekly_data = weekly_data.merge(
teams_df[['team_abbr', 'team_name']],
left_on='recent_team',
right_on='team_abbr',
how='left'
)
print("Sample of Merged Data:\n", weekly_data.head()) # Confirm merge output

Step 3: Calculate performance metrics
The weekly_data set doesn’t include direct team wins or losses, so we’ll calculate alternative metrics based on available data.
I’ll start by aggregating passing_yards, rushing_yards, and total points (fantasy_points) per team to get an idea of each team’s offensive strength.
# Step 3: Calculate Offensive Metrics
def calculate_offensive_metrics(df):
metrics = df.groupby('team_name').agg({
'passing_yards': 'sum',
'rushing_yards': 'sum',
'fantasy_points': 'sum'
}).reset_index()
metrics['total_yards'] = metrics['passing_yards'] + metrics['rushing_yards']
return metrics
# Calculate and display offensive metrics
offensive_metrics = calculate_offensive_metrics(weekly_data)
print("\nOffensive Metrics:\n", offensive_metrics)

Step 4: Visualize offensive performance
Now let’s put this data into some sort of a visual with the plotly library. We’ll use bar charts to show total yards and fantasy points as proxies for offensive power.
# Step 4: Visualize Offensive Performance
def plot_total_yards(metrics_df):
plt.figure(figsize=(12, 6))
sns.barplot(data=metrics_df.sort_values('total_yards', ascending=False),
x='team_name', y='total_yards')
plt.xticks(rotation=45, ha='right')
plt.title('Total Yards by Team')
plt.tight_layout()
plt.show()
def plot_fantasy_points(metrics_df):
plt.figure(figsize=(12, 6))
sns.barplot(data=metrics_df.sort_values('fantasy_points', ascending=False),
x='team_name', y='fantasy_points')
plt.xticks(rotation=45, ha='right')
plt.title('Fantasy Points by Team')
plt.tight_layout()
plt.show()
# Generate visualizations
plot_total_yards(offensive_metrics)
plot_fantasy_points(offensive_metrics)

If you close this chart, you’ll see the next chart plotting fantasy points by team.

These charts highlight which teams are leading in offensive output, using total yards and fantasy points as indicators.
Step 5: Calculate efficiency ratings
Awesome! Next, we’ll focus on average passing_yards and rushing_yards per game to estimate efficiency, with league averages as a baseline.
# Step 5: Calculate Efficiency Ratings
def calculate_efficiency(df):
efficiency = df.groupby('team_name').agg({
'passing_yards': 'mean',
'rushing_yards': 'mean'
}).reset_index()
league_avg_passing = efficiency['passing_yards'].mean()
league_avg_rushing = efficiency['rushing_yards'].mean()
efficiency['passing_efficiency'] = (efficiency['passing_yards'] / league_avg_passing) * 100
efficiency['rushing_efficiency'] = (efficiency['rushing_yards'] / league_avg_rushing) * 100
return efficiency
# Calculate and display efficiency ratings
efficiency_metrics = calculate_efficiency(weekly_data)
print("\nEfficiency Metrics:\n", efficiency_metrics)

Step 6: Build a team dashboard
A dashboard provides a summarized view of team performance using calculated metrics like total yards, fantasy points, and efficiency ratings.
# Step 6: Build a Team Dashboard
def create_team_dashboard(team_name, offensive_df, efficiency_df):
team_offense = offensive_df[offensive_df['team_name'] == team_name].iloc[0]
team_efficiency = efficiency_df[efficiency_df['team_name'] == team_name].iloc[0]
print(f"\nPerformance Dashboard for {team_name}")
print("-" * 50)
print(f"Total Passing Yards: {team_offense['passing_yards']}")
print(f"Total Rushing Yards: {team_offense['rushing_yards']}")
print(f"Total Fantasy Points: {team_offense['fantasy_points']}")
print(f"Passing Efficiency: {team_efficiency['passing_efficiency']:.1f}")
print(f"Rushing Efficiency: {team_efficiency['rushing_efficiency']:.1f}")
# Example usage for a specific team
create_team_dashboard("New York Jets", offensive_metrics, efficiency_metrics)

Step 7: Analyze trends over time
To track weekly scoring trends, plot data for each team to see changes in passing and rushing yards over time.
# Step 7: Analyze Trends Over Time
def analyze_team_trends(df, team_name):
team_data = df[df['team_name'] == team_name].sort_values('week').copy()
# Replace zeros with NaN and fill using forward fill (to keep actual zeroes, skip this step)
team_data['passing_yards'].replace(0, np.nan, inplace=True)
team_data['rushing_yards'].replace(0, np.nan, inplace=True)
team_data['passing_yards'].fillna(method='ffill', inplace=True)
team_data['rushing_yards'].fillna(method='ffill', inplace=True)
# Optional: Calculate rolling averages to smoothen trends
team_data['passing_yards_avg'] = team_data['passing_yards'].rolling(window=3, min_periods=1).mean()
team_data['rushing_yards_avg'] = team_data['rushing_yards'].rolling(window=3, min_periods=1).mean()
# Plot passing and rushing yards over weeks with smoothing
plt.figure(figsize=(12, 6))
plt.plot(team_data['week'], team_data['passing_yards_avg'], label='Passing Yards (3-week avg)', color='blue')
plt.plot(team_data['week'], team_data['rushing_yards_avg'], label='Rushing Yards (3-week avg)', color='orange')
plt.title(f'{team_name} Yards Over Time (Smoothed)')
plt.xlabel('Week')
plt.ylabel('Yards')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# Example trend analysis with improved visualization for New York Jets
analyze_team_trends(weekly_data, "New York Jets")

Step 8: Predict future performance
Using a rolling average on weekly data for each team, this simple function estimates passing and rushing yards in the next game.

Wrap up
You’ve now created a detailed analysis framework for NFL team performance using Python. You can track team success with win percentages, compare offensive and defensive efficiency, observe weekly trends, and even forecast future outcomes.
Hope this short guide helped you understand a fair bit of data analysis!