Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example: results tracker #351

Merged
merged 7 commits into from
Apr 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ docs/examples_gallery/

# all variations of cache directories
*_cache/
.DS_Store

# other data directories
reference/
Expand Down
9 changes: 8 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
from datetime import datetime
import re

import plotly.io as pio
from plotly.io._sg_scraper import plotly_sg_scraper

# -- Project information -----------------------------------------------------

# load version number from file in sources dir without importing
Expand Down Expand Up @@ -79,8 +82,11 @@
html_css_files = [
'css/custom.css',
]

doc_cache = os.path.abspath('../doc_cache')

# Plotly configuration: use sphinx to render plotly
pio.renderers.default = 'sphinx_gallery_png'

# matplotlib plot directive options
plot_pre_code = f"import numpy as np;" \
f"from matplotlib import pyplot as plt;" \
Expand All @@ -106,6 +112,7 @@
'gallery_dirs': 'examples_gallery',
'download_all_examples': False,
'remove_config_comments': True,
'image_scrapers': ('matplotlib', plotly_sg_scraper) # For plotly thumbnail
}

# options for latexpdf build
Expand Down
89 changes: 89 additions & 0 deletions examples/plot_results_tracker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""Plot driver standings in a heatmap
======================================

Plot the points for each driven in each race of a given season in a heatmap, as
https://public.tableau.com/app/profile/mateusz.karmalski/viz/F1ResultsTracker2022
"""

import pandas as pd
import plotly.express as px
from plotly.io import show

from fastf1.ergast import Ergast


##############################################################################
# First, we load the results for season 2022.
ergast = Ergast()
races = ergast.get_race_schedule(2022) # Races in year 2022
results = []

# For each race in the season
for rnd, race in races['raceName'].items():

# Get results. Note that we use the round no. + 1, because the round no.
# starts from one (1) instead of zero (0)
temp = ergast.get_race_results(season=2022, round=rnd + 1)
temp = temp.content[0]

# If there is a sprint, get the results as well
sprint = ergast.get_sprint_results(season=2022, round=rnd + 1)
if sprint.content and sprint.description['round'][0] == rnd + 1:
temp = pd.merge(temp, sprint.content[0], on='driverCode', how='left')
# Add sprint points and race points to get the total
temp['points'] = temp['points_x'] + temp['points_y']
temp.drop(columns=['points_x', 'points_y'], inplace=True)

# Add round no. and grand prix name
temp['round'] = rnd + 1
temp['race'] = race.removesuffix(' Grand Prix')
temp = temp[['round', 'race', 'driverCode', 'points']] # Keep useful cols.
results.append(temp)

# Append all races into a single dataframe
results = pd.concat(results)
races = results['race'].drop_duplicates()

##############################################################################
# Then we “reshape” the results to a wide table, where each row represents a
# driver and each column refers to a race, and the cell value is the points.
results = results.pivot(index='driverCode', columns='round', values='points')
# Here we have a 22-by-22 matrix (22 races and 22 drivers, incl. DEV and HUL)

# Rank the drivers by their total points
results['total_points'] = results.sum(axis=1)
results = results.sort_values(by='total_points', ascending=False)
results.drop(columns='total_points', inplace=True)

# Use race name, instead of round no., as column names
results.columns = races


##############################################################################
# The final step is to plot a heatmap using plotly
fig = px.imshow(
results,
text_auto=True,
aspect='auto', # Automatically adjust the aspect ratio
color_continuous_scale=[[0, 'rgb(198, 219, 239)'], # Blue scale
[0.25, 'rgb(107, 174, 214)'],
[0.5, 'rgb(33, 113, 181)'],
[0.75, 'rgb(8, 81, 156)'],
[1, 'rgb(8, 48, 107)']],
labels={'x': 'Race',
'y': 'Driver',
'color': 'Points'} # Change hover texts
)
fig.update_xaxes(title_text='') # Remove axis titles
fig.update_yaxes(title_text='')
fig.update_yaxes(tickmode='linear') # Show all ticks, i.e. driver names
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='LightGrey',
showline=False,
tickson='boundaries') # Show horizontal grid only
fig.update_xaxes(showgrid=False, showline=False) # And remove vertical grid
fig.update_layout(plot_bgcolor='rgba(0,0,0,0)') # White background
fig.update_layout(coloraxis_showscale=False) # Remove legend
fig.update_layout(xaxis=dict(side='top')) # x-axis on top
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0)) # Remove border margins
fig
show(fig)
4 changes: 3 additions & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ readme-renderer
xdoctest
pre-commit
requests>=2.28.1
websockets>=10.3
websockets>=10.3
plotly
kaleido