Added consideration of race position and gap to ahead cars

This commit is contained in:
Aditya Pulipaka
2025-10-19 04:28:49 -05:00
parent 098d881d15
commit 47f592c88b
15 changed files with 413 additions and 17537 deletions

View File

@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 4,
"id": "be0c6fbf",
"metadata": {},
"outputs": [],
@@ -31,7 +31,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 5,
"id": "f757cb34",
"metadata": {},
"outputs": [
@@ -39,7 +39,6 @@
"name": "stderr",
"output_type": "stream",
"text": [
"req WARNING \tDEFAULT CACHE ENABLED! (318.35 MB) /Users/adipu/Library/Caches/fastf1\n",
"core INFO \tLoading data for Italian Grand Prix - Race [v3.6.1]\n",
"req INFO \tUsing cached data for session_info\n",
"req INFO \tUsing cached data for driver_info\n",
@@ -95,7 +94,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 6,
"id": "aa5e5d8f",
"metadata": {},
"outputs": [
@@ -136,6 +135,9 @@
" <th></th>\n",
" <th>lap_number</th>\n",
" <th>total_laps</th>\n",
" <th>position</th>\n",
" <th>gap_to_leader</th>\n",
" <th>gap_to_ahead</th>\n",
" <th>lap_time</th>\n",
" <th>average_speed</th>\n",
" <th>max_speed</th>\n",
@@ -150,6 +152,9 @@
" <th>0</th>\n",
" <td>1</td>\n",
" <td>51</td>\n",
" <td>11</td>\n",
" <td>6.223</td>\n",
" <td>0.620</td>\n",
" <td>0 days 00:01:33.340000</td>\n",
" <td>210.17</td>\n",
" <td>326.0</td>\n",
@@ -162,6 +167,9 @@
" <th>1</th>\n",
" <td>2</td>\n",
" <td>51</td>\n",
" <td>11</td>\n",
" <td>8.229</td>\n",
" <td>0.712</td>\n",
" <td>0 days 00:01:28.012000</td>\n",
" <td>236.87</td>\n",
" <td>330.0</td>\n",
@@ -174,6 +182,9 @@
" <th>2</th>\n",
" <td>3</td>\n",
" <td>51</td>\n",
" <td>11</td>\n",
" <td>9.799</td>\n",
" <td>0.898</td>\n",
" <td>0 days 00:01:27.546000</td>\n",
" <td>236.40</td>\n",
" <td>331.0</td>\n",
@@ -186,6 +197,9 @@
" <th>3</th>\n",
" <td>4</td>\n",
" <td>51</td>\n",
" <td>11</td>\n",
" <td>10.953</td>\n",
" <td>0.919</td>\n",
" <td>0 days 00:01:27.221000</td>\n",
" <td>240.13</td>\n",
" <td>341.0</td>\n",
@@ -198,6 +212,9 @@
" <th>4</th>\n",
" <td>5</td>\n",
" <td>51</td>\n",
" <td>11</td>\n",
" <td>11.563</td>\n",
" <td>0.917</td>\n",
" <td>0 days 00:01:27.033000</td>\n",
" <td>236.09</td>\n",
" <td>345.0</td>\n",
@@ -210,6 +227,9 @@
" <th>5</th>\n",
" <td>6</td>\n",
" <td>51</td>\n",
" <td>11</td>\n",
" <td>12.123</td>\n",
" <td>0.923</td>\n",
" <td>0 days 00:01:27.175000</td>\n",
" <td>236.74</td>\n",
" <td>343.0</td>\n",
@@ -222,6 +242,9 @@
" <th>6</th>\n",
" <td>7</td>\n",
" <td>51</td>\n",
" <td>11</td>\n",
" <td>12.694</td>\n",
" <td>0.387</td>\n",
" <td>0 days 00:01:26.929000</td>\n",
" <td>239.72</td>\n",
" <td>340.0</td>\n",
@@ -234,6 +257,9 @@
" <th>7</th>\n",
" <td>8</td>\n",
" <td>51</td>\n",
" <td>10</td>\n",
" <td>13.413</td>\n",
" <td>2.760</td>\n",
" <td>0 days 00:01:26.943000</td>\n",
" <td>238.45</td>\n",
" <td>351.0</td>\n",
@@ -246,6 +272,9 @@
" <th>8</th>\n",
" <td>9</td>\n",
" <td>51</td>\n",
" <td>10</td>\n",
" <td>14.320</td>\n",
" <td>3.387</td>\n",
" <td>0 days 00:01:27.383000</td>\n",
" <td>236.81</td>\n",
" <td>330.0</td>\n",
@@ -258,6 +287,9 @@
" <th>9</th>\n",
" <td>10</td>\n",
" <td>51</td>\n",
" <td>10</td>\n",
" <td>15.177</td>\n",
" <td>3.760</td>\n",
" <td>0 days 00:01:27.368000</td>\n",
" <td>232.42</td>\n",
" <td>331.0</td>\n",
@@ -271,32 +303,44 @@
"</div>"
],
"text/plain": [
" lap_number total_laps lap_time average_speed max_speed \\\n",
"0 1 51 0 days 00:01:33.340000 210.17 326.0 \n",
"1 2 51 0 days 00:01:28.012000 236.87 330.0 \n",
"2 3 51 0 days 00:01:27.546000 236.40 331.0 \n",
"3 4 51 0 days 00:01:27.221000 240.13 341.0 \n",
"4 5 51 0 days 00:01:27.033000 236.09 345.0 \n",
"5 6 51 0 days 00:01:27.175000 236.74 343.0 \n",
"6 7 51 0 days 00:01:26.929000 239.72 340.0 \n",
"7 8 51 0 days 00:01:26.943000 238.45 351.0 \n",
"8 9 51 0 days 00:01:27.383000 236.81 330.0 \n",
"9 10 51 0 days 00:01:27.368000 232.42 331.0 \n",
" lap_number total_laps position gap_to_leader gap_to_ahead \\\n",
"0 1 51 11 6.223 0.620 \n",
"1 2 51 11 8.229 0.712 \n",
"2 3 51 11 9.799 0.898 \n",
"3 4 51 11 10.953 0.919 \n",
"4 5 51 11 11.563 0.917 \n",
"5 6 51 11 12.123 0.923 \n",
"6 7 51 11 12.694 0.387 \n",
"7 8 51 10 13.413 2.760 \n",
"8 9 51 10 14.320 3.387 \n",
"9 10 51 10 15.177 3.760 \n",
"\n",
" tire_compound tire_life_laps track_temperature rainfall \n",
"0 MEDIUM 1 42.5 False \n",
"1 MEDIUM 2 42.5 False \n",
"2 MEDIUM 3 43.2 False \n",
"3 MEDIUM 4 43.2 False \n",
"4 MEDIUM 5 43.1 False \n",
"5 MEDIUM 6 43.3 False \n",
"6 MEDIUM 7 43.6 False \n",
"7 MEDIUM 8 43.6 False \n",
"8 MEDIUM 9 43.6 False \n",
"9 MEDIUM 10 43.9 False "
" lap_time average_speed max_speed tire_compound \\\n",
"0 0 days 00:01:33.340000 210.17 326.0 MEDIUM \n",
"1 0 days 00:01:28.012000 236.87 330.0 MEDIUM \n",
"2 0 days 00:01:27.546000 236.40 331.0 MEDIUM \n",
"3 0 days 00:01:27.221000 240.13 341.0 MEDIUM \n",
"4 0 days 00:01:27.033000 236.09 345.0 MEDIUM \n",
"5 0 days 00:01:27.175000 236.74 343.0 MEDIUM \n",
"6 0 days 00:01:26.929000 239.72 340.0 MEDIUM \n",
"7 0 days 00:01:26.943000 238.45 351.0 MEDIUM \n",
"8 0 days 00:01:27.383000 236.81 330.0 MEDIUM \n",
"9 0 days 00:01:27.368000 232.42 331.0 MEDIUM \n",
"\n",
" tire_life_laps track_temperature rainfall \n",
"0 1 42.5 False \n",
"1 2 42.5 False \n",
"2 3 43.2 False \n",
"3 4 43.2 False \n",
"4 5 43.1 False \n",
"5 6 43.3 False \n",
"6 7 43.6 False \n",
"7 8 43.6 False \n",
"8 9 43.6 False \n",
"9 10 43.9 False "
]
},
"execution_count": 3,
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
@@ -306,7 +350,10 @@
"weather = session.weather_data\n",
"weather['SessionTime'] = pd.to_timedelta(weather['Time'])\n",
"\n",
"# 4. Create lap-level data by aggregating telemetry\n",
"# 4. Get all laps for position calculation\n",
"all_laps = session.laps\n",
"\n",
"# 5. Create lap-level data by aggregating telemetry\n",
"lap_data_list = []\n",
"\n",
"for lap_idx in driver_laps.index:\n",
@@ -332,6 +379,43 @@
" tire_compound = lap['Compound']\n",
" tire_life = lap['TyreLife']\n",
" \n",
" # Get position data for this lap\n",
" position = lap['Position']\n",
" \n",
" # Calculate gaps: get all drivers' data for this lap\n",
" this_lap_all_drivers = all_laps[all_laps['LapNumber'] == lap_number].copy()\n",
" \n",
" # Sort by position to calculate gaps\n",
" this_lap_all_drivers = this_lap_all_drivers.sort_values('Position')\n",
" \n",
" # Calculate cumulative race time for gap calculations\n",
" gap_to_leader = 0.0\n",
" gap_to_ahead = 0.0\n",
" \n",
" if pd.notna(position) and position > 1:\n",
" # Get our driver's data\n",
" our_data = this_lap_all_drivers[this_lap_all_drivers['Driver'] == 'ALO']\n",
" \n",
" if not our_data.empty:\n",
" # Time at the end of this lap (cumulative)\n",
" # Note: FastF1 provides 'Time' which is cumulative race time\n",
" our_time = our_data['Time'].values[0]\n",
" \n",
" # Get leader's time (P1)\n",
" leader_data = this_lap_all_drivers[this_lap_all_drivers['Position'] == 1]\n",
" if not leader_data.empty:\n",
" leader_time = leader_data['Time'].values[0]\n",
" # Convert numpy.timedelta64 to seconds\n",
" gap_to_leader = (our_time - leader_time) / np.timedelta64(1, 's')\n",
" \n",
" # Get car ahead's time (Position - 1)\n",
" ahead_position = position - 1\n",
" ahead_data = this_lap_all_drivers[this_lap_all_drivers['Position'] == ahead_position]\n",
" if not ahead_data.empty:\n",
" ahead_time = ahead_data['Time'].values[0]\n",
" # Convert numpy.timedelta64 to seconds\n",
" gap_to_ahead = (our_time - ahead_time) / np.timedelta64(1, 's')\n",
" \n",
" # Get weather data for this lap (use lap start time)\n",
" lap_start_time = pd.to_timedelta(lap['LapStartTime'])\n",
" \n",
@@ -344,6 +428,9 @@
" lap_record = {\n",
" 'lap_number': int(lap_number),\n",
" 'total_laps': int(total_laps),\n",
" 'position': int(position) if pd.notna(position) else None,\n",
" 'gap_to_leader': round(gap_to_leader, 3) if gap_to_leader > 0 else 0.0,\n",
" 'gap_to_ahead': round(gap_to_ahead, 3) if gap_to_ahead > 0 else 0.0,\n",
" 'lap_time': lap_time,\n",
" 'average_speed': round(avg_speed, 2),\n",
" 'max_speed': round(max_speed, 2),\n",
@@ -359,7 +446,7 @@
" if lap_number % 10 == 0:\n",
" print(f\"Processed lap {int(lap_number)}...\")\n",
"\n",
"# 5. Create final dataframe\n",
"# 6. Create final dataframe\n",
"laps_df = pd.DataFrame(lap_data_list)\n",
"\n",
"print(f\"\\n✓ Created lap-level dataframe with {len(laps_df)} laps\")\n",
@@ -369,7 +456,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 7,
"id": "b1086b8d",
"metadata": {},
"outputs": [
@@ -383,6 +470,9 @@
"Column types:\n",
"lap_number int64\n",
"total_laps int64\n",
"position int64\n",
"gap_to_leader float64\n",
"gap_to_ahead float64\n",
"lap_time timedelta64[ns]\n",
"average_speed float64\n",
"max_speed float64\n",
@@ -418,6 +508,9 @@
" <th></th>\n",
" <th>lap_number</th>\n",
" <th>total_laps</th>\n",
" <th>position</th>\n",
" <th>gap_to_leader</th>\n",
" <th>gap_to_ahead</th>\n",
" <th>lap_time</th>\n",
" <th>average_speed</th>\n",
" <th>max_speed</th>\n",
@@ -430,6 +523,9 @@
" <th>count</th>\n",
" <td>51.000000</td>\n",
" <td>51.0</td>\n",
" <td>51.000000</td>\n",
" <td>51.000000</td>\n",
" <td>51.000000</td>\n",
" <td>51</td>\n",
" <td>51.000000</td>\n",
" <td>51.000000</td>\n",
@@ -440,6 +536,9 @@
" <th>mean</th>\n",
" <td>26.000000</td>\n",
" <td>51.0</td>\n",
" <td>9.803922</td>\n",
" <td>29.418314</td>\n",
" <td>2.889235</td>\n",
" <td>0 days 00:01:27.596803921</td>\n",
" <td>235.797059</td>\n",
" <td>333.686275</td>\n",
@@ -450,6 +549,9 @@
" <th>std</th>\n",
" <td>14.866069</td>\n",
" <td>0.0</td>\n",
" <td>1.058671</td>\n",
" <td>13.842909</td>\n",
" <td>1.707825</td>\n",
" <td>0 days 00:00:03.069690434</td>\n",
" <td>7.855085</td>\n",
" <td>4.921342</td>\n",
@@ -460,6 +562,9 @@
" <th>min</th>\n",
" <td>1.000000</td>\n",
" <td>51.0</td>\n",
" <td>6.000000</td>\n",
" <td>6.223000</td>\n",
" <td>0.387000</td>\n",
" <td>0 days 00:01:26.105000</td>\n",
" <td>191.140000</td>\n",
" <td>322.000000</td>\n",
@@ -470,6 +575,9 @@
" <th>25%</th>\n",
" <td>13.500000</td>\n",
" <td>51.0</td>\n",
" <td>9.000000</td>\n",
" <td>16.928500</td>\n",
" <td>1.123000</td>\n",
" <td>0 days 00:01:26.715000</td>\n",
" <td>236.105000</td>\n",
" <td>331.000000</td>\n",
@@ -480,6 +588,9 @@
" <th>50%</th>\n",
" <td>26.000000</td>\n",
" <td>51.0</td>\n",
" <td>10.000000</td>\n",
" <td>29.113000</td>\n",
" <td>2.799000</td>\n",
" <td>0 days 00:01:26.943000</td>\n",
" <td>237.130000</td>\n",
" <td>332.000000</td>\n",
@@ -490,6 +601,9 @@
" <th>75%</th>\n",
" <td>38.500000</td>\n",
" <td>51.0</td>\n",
" <td>10.000000</td>\n",
" <td>43.405500</td>\n",
" <td>4.136500</td>\n",
" <td>0 days 00:01:27.328500</td>\n",
" <td>238.655000</td>\n",
" <td>334.000000</td>\n",
@@ -500,6 +614,9 @@
" <th>max</th>\n",
" <td>51.000000</td>\n",
" <td>51.0</td>\n",
" <td>12.000000</td>\n",
" <td>48.171000</td>\n",
" <td>8.135000</td>\n",
" <td>0 days 00:01:47.272000</td>\n",
" <td>241.700000</td>\n",
" <td>351.000000</td>\n",
@@ -511,28 +628,38 @@
"</div>"
],
"text/plain": [
" lap_number total_laps lap_time average_speed \\\n",
"count 51.000000 51.0 51 51.000000 \n",
"mean 26.000000 51.0 0 days 00:01:27.596803921 235.797059 \n",
"std 14.866069 0.0 0 days 00:00:03.069690434 7.855085 \n",
"min 1.000000 51.0 0 days 00:01:26.105000 191.140000 \n",
"25% 13.500000 51.0 0 days 00:01:26.715000 236.105000 \n",
"50% 26.000000 51.0 0 days 00:01:26.943000 237.130000 \n",
"75% 38.500000 51.0 0 days 00:01:27.328500 238.655000 \n",
"max 51.000000 51.0 0 days 00:01:47.272000 241.700000 \n",
" lap_number total_laps position gap_to_leader gap_to_ahead \\\n",
"count 51.000000 51.0 51.000000 51.000000 51.000000 \n",
"mean 26.000000 51.0 9.803922 29.418314 2.889235 \n",
"std 14.866069 0.0 1.058671 13.842909 1.707825 \n",
"min 1.000000 51.0 6.000000 6.223000 0.387000 \n",
"25% 13.500000 51.0 9.000000 16.928500 1.123000 \n",
"50% 26.000000 51.0 10.000000 29.113000 2.799000 \n",
"75% 38.500000 51.0 10.000000 43.405500 4.136500 \n",
"max 51.000000 51.0 12.000000 48.171000 8.135000 \n",
"\n",
" max_speed tire_life_laps track_temperature \n",
"count 51.000000 51.000000 51.000000 \n",
"mean 333.686275 15.411765 42.898039 \n",
"std 4.921342 8.616673 0.876924 \n",
"min 322.000000 1.000000 40.800000 \n",
"25% 331.000000 8.500000 42.500000 \n",
"50% 332.000000 15.000000 43.100000 \n",
"75% 334.000000 21.000000 43.600000 \n",
"max 351.000000 33.000000 44.300000 "
" lap_time average_speed max_speed tire_life_laps \\\n",
"count 51 51.000000 51.000000 51.000000 \n",
"mean 0 days 00:01:27.596803921 235.797059 333.686275 15.411765 \n",
"std 0 days 00:00:03.069690434 7.855085 4.921342 8.616673 \n",
"min 0 days 00:01:26.105000 191.140000 322.000000 1.000000 \n",
"25% 0 days 00:01:26.715000 236.105000 331.000000 8.500000 \n",
"50% 0 days 00:01:26.943000 237.130000 332.000000 15.000000 \n",
"75% 0 days 00:01:27.328500 238.655000 334.000000 21.000000 \n",
"max 0 days 00:01:47.272000 241.700000 351.000000 33.000000 \n",
"\n",
" track_temperature \n",
"count 51.000000 \n",
"mean 42.898039 \n",
"std 0.876924 \n",
"min 40.800000 \n",
"25% 42.500000 \n",
"50% 43.100000 \n",
"75% 43.600000 \n",
"max 44.300000 "
]
},
"execution_count": 4,
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
@@ -549,7 +676,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 8,
"id": "b2a3b878",
"metadata": {},
"outputs": [
@@ -569,7 +696,55 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 9,
"id": "efcff166",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Position and Gap Analysis:\n",
"Starting position: P11\n",
"Final position: P9\n",
"Average gap to leader: 29.42s\n",
"Average gap to car ahead: 2.89s\n",
"\n",
"Position changes over race:\n",
" lap_number position gap_to_leader gap_to_ahead\n",
"0 1 11 6.223 0.620\n",
"1 2 11 8.229 0.712\n",
"2 3 11 9.799 0.898\n",
"3 4 11 10.953 0.919\n",
"4 5 11 11.563 0.917\n",
"5 6 11 12.123 0.923\n",
"6 7 11 12.694 0.387\n",
"7 8 10 13.413 2.760\n",
"8 9 10 14.320 3.387\n",
"9 10 10 15.177 3.760\n",
"10 11 10 15.829 3.984\n",
"11 12 10 16.760 4.129\n",
"12 13 10 17.031 3.995\n",
"13 14 10 17.666 4.076\n",
"14 15 10 17.366 0.469\n"
]
}
],
"source": [
"# Display position and gap information\n",
"print(\"\\nPosition and Gap Analysis:\")\n",
"print(f\"Starting position: P{laps_df['position'].iloc[0]}\")\n",
"print(f\"Final position: P{laps_df['position'].iloc[-1]}\")\n",
"print(f\"Average gap to leader: {laps_df['gap_to_leader'].mean():.2f}s\")\n",
"print(f\"Average gap to car ahead: {laps_df['gap_to_ahead'].mean():.2f}s\")\n",
"print(f\"\\nPosition changes over race:\")\n",
"print(laps_df[['lap_number', 'position', 'gap_to_leader', 'gap_to_ahead']].head(15))"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "0202372e",
"metadata": {},
"outputs": [