Pierwszy kontakt z danymi¶
Pobieranie danych czasowych i telemetrii F1 przez FastF1. Pierwsze uruchomienie pobiera dane do ../cache/.
import fastf1
import pandas as pd
import numpy as np
# enable local cache (gitignored)
fastf1.Cache.enable_cache('../cache')
Wczytanie jednej sesji¶
Typy sesji: FP1, FP2, FP3, Q, R (sprint: S, SQ).
session = fastf1.get_session(2024, 'Monza', 'R')
session.load() # downloads timing, laps, telemetry, weather
core INFO Loading data for Italian Grand Prix - Race [v3.8.3] req INFO No cached data found for session_info. Loading data... _api INFO Fetching session info data... req INFO Data has been written to cache! req INFO No cached data found for driver_info. Loading data... _api INFO Fetching driver list... req INFO Data has been written to cache! req INFO No cached data found for session_status_data. Loading data... _api INFO Fetching session status data... req INFO Data has been written to cache! req INFO No cached data found for lap_count. Loading data... _api INFO Fetching lap count data... req INFO Data has been written to cache! req INFO No cached data found for track_status_data. Loading data... _api INFO Fetching track status data... req INFO Data has been written to cache! req INFO No cached data found for _extended_timing_data. Loading data... _api INFO Fetching timing data... _api INFO Parsing timing data... req INFO Data has been written to cache! req INFO No cached data found for timing_app_data. Loading data... _api INFO Fetching timing app data... req INFO Data has been written to cache! core INFO Processing timing data... req INFO No cached data found for car_data. Loading data... _api INFO Fetching car data... _api INFO Parsing car data... req INFO Data has been written to cache! req INFO No cached data found for position_data. Loading data... _api INFO Fetching position data... _api INFO Parsing position data... req INFO Data has been written to cache! req INFO No cached data found for weather_data. Loading data... _api INFO Fetching weather data... req INFO Data has been written to cache! req INFO No cached data found for race_control_messages. Loading data... _api INFO Fetching race control messages... req INFO Data has been written to cache! core INFO Finished loading data for 20 drivers: ['16', '81', '4', '55', '44', '1', '63', '11', '23', '20', '14', '43', '3', '31', '10', '77', '27', '24', '18', '22']
Okrążenia¶
laps = session.laps
print(laps.shape)
laps.head()
(1008, 31)
| Time | Driver | DriverNumber | LapTime | LapNumber | Stint | PitOutTime | PitInTime | Sector1Time | Sector2Time | ... | FreshTyre | Team | LapStartTime | LapStartDate | TrackStatus | Position | Deleted | DeletedReason | FastF1Generated | IsAccurate | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 days 00:57:18.931000 | LEC | 16 | 0 days 00:01:28.179000 | 1.0 | 1.0 | NaT | NaT | NaT | 0 days 00:00:29.989000 | ... | True | Ferrari | 0 days 00:55:50.494000 | 2024-09-01 13:03:34.413 | 1 | 2.0 | False | False | False | |
| 1 | 0 days 00:58:44.327000 | LEC | 16 | 0 days 00:01:25.396000 | 2.0 | 1.0 | NaT | NaT | 0 days 00:00:27.707000 | 0 days 00:00:29.265000 | ... | True | Ferrari | 0 days 00:57:18.931000 | 2024-09-01 13:05:02.850 | 1 | 2.0 | False | False | True | |
| 2 | 0 days 01:00:09.506000 | LEC | 16 | 0 days 00:01:25.179000 | 3.0 | 1.0 | NaT | NaT | 0 days 00:00:27.679000 | 0 days 00:00:29.001000 | ... | True | Ferrari | 0 days 00:58:44.327000 | 2024-09-01 13:06:28.246 | 1 | 2.0 | False | False | True | |
| 3 | 0 days 01:01:34.316000 | LEC | 16 | 0 days 00:01:24.810000 | 4.0 | 1.0 | NaT | NaT | 0 days 00:00:27.653000 | 0 days 00:00:28.883000 | ... | True | Ferrari | 0 days 01:00:09.506000 | 2024-09-01 13:07:53.425 | 1 | 2.0 | False | False | True | |
| 4 | 0 days 01:02:58.919000 | LEC | 16 | 0 days 00:01:24.603000 | 5.0 | 1.0 | NaT | NaT | 0 days 00:00:27.630000 | 0 days 00:00:28.790000 | ... | True | Ferrari | 0 days 01:01:34.316000 | 2024-09-01 13:09:18.235 | 1 | 2.0 | False | False | True |
5 rows × 31 columns
# columns available
list(laps.columns)
['Time', 'Driver', 'DriverNumber', 'LapTime', 'LapNumber', 'Stint', 'PitOutTime', 'PitInTime', 'Sector1Time', 'Sector2Time', 'Sector3Time', 'Sector1SessionTime', 'Sector2SessionTime', 'Sector3SessionTime', 'SpeedI1', 'SpeedI2', 'SpeedFL', 'SpeedST', 'IsPersonalBest', 'Compound', 'TyreLife', 'FreshTyre', 'Team', 'LapStartTime', 'LapStartDate', 'TrackStatus', 'Position', 'Deleted', 'DeletedReason', 'FastF1Generated', 'IsAccurate']
Pogoda¶
session.weather_data.head()
| Time | AirTemp | Humidity | Pressure | Rainfall | TrackTemp | WindDirection | WindSpeed | |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 days 00:00:26.141000 | 33.2 | 38.0 | 993.8 | False | 52.1 | 318 | 0.7 |
| 1 | 0 days 00:01:26.139000 | 33.2 | 37.0 | 993.9 | False | 52.1 | 207 | 1.0 |
| 2 | 0 days 00:02:26.141000 | 33.2 | 37.0 | 993.9 | False | 52.8 | 230 | 1.3 |
| 3 | 0 days 00:03:26.146000 | 33.2 | 36.0 | 993.8 | False | 52.8 | 200 | 0.7 |
| 4 | 0 days 00:04:26.151000 | 33.3 | 36.0 | 993.8 | False | 52.8 | 182 | 0.8 |
Telemetria jednego kierowcy¶
ver = laps.pick_drivers('VER').pick_fastest()
tel = ver.get_telemetry()
print(tel.shape)
tel[['Distance', 'Speed', 'Throttle', 'Brake', 'nGear', 'X', 'Y']].head()
(632, 18)
| Distance | Speed | Throttle | Brake | nGear | X | Y | |
|---|---|---|---|---|---|---|---|
| 2 | 0.266665 | 316.542500 | 100.0 | False | 8 | -1376.705009 | -710.765951 |
| 3 | 5.653889 | 317.000000 | 100.0 | False | 8 | -1372.727497 | -664.290235 |
| 4 | 17.685200 | 317.755556 | 100.0 | False | 8 | -1363.000000 | -553.000000 |
| 5 | 30.097292 | 318.533333 | 100.0 | False | 8 | -1352.000000 | -429.000000 |
| 6 | 37.553889 | 319.000000 | 100.0 | False | 8 | -1345.615497 | -354.485258 |
Czas okrążenia a wiek opon¶
Czy dane nadają się do modelowania?
import plotly.express as px
df = laps[['Driver', 'LapNumber', 'LapTime', 'Compound', 'TyreLife', 'Stint']].copy()
df = df.dropna(subset=['LapTime'])
df['LapTime_s'] = df['LapTime'].dt.total_seconds()
ver_laps = df[df['Driver'] == 'VER']
fig = px.scatter(ver_laps, x='TyreLife', y='LapTime_s', color='Compound',
title='VER lap time vs tyre life - Monza 2024')
fig.show()
Wykres pokazuje strukturę, ale sam nie odpowiada na pytanie. Widać przede wszystkim, że wiek opony nie tłumaczy czasu okrążenia: dwa stinty na oponie HARD leżą przy tym samym wieku około 1.5 s od siebie (późniejszy, na lżejszym aucie, jest szybszy), a stint na MEDIUM jest jeszcze szybszy, choć auto wiozło wtedy najwięcej paliwa. Mieszanka i ilość paliwa znaczą więc co najmniej tyle samo co zużycie opony, a w obrębie jednego stintu trend wieku opony jest słaby. Do tego dochodzą wartości odstające - pierwsze okrążenie po starcie oraz okrążenia wjazdu do boksów i wyjazdu z nich (88-108 s) - które trzeba odfiltrować.
Odpowiedź brzmi więc: tak, ale dopiero po oczyszczeniu i z większą liczbą cech niż sam wiek opony. Robimy to w notebooku 01 dla wszystkich wyścigów sezonów 2023-2024, a w notebooku 02 wracamy do pytania o degradację opon już na oczyszczonych danych.