These examples demonstrate how to analyze race strategies, tire compounds, position changes, and team performance.
Tire Strategy
Visualize all drivers’ tire strategies throughout a race.
from matplotlib import pyplot as plt
import fastf1
import fastf1.plotting
# Load the race session
session = fastf1.get_session(2022, "Hungary", 'R')
session.load()
laps = session.laps
# Get the list of drivers and convert to abbreviations
drivers = session.drivers
drivers = [session.get_driver(driver)["Abbreviation"] for driver in drivers]
print(drivers)
# Find the stint length and compound used for every stint by every driver
# Group by driver, stint number, and compound, then count laps
stints = laps[["Driver", "Stint", "Compound", "LapNumber"]]
stints = stints.groupby(["Driver", "Stint", "Compound"])
stints = stints.count().reset_index()
# Rename LapNumber column to StintLength
stints = stints.rename(columns={"LapNumber": "StintLength"})
print(stints)
# Plot the strategies for each driver
fig, ax = plt.subplots(figsize=(5, 10))
for driver in drivers:
driver_stints = stints.loc[stints["Driver"] == driver]
previous_stint_end = 0
for idx, row in driver_stints.iterrows():
# Each row contains the compound name and stint length
# Use these to draw horizontal bars
compound_color = fastf1.plotting.get_compound_color(row["Compound"],
session=session)
plt.barh(
y=driver,
width=row["StintLength"],
left=previous_stint_end,
color=compound_color,
edgecolor="black",
fill=True
)
previous_stint_end += row["StintLength"]
# Make the plot more readable
plt.title("2022 Hungarian Grand Prix Strategies")
plt.xlabel("Lap Number")
plt.grid(False)
# Invert y-axis so drivers that finish higher are closer to the top
ax.invert_yaxis()
# Plot aesthetics
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
plt.tight_layout()
plt.show()
What This Example Shows
- Grouping laps by driver and stint
- Calculating stint lengths
- Using horizontal bars to visualize strategies
- Color coding by tire compound
- Ordering drivers by finishing position
Expected Output
A horizontal bar chart showing each driver’s race with colored segments representing different tire compound stints. You can see:
- How many stops each driver made
- Which compounds they used and when
- Stint lengths for each driver
- Strategic differences between teams
Understanding Stints
A stint is a period of running on the same set of tires. FastF1 automatically numbers stints:
- Stint 1: Start to first pit stop
- Stint 2: First pit stop to second pit stop
- And so on…
Position Changes
Track how driver positions change throughout a race.
import matplotlib.pyplot as plt
import fastf1.plotting
fastf1.plotting.setup_mpl(mpl_timedelta_support=False, color_scheme='fastf1')
# Load the session
session = fastf1.get_session(2023, 1, 'R')
session.load(telemetry=False, weather=False)
fig, ax = plt.subplots(figsize=(8.0, 4.9))
# For each driver, plot their position over the laps
for drv in session.drivers:
drv_laps = session.laps.pick_drivers(drv)
abb = drv_laps['Driver'].iloc[0]
style = fastf1.plotting.get_driver_style(identifier=abb,
style=['color', 'linestyle'],
session=session)
ax.plot(drv_laps['LapNumber'], drv_laps['Position'],
label=abb, **style)
# Finalize the plot
ax.set_ylim([20.5, 0.5])
ax.set_yticks([1, 5, 10, 15, 20])
ax.set_xlabel('Lap')
ax.set_ylabel('Position')
# Add legend outside the plot area
ax.legend(bbox_to_anchor=(1.0, 1.02))
plt.tight_layout()
plt.show()
What This Example Shows
- Tracking position changes lap by lap
- Using driver-specific styling (colors and line styles)
- Creating an inverted y-axis (position 1 at top)
- Handling crowded plots with external legends
Expected Output
A line plot showing all drivers’ positions throughout the race. You can observe:
- Starting grid positions
- Overtakes and position swaps
- Pit stop drops
- Safety car bunching
- Final finishing order
# For position analysis, skip telemetry and weather data
session.load(telemetry=False, weather=False)
This significantly speeds up loading when you only need lap-by-lap data.
Qualifying Results
Visualize qualifying results with time gaps to pole position.
import matplotlib.pyplot as plt
import pandas as pd
from timple.timedelta import strftimedelta
import fastf1
import fastf1.plotting
from fastf1.core import Laps
fastf1.plotting.setup_mpl(mpl_timedelta_support=True, color_scheme=None)
session = fastf1.get_session(2021, 'Spanish Grand Prix', 'Q')
session.load()
# Get an array of all drivers
drivers = pd.unique(session.laps['Driver'])
print(drivers)
# Get each driver's fastest lap and create a sorted list
list_fastest_laps = list()
for drv in drivers:
drvs_fastest_lap = session.laps.pick_drivers(drv).pick_fastest()
list_fastest_laps.append(drvs_fastest_lap)
fastest_laps = Laps(list_fastest_laps) \
.sort_values(by='LapTime') \
.reset_index(drop=True)
# Calculate time delta from pole position
pole_lap = fastest_laps.pick_fastest()
fastest_laps['LapTimeDelta'] = fastest_laps['LapTime'] - pole_lap['LapTime']
print(fastest_laps[['Driver', 'LapTime', 'LapTimeDelta']])
# Create a list of team colors per lap
team_colors = list()
for index, lap in fastest_laps.iterlaps():
color = fastf1.plotting.get_team_color(lap['Team'], session=session)
team_colors.append(color)
# Plot the data
fig, ax = plt.subplots()
ax.barh(fastest_laps.index, fastest_laps['LapTimeDelta'],
color=team_colors, edgecolor='grey')
ax.set_yticks(fastest_laps.index)
ax.set_yticklabels(fastest_laps['Driver'])
# Show fastest at the top
ax.invert_yaxis()
# Draw vertical lines behind the bars
ax.set_axisbelow(True)
ax.xaxis.grid(True, which='major', linestyle='--', color='black', zorder=-1000)
# Add title with pole lap time
lap_time_string = strftimedelta(pole_lap['LapTime'], '%m:%s.%ms')
plt.suptitle(f"{session.event['EventName']} {session.event.year} Qualifying\n"
f"Fastest Lap: {lap_time_string} ({pole_lap['Driver']})")
plt.show()
What This Example Shows
- Collecting fastest laps for all drivers
- Calculating time gaps from pole position
- Creating horizontal bar charts
- Using team colors for bars
- Formatting timedelta for display
Expected Output
A horizontal bar chart showing the qualifying results, with bars representing the time gap to pole position. Team colors make it easy to compare teammates.
Team Pace Ranking
Rank teams by race pace using box plots.
import seaborn as sns
from matplotlib import pyplot as plt
import fastf1
import fastf1.plotting
fastf1.plotting.setup_mpl(mpl_timedelta_support=False, color_scheme='fastf1')
# Load the race session and pick quick laps
race = fastf1.get_session(2024, 1, 'R')
race.load()
laps = race.laps.pick_quicklaps()
# Convert lap time to seconds
transformed_laps = laps.copy()
transformed_laps.loc[:, "LapTime (s)"] = laps["LapTime"].dt.total_seconds()
# Order teams from fastest to slowest (by median lap time)
team_order = (
transformed_laps[["Team", "LapTime (s)"]]
.groupby("Team")
.median()["LapTime (s)"]
.sort_values()
.index
)
print(team_order)
# Create color palette for teams
team_palette = {team: fastf1.plotting.get_team_color(team, session=race)
for team in team_order}
# Create box plot
fig, ax = plt.subplots(figsize=(15, 10))
sns.boxplot(
data=transformed_laps,
x="Team",
y="LapTime (s)",
hue="Team",
order=team_order,
palette=team_palette,
whiskerprops=dict(color="white"),
boxprops=dict(edgecolor="white"),
medianprops=dict(color="grey"),
capprops=dict(color="white"),
)
plt.title("2024 Bahrain Grand Prix - Team Pace Comparison")
plt.grid(visible=False)
ax.set(xlabel=None)
plt.tight_layout()
plt.show()
What This Example Shows
- Aggregating laps by team
- Using box plots to show pace distribution
- Ordering teams by median pace
- Customizing box plot styling
Expected Output
A box plot showing each team’s lap time distribution:
- Box: 25th to 75th percentile (middle 50% of laps)
- Line in box: Median lap time
- Whiskers: Extend to show range (excluding outliers)
- Teams ordered: Fastest (left) to slowest (right)
Understanding Box Plots
- Narrow box: Consistent pace
- Wide box: Variable pace (tire deg, traffic, etc.)
- Lower position: Faster overall pace
- Outliers: Shown as individual points beyond whiskers
Strategy Analysis Tips
Identifying Strategic Trends
# Count pit stops per driver
pit_stops = stints.groupby('Driver').size() - 1 # Subtract 1 (initial stint)
# Most common strategy
common_strategy = stints.groupby(['Stint', 'Compound']).size()
# Average stint length by compound
avg_stint_length = stints.groupby('Compound')['StintLength'].mean()
Comparing Strategies
# Compare two drivers' strategies
driver1_stints = stints[stints['Driver'] == 'VER']
driver2_stints = stints[stints['Driver'] == 'HAM']
print("VER stints:", driver1_stints[['Stint', 'Compound', 'StintLength']])
print("HAM stints:", driver2_stints[['Stint', 'Compound', 'StintLength']])
Strategy analysis is most interesting for dry races. Mixed conditions races may show unusual patterns due to weather-driven pit stops.