{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Formula One Project: Data Preparation and EDA\n",
    "\n",
    "DUE: November 22nd, 2024 (Fri)  \n",
    "Name(s): Sean O'Connor, Connor Coles    \n",
    "Class: CSCI 349 - Intro to Data Mining  \n",
    "Semester: Fall 2024  \n",
    "Instructor: Brian King  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Assignment Description\n",
    "Create your first notebook file, DataPrep_EDA.ipynb. Use both markdown and code cells to convey the following:\n",
    "- What problem are you working on? Summarize in a single cell.\n",
    "- What data are you using to understand the problem? Describe the data in a very general sense. Where did it come from? You should understand what every observation in the data represents, and what each variable represents.\n",
    "- Remember that the key to achieving good machine learning outcomes is understanding how each real-world entity in your data will be represented as a fixed length vector of attributes in your dataset! Preprocessing your data will be a big part of this challenge. If you do not expect to spend quality time cleaning and prepping your data, you will not get good results. Once you have established how each data object is represented in a form ready for a data mining algorithm, and the data are clean, you will have a substantial part of your battle toward modeling solved.\n",
    "- Strive to generate good summary statistics, show what the data looks like, and include good EDA and visualizations with boxplots, barcharts, density plots for key variables, or whatever other plots you want that are specific to your data and problem to help the reader understand basic distributions of important variables. Visualizations can help you convey general info about your data and are extremely helpful.\n",
    "- In your final cells, discuss the modeling methods you expect to use. Start by clearly explaining if this is a classification, regression, clustering, or association rule mining problem? Justify. You have much of the framework to apply most algorithms, even those beyond what we covered in class. Feel free to explore different methods if you have good justification for doing so. If there are any papers of significance that have been published with these data, then discuss the ones most interesting/relevant to the team.\n",
    "- Finally, what is your overarching aim with this project? What are you hoping to learn? Or, what hypothesis are you using the data to confirm or disprove? What challenges do you foresee on this project? Discuss your concerns. How will you get your work done? Give a reasonable list of milestones to reach to arrive at the final deadline for the project."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Problem Statement\n",
    "We are analyzing Formula One driver performance to understand and predict race outcomes based on various conditions. Specifically, we aim to:\n",
    "1. Predict lap times based on weather and track conditions\n",
    "2. Understand how different variables affect driver performance\n",
    "3. Create models that can forecast race performance\n",
    "\n",
    "This is primarily a regression problem, as we're predicting continuous values (lap times) based on multiple features."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-20T02:14:34.811557Z",
     "start_time": "2024-11-20T02:14:34.804489Z"
    }
   },
   "outputs": [],
   "source": [
    "# Importing Libraries\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "import os\n",
    "\n",
    "import fastf1\n",
    "import fastf1.plotting\n",
    "from fastf1.ergast.structure import FastestLap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set up FastF1 plotting and caching\n",
    "cache_dir = '../data/cache'\n",
    "if not os.path.exists(cache_dir):\n",
    "    os.makedirs(cache_dir)\n",
    "\n",
    "fastf1.Cache.enable_cache(cache_dir)\n",
    "fastf1.plotting.setup_mpl(misc_mpl_mods=False, color_scheme=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define years, sessions, and events of interest\n",
    "years = [2021, 2022, 2023, 2024]\n",
    "sessions = ['Race']\n",
    "events = ['Bahrain Grand Prix', 'British Grand Prix', 'United States Grand Prix', 'Mexico City Grand Prix', 'São Paulo Grand Prix'] "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Why these events, sessions, and years?\n",
    "\n",
    "These events were chosen because they are all currently scheduled for the 2024 season, as well as having occurred in previous years. \n",
    "\n",
    "Each event has a specific set of conditions that may affect driver performance:\n",
    "- Bahrain: Hot and humid, with high track temperatures\n",
    "- British: Cool and changeable, with frequent rain\n",
    "- United States: Very hot, with high track temperatures\n",
    "- Mexico City: Cool and changeable, with frequent rain\n",
    "- São Paulo: Hot and humid, with high track temperatures and heavy rain\n",
    "\n",
    "As for years, we chose 2021 to 2024 because they are the most recent years for which data is available. In 2021, the regulations changed to allow for more overtaking, so the lap times became incomparable to that of previous years.\n",
    "\n",
    "We chose to only use the 'Race' session because it is the most representative of a race condition, as opposed to qualifying, which can be very sporadic."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "core           INFO \tLoading data for Bahrain Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['33', '44', '77', '16', '10', '3', '4', '55', '14', '18', '11', '99', '22', '7', '63', '31', '6', '47', '9', '5']\n",
      "core           INFO \tLoading data for British Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['33', '44', '77', '16', '4', '3', '14', '5', '31', '55', '10', '63', '7', '18', '99', '22', '6', '47', '9', '11']\n",
      "core           INFO \tLoading data for United States Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 United States Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "core        WARNING \tDriver  7: Lap timing integrity check failed for 1 lap(s)\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['33', '44', '11', '16', '55', '3', '4', '10', '77', '22', '31', '99', '18', '6', '7', '47', '9', '5', '14', '63']\n",
      "core           INFO \tLoading data for Mexico City Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 Mexico City Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['77', '44', '33', '11', '10', '55', '3', '16', '5', '7', '99', '14', '6', '47', '9', '63', '22', '4', '31', '18']\n",
      "core           INFO \tLoading data for São Paulo Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 São Paulo Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['77', '33', '55', '11', '4', '16', '10', '31', '5', '44', '3', '14', '99', '18', '22', '6', '63', '47', '9', '7']\n",
      "core           INFO \tLoading data for Bahrain Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['16', '1', '55', '11', '44', '77', '20', '14', '63', '10', '31', '47', '4', '23', '24', '22', '27', '3', '18', '6']\n",
      "core           INFO \tLoading data for British Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['55', '1', '16', '11', '44', '4', '14', '63', '24', '6', '10', '77', '22', '3', '31', '23', '20', '5', '47', '18']\n",
      "events      WARNING \tCorrecting user input 'United States Grand Prix' to 'United States Grand Prix'\n",
      "core           INFO \tLoading data for United States Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 United States Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['55', '1', '44', '63', '18', '4', '77', '23', '11', '5', '10', '16', '20', '14', '3', '47', '6', '24', '22', '31']\n",
      "core           INFO \tLoading data for Mexico City Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 Mexico City Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['1', '63', '44', '11', '55', '77', '16', '4', '14', '31', '3', '24', '22', '10', '47', '5', '23', '6', '20', '18']\n",
      "core           INFO \tLoading data for São Paulo Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 São Paulo Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['63', '44', '1', '11', '16', '4', '55', '20', '5', '10', '3', '47', '24', '77', '18', '31', '14', '6', '23', '22']\n",
      "core           INFO \tLoading data for Bahrain Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['1', '11', '16', '55', '14', '63', '44', '18', '31', '27', '4', '77', '24', '22', '23', '2', '20', '81', '21', '10']\n",
      "core           INFO \tLoading data for British Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['1', '4', '81', '16', '55', '63', '44', '23', '14', '10', '27', '18', '31', '2', '11', '22', '24', '21', '20', '77']\n",
      "events      WARNING \tCorrecting user input 'United States Grand Prix' to 'United States Grand Prix'\n",
      "core           INFO \tLoading data for United States Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 United States Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['16', '4', '44', '55', '63', '1', '10', '31', '11', '81', '22', '24', '77', '3', '23', '2', '20', '27', '14', '18']\n",
      "core           INFO \tLoading data for Mexico City Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 Mexico City Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['16', '55', '1', '3', '11', '44', '81', '63', '77', '24', '10', '27', '14', '23', '31', '20', '4', '22', '2', '18']\n",
      "core           INFO \tLoading data for São Paulo Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 São Paulo Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['1', '16', '18', '14', '44', '4', '55', '63', '11', '81', '27', '20', '23', '31', '10', '22', '3', '77', '2', '24']\n",
      "core           INFO \tLoading data for Bahrain Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['1', '16', '63', '55', '11', '14', '4', '81', '44', '27', '22', '18', '23', '3', '20', '77', '24', '2', '31', '10']\n",
      "core           INFO \tLoading data for British Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['63', '44', '4', '1', '81', '27', '55', '18', '23', '14', '16', '2', '22', '24', '3', '77', '20', '31', '10', '11']\n",
      "events      WARNING \tCorrecting user input 'United States Grand Prix' to 'United States Grand Prix'\n",
      "core           INFO \tLoading data for United States Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 United States Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['4', '1', '55', '16', '81', '10', '14', '20', '11', '22', '27', '31', '18', '23', '43', '77', '44', '24', '30', '63']\n",
      "core           INFO \tLoading data for Mexico City Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 Mexico City Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['55', '1', '4', '16', '63', '44', '20', '10', '23', '27', '22', '30', '14', '18', '77', '43', '81', '11', '24', '31']\n",
      "core           INFO \tLoading data for São Paulo Grand Prix - Race [v3.4.4]\n",
      "req            INFO \tUsing cached data for session_info\n",
      "req            INFO \tUsing cached data for driver_info\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 São Paulo Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "logger      WARNING \tFailed to load result data from Ergast!\n",
      "core        WARNING \tNo result data for this session available on Ergast! (This is expected for recent sessions)\n",
      "req            INFO \tUsing cached data for session_status_data\n",
      "req            INFO \tUsing cached data for lap_count\n",
      "req            INFO \tUsing cached data for track_status_data\n",
      "req            INFO \tUsing cached data for _extended_timing_data\n",
      "req            INFO \tUsing cached data for timing_app_data\n",
      "core           INFO \tProcessing timing data...\n",
      "core        WARNING \tNo lap data for driver 23\n",
      "core        WARNING \tFailed to perform lap accuracy check - all laps marked as inaccurate (driver 23)\n",
      "logger      WARNING \tFailed to add first lap time from Ergast!\n",
      "req            INFO \tUsing cached data for car_data\n",
      "req            INFO \tUsing cached data for position_data\n",
      "req            INFO \tUsing cached data for weather_data\n",
      "req            INFO \tUsing cached data for race_control_messages\n",
      "core           INFO \tFinished loading data for 20 drivers: ['4', '63', '22', '31', '30', '16', '23', '81', '14', '18', '77', '11', '10', '44', '50', '43', '1', '27', '24', '55']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Weather Data Structure:\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 3340 entries, 0 to 3339\n",
      "Data columns (total 11 columns):\n",
      " #   Column         Non-Null Count  Dtype          \n",
      "---  ------         --------------  -----          \n",
      " 0   Time           3340 non-null   timedelta64[ns]\n",
      " 1   Year           3340 non-null   int64          \n",
      " 2   Event          3340 non-null   object         \n",
      " 3   Session        3340 non-null   object         \n",
      " 4   AirTemp        3340 non-null   float64        \n",
      " 5   Humidity       3340 non-null   float64        \n",
      " 6   Pressure       3340 non-null   float64        \n",
      " 7   Rainfall       3340 non-null   bool           \n",
      " 8   TrackTemp      3340 non-null   float64        \n",
      " 9   WindDirection  3340 non-null   int64          \n",
      " 10  WindSpeed      3340 non-null   float64        \n",
      "dtypes: bool(1), float64(5), int64(2), object(2), timedelta64[ns](1)\n",
      "memory usage: 264.3+ KB\n",
      "None\n",
      "\n",
      "Lap Data Structure:\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 22164 entries, 0 to 22163\n",
      "Data columns (total 18 columns):\n",
      " #   Column       Non-Null Count  Dtype          \n",
      "---  ------       --------------  -----          \n",
      " 0   Time         22164 non-null  timedelta64[ns]\n",
      " 1   Year         22164 non-null  int64          \n",
      " 2   Event        22164 non-null  object         \n",
      " 3   Session      22164 non-null  object         \n",
      " 4   Driver       22164 non-null  object         \n",
      " 5   Team         22164 non-null  object         \n",
      " 6   LapNumber    22164 non-null  float64        \n",
      " 7   LapTime      21470 non-null  timedelta64[ns]\n",
      " 8   Sector1Time  21658 non-null  timedelta64[ns]\n",
      " 9   Sector2Time  22121 non-null  timedelta64[ns]\n",
      " 10  Sector3Time  22124 non-null  timedelta64[ns]\n",
      " 11  Compound     22164 non-null  object         \n",
      " 12  TyreLife     22164 non-null  float64        \n",
      " 13  FreshTyre    22164 non-null  bool           \n",
      " 14  SpeedI1      18914 non-null  float64        \n",
      " 15  SpeedI2      22124 non-null  float64        \n",
      " 16  SpeedFL      21288 non-null  float64        \n",
      " 17  SpeedST      20033 non-null  float64        \n",
      "dtypes: bool(1), float64(6), int64(1), object(5), timedelta64[ns](5)\n",
      "memory usage: 2.9+ MB\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# Get data from FastF1 API\n",
    "\n",
    "# Data containers\n",
    "weather_data_list = []\n",
    "lap_data_list = []\n",
    "\n",
    "# Loop through years and sessions\n",
    "for year in years:\n",
    "    for event_name in events:   \n",
    "        for session_name in sessions:\n",
    "            try:\n",
    "                print(f\"Processing {year} {event_name} - {session_name}\")\n",
    "                \n",
    "                # Load the session\n",
    "                session = fastf1.get_session(year, event_name, session_name, backend='fastf1')\n",
    "                session.load()\n",
    "                \n",
    "                # Process weather data\n",
    "                weather_data = session.weather_data\n",
    "                if weather_data is not None:\n",
    "                    weather_df = pd.DataFrame(weather_data)\n",
    "                    # Add context columns\n",
    "                    weather_df['Year'] = year\n",
    "                    weather_df['Event'] = event_name\n",
    "                    weather_df['Session'] = session_name\n",
    "                    weather_data_list.append(weather_df)\n",
    "\n",
    "                # Process lap data\n",
    "                lap_data = session.laps\n",
    "                if lap_data is not None:\n",
    "                    lap_df = pd.DataFrame(lap_data)\n",
    "                    # Add context columns\n",
    "                    lap_df['Year'] = year\n",
    "                    lap_df['Event'] = event_name\n",
    "                    lap_df['Session'] = session_name\n",
    "                    # Ensure driver information is included\n",
    "                    if 'Driver' not in lap_df.columns:\n",
    "                        lap_df['Driver'] = lap_df['DriverNumber'].map(session.drivers)\n",
    "                    # Add team information if available\n",
    "                    if 'Team' not in lap_df.columns:\n",
    "                        lap_df['Team'] = lap_df['Driver'].map(session.drivers_info['TeamName'])\n",
    "                    lap_data_list.append(lap_df)\n",
    "        \n",
    "            except Exception as e:\n",
    "                print(f\"Error with {event_name} {session_name} ({year}): {e}\")\n",
    "\n",
    "# Combine data into DataFrames\n",
    "if weather_data_list:\n",
    "    weather_data_combined = pd.concat(weather_data_list, ignore_index=True)\n",
    "    # Ensure consistent column ordering\n",
    "    weather_cols = ['Time', 'Year', 'Event', 'Session', \n",
    "                   'AirTemp', 'Humidity', 'Pressure', 'Rainfall', \n",
    "                   'TrackTemp', 'WindDirection', 'WindSpeed']\n",
    "    weather_data_combined = weather_data_combined[weather_cols]\n",
    "    print(\"\\nWeather Data Structure:\")\n",
    "    print(weather_data_combined.info())\n",
    "\n",
    "if lap_data_list:\n",
    "    lap_data_combined = pd.concat(lap_data_list, ignore_index=True)\n",
    "    # Ensure consistent column ordering\n",
    "    lap_cols = ['Time', 'Year', 'Event', 'Session', \n",
    "                'Driver', 'Team', 'LapNumber', 'LapTime',\n",
    "                'Sector1Time', 'Sector2Time', 'Sector3Time',\n",
    "                'Compound', 'TyreLife', 'FreshTyre',\n",
    "                'SpeedI1', 'SpeedI2', 'SpeedFL', 'SpeedST']\n",
    "    # Only include columns that exist\n",
    "    existing_cols = [col for col in lap_cols if col in lap_data_combined.columns]\n",
    "    lap_data_combined = lap_data_combined[existing_cols]\n",
    "    print(\"\\nLap Data Structure:\")\n",
    "    print(lap_data_combined.info())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Events per Year:\n",
      "Event  Bahrain Grand Prix  British Grand Prix  Mexico City Grand Prix  \\\n",
      "Year                                                                    \n",
      "2021                 1028                 970                    1261   \n",
      "2022                 1125                 815                    1379   \n",
      "2023                 1056                 971                    1282   \n",
      "2024                 1129                 961                    1215   \n",
      "\n",
      "Event  São Paulo Grand Prix  United States Grand Prix  \n",
      "Year                                                   \n",
      "2021                   1360                      1044  \n",
      "2022                   1259                       992  \n",
      "2023                   1109                      1014  \n",
      "2024                   1135                      1059  \n",
      "\n",
      "Drivers per Event:\n",
      "Driver\n",
      "ALB    5\n",
      "ALO    5\n",
      "BEA    1\n",
      "BOT    5\n",
      "COL    3\n",
      "DEV    2\n",
      "GAS    5\n",
      "GIO    5\n",
      "HAM    5\n",
      "HUL    5\n",
      "LAT    5\n",
      "LAW    3\n",
      "LEC    5\n",
      "MAG    5\n",
      "MAZ    5\n",
      "MSC    5\n",
      "NOR    5\n",
      "OCO    5\n",
      "PER    5\n",
      "PIA    5\n",
      "RAI    5\n",
      "RIC    5\n",
      "RUS    5\n",
      "SAI    5\n",
      "SAR    5\n",
      "STR    5\n",
      "TSU    5\n",
      "VER    5\n",
      "VET    5\n",
      "ZHO    5\n",
      "dtype: int64\n",
      "\n",
      "Laps per Driver:\n",
      "Driver\n",
      "NOR    1200\n",
      "HAM    1172\n",
      "VER    1171\n",
      "PER    1151\n",
      "SAI    1139\n",
      "LEC    1137\n",
      "RUS    1135\n",
      "BOT    1115\n",
      "ALO    1097\n",
      "STR    1088\n",
      "GAS    1080\n",
      "OCO    1076\n",
      "TSU    1059\n",
      "RIC     822\n",
      "ZHO     811\n",
      "ALB     656\n",
      "MAG     647\n",
      "HUL     626\n",
      "LAT     601\n",
      "VET     539\n",
      "MSC     536\n",
      "PIA     520\n",
      "SAR     412\n",
      "RAI     302\n",
      "GIO     301\n",
      "MAZ     243\n",
      "LAW     195\n",
      "COL     156\n",
      "DEV     108\n",
      "BEA      69\n",
      "Name: LapNumber, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "# Display some summary statistics, to ensure the data is correct\n",
    "print(\"\\nEvents per Year:\")\n",
    "print(lap_data_combined.groupby(['Year', 'Event']).size().unstack())\n",
    "\n",
    "print(\"\\nDrivers per Event:\")\n",
    "print(lap_data_combined.groupby(['Event', 'Driver']).size().unstack().notna().sum())\n",
    "\n",
    "print(\"\\nLaps per Driver:\")\n",
    "print(lap_data_combined.groupby('Driver')['LapNumber'].count().sort_values(ascending=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 3340 entries, 0 to 3339\n",
      "Data columns (total 11 columns):\n",
      " #   Column         Non-Null Count  Dtype          \n",
      "---  ------         --------------  -----          \n",
      " 0   Time           3340 non-null   timedelta64[ns]\n",
      " 1   Year           3340 non-null   int64          \n",
      " 2   Event          3340 non-null   object         \n",
      " 3   Session        3340 non-null   object         \n",
      " 4   AirTemp        3340 non-null   float64        \n",
      " 5   Humidity       3340 non-null   float64        \n",
      " 6   Pressure       3340 non-null   float64        \n",
      " 7   Rainfall       3340 non-null   bool           \n",
      " 8   TrackTemp      3340 non-null   float64        \n",
      " 9   WindDirection  3340 non-null   int64          \n",
      " 10  WindSpeed      3340 non-null   float64        \n",
      "dtypes: bool(1), float64(5), int64(2), object(2), timedelta64[ns](1)\n",
      "memory usage: 264.3+ KB\n"
     ]
    }
   ],
   "source": [
    "weather_data_combined.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "      <th>Event</th>\n",
       "      <th>Session</th>\n",
       "      <th>AirTemp</th>\n",
       "      <th>Humidity</th>\n",
       "      <th>Pressure</th>\n",
       "      <th>Rainfall</th>\n",
       "      <th>TrackTemp</th>\n",
       "      <th>WindDirection</th>\n",
       "      <th>WindSpeed</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0 days 00:00:43.040000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.9</td>\n",
       "      <td>56.4</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>6</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0 days 00:01:43.040000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.8</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>8</td>\n",
       "      <td>1.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0 days 00:02:43.040000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.8</td>\n",
       "      <td>1014.7</td>\n",
       "      <td>False</td>\n",
       "      <td>30.2</td>\n",
       "      <td>11</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0 days 00:03:43.039000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.7</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>30.2</td>\n",
       "      <td>7</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0 days 00:04:43.041000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.1</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>0</td>\n",
       "      <td>0.9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                    Time  Year               Event Session  AirTemp  Humidity  \\\n",
       "0 0 days 00:00:43.040000  2021  Bahrain Grand Prix    Race     20.9      56.4   \n",
       "1 0 days 00:01:43.040000  2021  Bahrain Grand Prix    Race     20.8      56.8   \n",
       "2 0 days 00:02:43.040000  2021  Bahrain Grand Prix    Race     20.8      56.8   \n",
       "3 0 days 00:03:43.039000  2021  Bahrain Grand Prix    Race     20.8      56.7   \n",
       "4 0 days 00:04:43.041000  2021  Bahrain Grand Prix    Race     20.8      56.1   \n",
       "\n",
       "   Pressure  Rainfall  TrackTemp  WindDirection  WindSpeed  \n",
       "0    1014.8     False       29.9              6        1.0  \n",
       "1    1014.8     False       29.9              8        1.1  \n",
       "2    1014.7     False       30.2             11        1.0  \n",
       "3    1014.8     False       30.2              7        1.0  \n",
       "4    1014.8     False       29.9              0        0.9  "
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weather_data_combined.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "      <th>AirTemp</th>\n",
       "      <th>Humidity</th>\n",
       "      <th>Pressure</th>\n",
       "      <th>TrackTemp</th>\n",
       "      <th>WindDirection</th>\n",
       "      <th>WindSpeed</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>3340</td>\n",
       "      <td>3340.000000</td>\n",
       "      <td>3340.000000</td>\n",
       "      <td>3340.000000</td>\n",
       "      <td>3340.000000</td>\n",
       "      <td>3340.000000</td>\n",
       "      <td>3340.000000</td>\n",
       "      <td>3340.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0 days 01:24:31.030640119</td>\n",
       "      <td>2022.506287</td>\n",
       "      <td>23.515120</td>\n",
       "      <td>49.327725</td>\n",
       "      <td>942.198563</td>\n",
       "      <td>37.713174</td>\n",
       "      <td>171.006587</td>\n",
       "      <td>1.456886</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0 days 00:49:45.991344708</td>\n",
       "      <td>1.104440</td>\n",
       "      <td>4.132815</td>\n",
       "      <td>17.572925</td>\n",
       "      <td>86.689976</td>\n",
       "      <td>9.259403</td>\n",
       "      <td>95.769102</td>\n",
       "      <td>1.374015</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>0 days 00:00:05.091000</td>\n",
       "      <td>2021.000000</td>\n",
       "      <td>14.500000</td>\n",
       "      <td>16.000000</td>\n",
       "      <td>778.500000</td>\n",
       "      <td>20.700000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0 days 00:41:50.938250</td>\n",
       "      <td>2022.000000</td>\n",
       "      <td>20.500000</td>\n",
       "      <td>36.000000</td>\n",
       "      <td>922.500000</td>\n",
       "      <td>29.400000</td>\n",
       "      <td>104.000000</td>\n",
       "      <td>0.600000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0 days 01:23:45.092500</td>\n",
       "      <td>2023.000000</td>\n",
       "      <td>22.900000</td>\n",
       "      <td>51.000000</td>\n",
       "      <td>992.000000</td>\n",
       "      <td>37.400000</td>\n",
       "      <td>176.000000</td>\n",
       "      <td>1.100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>0 days 02:05:19.890750</td>\n",
       "      <td>2023.000000</td>\n",
       "      <td>27.325000</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>1006.700000</td>\n",
       "      <td>47.100000</td>\n",
       "      <td>241.000000</td>\n",
       "      <td>1.800000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>0 days 03:22:50.536000</td>\n",
       "      <td>2024.000000</td>\n",
       "      <td>31.000000</td>\n",
       "      <td>92.000000</td>\n",
       "      <td>1017.500000</td>\n",
       "      <td>56.300000</td>\n",
       "      <td>359.000000</td>\n",
       "      <td>10.100000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                            Time         Year      AirTemp     Humidity  \\\n",
       "count                       3340  3340.000000  3340.000000  3340.000000   \n",
       "mean   0 days 01:24:31.030640119  2022.506287    23.515120    49.327725   \n",
       "std    0 days 00:49:45.991344708     1.104440     4.132815    17.572925   \n",
       "min       0 days 00:00:05.091000  2021.000000    14.500000    16.000000   \n",
       "25%       0 days 00:41:50.938250  2022.000000    20.500000    36.000000   \n",
       "50%       0 days 01:23:45.092500  2023.000000    22.900000    51.000000   \n",
       "75%       0 days 02:05:19.890750  2023.000000    27.325000    60.000000   \n",
       "max       0 days 03:22:50.536000  2024.000000    31.000000    92.000000   \n",
       "\n",
       "          Pressure    TrackTemp  WindDirection    WindSpeed  \n",
       "count  3340.000000  3340.000000    3340.000000  3340.000000  \n",
       "mean    942.198563    37.713174     171.006587     1.456886  \n",
       "std      86.689976     9.259403      95.769102     1.374015  \n",
       "min     778.500000    20.700000       0.000000     0.000000  \n",
       "25%     922.500000    29.400000     104.000000     0.600000  \n",
       "50%     992.000000    37.400000     176.000000     1.100000  \n",
       "75%    1006.700000    47.100000     241.000000     1.800000  \n",
       "max    1017.500000    56.300000     359.000000    10.100000  "
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weather_data_combined.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 22164 entries, 0 to 22163\n",
      "Data columns (total 18 columns):\n",
      " #   Column       Non-Null Count  Dtype          \n",
      "---  ------       --------------  -----          \n",
      " 0   Time         22164 non-null  timedelta64[ns]\n",
      " 1   Year         22164 non-null  int64          \n",
      " 2   Event        22164 non-null  object         \n",
      " 3   Session      22164 non-null  object         \n",
      " 4   Driver       22164 non-null  object         \n",
      " 5   Team         22164 non-null  object         \n",
      " 6   LapNumber    22164 non-null  float64        \n",
      " 7   LapTime      21470 non-null  timedelta64[ns]\n",
      " 8   Sector1Time  21658 non-null  timedelta64[ns]\n",
      " 9   Sector2Time  22121 non-null  timedelta64[ns]\n",
      " 10  Sector3Time  22124 non-null  timedelta64[ns]\n",
      " 11  Compound     22164 non-null  object         \n",
      " 12  TyreLife     22164 non-null  float64        \n",
      " 13  FreshTyre    22164 non-null  bool           \n",
      " 14  SpeedI1      18914 non-null  float64        \n",
      " 15  SpeedI2      22124 non-null  float64        \n",
      " 16  SpeedFL      21288 non-null  float64        \n",
      " 17  SpeedST      20033 non-null  float64        \n",
      "dtypes: bool(1), float64(6), int64(1), object(5), timedelta64[ns](5)\n",
      "memory usage: 2.9+ MB\n"
     ]
    }
   ],
   "source": [
    "lap_data_combined.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "      <th>Event</th>\n",
       "      <th>Session</th>\n",
       "      <th>Driver</th>\n",
       "      <th>Team</th>\n",
       "      <th>LapNumber</th>\n",
       "      <th>LapTime</th>\n",
       "      <th>Sector1Time</th>\n",
       "      <th>Sector2Time</th>\n",
       "      <th>Sector3Time</th>\n",
       "      <th>Compound</th>\n",
       "      <th>TyreLife</th>\n",
       "      <th>FreshTyre</th>\n",
       "      <th>SpeedI1</th>\n",
       "      <th>SpeedI2</th>\n",
       "      <th>SpeedFL</th>\n",
       "      <th>SpeedST</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0 days 00:39:14.871000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>1.0</td>\n",
       "      <td>NaT</td>\n",
       "      <td>NaT</td>\n",
       "      <td>0 days 00:00:56.543000</td>\n",
       "      <td>0 days 00:00:34.384000</td>\n",
       "      <td>MEDIUM</td>\n",
       "      <td>4.0</td>\n",
       "      <td>False</td>\n",
       "      <td>238.0</td>\n",
       "      <td>97.0</td>\n",
       "      <td>246.0</td>\n",
       "      <td>261.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0 days 00:41:37.134000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0 days 00:02:22.263000</td>\n",
       "      <td>0 days 00:00:45.220000</td>\n",
       "      <td>0 days 00:01:00.086000</td>\n",
       "      <td>0 days 00:00:36.957000</td>\n",
       "      <td>MEDIUM</td>\n",
       "      <td>5.0</td>\n",
       "      <td>False</td>\n",
       "      <td>120.0</td>\n",
       "      <td>134.0</td>\n",
       "      <td>182.0</td>\n",
       "      <td>236.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0 days 00:44:09.738000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>3.0</td>\n",
       "      <td>NaT</td>\n",
       "      <td>0 days 00:00:42.591000</td>\n",
       "      <td>0 days 00:01:00.850000</td>\n",
       "      <td>0 days 00:00:49.169000</td>\n",
       "      <td>MEDIUM</td>\n",
       "      <td>6.0</td>\n",
       "      <td>False</td>\n",
       "      <td>217.0</td>\n",
       "      <td>99.0</td>\n",
       "      <td>176.0</td>\n",
       "      <td>229.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0 days 00:46:16.510000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>4.0</td>\n",
       "      <td>0 days 00:02:06.772000</td>\n",
       "      <td>0 days 00:00:33.336000</td>\n",
       "      <td>0 days 00:00:50.186000</td>\n",
       "      <td>0 days 00:00:43.250000</td>\n",
       "      <td>MEDIUM</td>\n",
       "      <td>7.0</td>\n",
       "      <td>False</td>\n",
       "      <td>229.0</td>\n",
       "      <td>202.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>297.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0 days 00:48:28.044000</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>5.0</td>\n",
       "      <td>0 days 00:02:11.534000</td>\n",
       "      <td>0 days 00:01:05.748000</td>\n",
       "      <td>0 days 00:00:41.956000</td>\n",
       "      <td>0 days 00:00:23.830000</td>\n",
       "      <td>HARD</td>\n",
       "      <td>1.0</td>\n",
       "      <td>True</td>\n",
       "      <td>231.0</td>\n",
       "      <td>251.0</td>\n",
       "      <td>275.0</td>\n",
       "      <td>213.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                    Time  Year               Event Session Driver        Team  \\\n",
       "0 0 days 00:39:14.871000  2021  Bahrain Grand Prix    Race    GAS  AlphaTauri   \n",
       "1 0 days 00:41:37.134000  2021  Bahrain Grand Prix    Race    GAS  AlphaTauri   \n",
       "2 0 days 00:44:09.738000  2021  Bahrain Grand Prix    Race    GAS  AlphaTauri   \n",
       "3 0 days 00:46:16.510000  2021  Bahrain Grand Prix    Race    GAS  AlphaTauri   \n",
       "4 0 days 00:48:28.044000  2021  Bahrain Grand Prix    Race    GAS  AlphaTauri   \n",
       "\n",
       "   LapNumber                LapTime            Sector1Time  \\\n",
       "0        1.0                    NaT                    NaT   \n",
       "1        2.0 0 days 00:02:22.263000 0 days 00:00:45.220000   \n",
       "2        3.0                    NaT 0 days 00:00:42.591000   \n",
       "3        4.0 0 days 00:02:06.772000 0 days 00:00:33.336000   \n",
       "4        5.0 0 days 00:02:11.534000 0 days 00:01:05.748000   \n",
       "\n",
       "             Sector2Time            Sector3Time Compound  TyreLife  FreshTyre  \\\n",
       "0 0 days 00:00:56.543000 0 days 00:00:34.384000   MEDIUM       4.0      False   \n",
       "1 0 days 00:01:00.086000 0 days 00:00:36.957000   MEDIUM       5.0      False   \n",
       "2 0 days 00:01:00.850000 0 days 00:00:49.169000   MEDIUM       6.0      False   \n",
       "3 0 days 00:00:50.186000 0 days 00:00:43.250000   MEDIUM       7.0      False   \n",
       "4 0 days 00:00:41.956000 0 days 00:00:23.830000     HARD       1.0       True   \n",
       "\n",
       "   SpeedI1  SpeedI2  SpeedFL  SpeedST  \n",
       "0    238.0     97.0    246.0    261.0  \n",
       "1    120.0    134.0    182.0    236.0  \n",
       "2    217.0     99.0    176.0    229.0  \n",
       "3    229.0    202.0      NaN    297.0  \n",
       "4    231.0    251.0    275.0    213.0  "
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lap_data_combined.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "      <th>LapNumber</th>\n",
       "      <th>LapTime</th>\n",
       "      <th>Sector1Time</th>\n",
       "      <th>Sector2Time</th>\n",
       "      <th>Sector3Time</th>\n",
       "      <th>TyreLife</th>\n",
       "      <th>SpeedI1</th>\n",
       "      <th>SpeedI2</th>\n",
       "      <th>SpeedFL</th>\n",
       "      <th>SpeedST</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>22164</td>\n",
       "      <td>22164.000000</td>\n",
       "      <td>22164.000000</td>\n",
       "      <td>21470</td>\n",
       "      <td>21658</td>\n",
       "      <td>22121</td>\n",
       "      <td>22124</td>\n",
       "      <td>22164.000000</td>\n",
       "      <td>18914.000000</td>\n",
       "      <td>22124.000000</td>\n",
       "      <td>21288.000000</td>\n",
       "      <td>20033.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0 days 01:54:44.800035192</td>\n",
       "      <td>2022.485788</td>\n",
       "      <td>30.763626</td>\n",
       "      <td>0 days 00:01:32.813397251</td>\n",
       "      <td>0 days 00:00:28.815164742</td>\n",
       "      <td>0 days 00:00:39.797198453</td>\n",
       "      <td>0 days 00:00:25.173835246</td>\n",
       "      <td>13.626331</td>\n",
       "      <td>260.271968</td>\n",
       "      <td>237.564997</td>\n",
       "      <td>252.587326</td>\n",
       "      <td>296.487196</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0 days 00:32:17.225029250</td>\n",
       "      <td>1.121193</td>\n",
       "      <td>18.344432</td>\n",
       "      <td>0 days 00:00:12.742266127</td>\n",
       "      <td>0 days 00:00:06.851402866</td>\n",
       "      <td>0 days 00:00:06.054553871</td>\n",
       "      <td>0 days 00:00:06.702798903</td>\n",
       "      <td>9.292165</td>\n",
       "      <td>44.508356</td>\n",
       "      <td>40.623522</td>\n",
       "      <td>41.053033</td>\n",
       "      <td>35.907749</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>0 days 00:39:08.419000</td>\n",
       "      <td>2021.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0 days 00:01:11.010000</td>\n",
       "      <td>0 days 00:00:18.281000</td>\n",
       "      <td>0 days 00:00:29.991000</td>\n",
       "      <td>0 days 00:00:16.396000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>69.000000</td>\n",
       "      <td>40.000000</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>63.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0 days 01:28:13.891000</td>\n",
       "      <td>2021.000000</td>\n",
       "      <td>15.000000</td>\n",
       "      <td>0 days 00:01:23.029000</td>\n",
       "      <td>0 days 00:00:27.189250</td>\n",
       "      <td>0 days 00:00:37.224000</td>\n",
       "      <td>0 days 00:00:21.293000</td>\n",
       "      <td>6.000000</td>\n",
       "      <td>225.000000</td>\n",
       "      <td>217.000000</td>\n",
       "      <td>241.000000</td>\n",
       "      <td>292.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0 days 01:53:32.523500</td>\n",
       "      <td>2022.000000</td>\n",
       "      <td>30.000000</td>\n",
       "      <td>0 days 00:01:33.512000</td>\n",
       "      <td>0 days 00:00:29.187000</td>\n",
       "      <td>0 days 00:00:39.879000</td>\n",
       "      <td>0 days 00:00:24.026000</td>\n",
       "      <td>12.000000</td>\n",
       "      <td>282.000000</td>\n",
       "      <td>250.000000</td>\n",
       "      <td>248.000000</td>\n",
       "      <td>301.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>0 days 02:19:43.326750</td>\n",
       "      <td>2023.000000</td>\n",
       "      <td>45.000000</td>\n",
       "      <td>0 days 00:01:40.291750</td>\n",
       "      <td>0 days 00:00:30.638000</td>\n",
       "      <td>0 days 00:00:42.034000</td>\n",
       "      <td>0 days 00:00:26.934750</td>\n",
       "      <td>19.000000</td>\n",
       "      <td>297.000000</td>\n",
       "      <td>261.000000</td>\n",
       "      <td>282.000000</td>\n",
       "      <td>317.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>0 days 03:20:47.648000</td>\n",
       "      <td>2024.000000</td>\n",
       "      <td>71.000000</td>\n",
       "      <td>0 days 00:02:29.840000</td>\n",
       "      <td>0 days 00:01:38.794000</td>\n",
       "      <td>0 days 00:01:32.611000</td>\n",
       "      <td>0 days 00:01:36.011000</td>\n",
       "      <td>69.000000</td>\n",
       "      <td>333.000000</td>\n",
       "      <td>300.000000</td>\n",
       "      <td>344.000000</td>\n",
       "      <td>362.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                            Time          Year     LapNumber  \\\n",
       "count                      22164  22164.000000  22164.000000   \n",
       "mean   0 days 01:54:44.800035192   2022.485788     30.763626   \n",
       "std    0 days 00:32:17.225029250      1.121193     18.344432   \n",
       "min       0 days 00:39:08.419000   2021.000000      1.000000   \n",
       "25%       0 days 01:28:13.891000   2021.000000     15.000000   \n",
       "50%       0 days 01:53:32.523500   2022.000000     30.000000   \n",
       "75%       0 days 02:19:43.326750   2023.000000     45.000000   \n",
       "max       0 days 03:20:47.648000   2024.000000     71.000000   \n",
       "\n",
       "                         LapTime                Sector1Time  \\\n",
       "count                      21470                      21658   \n",
       "mean   0 days 00:01:32.813397251  0 days 00:00:28.815164742   \n",
       "std    0 days 00:00:12.742266127  0 days 00:00:06.851402866   \n",
       "min       0 days 00:01:11.010000     0 days 00:00:18.281000   \n",
       "25%       0 days 00:01:23.029000     0 days 00:00:27.189250   \n",
       "50%       0 days 00:01:33.512000     0 days 00:00:29.187000   \n",
       "75%       0 days 00:01:40.291750     0 days 00:00:30.638000   \n",
       "max       0 days 00:02:29.840000     0 days 00:01:38.794000   \n",
       "\n",
       "                     Sector2Time                Sector3Time      TyreLife  \\\n",
       "count                      22121                      22124  22164.000000   \n",
       "mean   0 days 00:00:39.797198453  0 days 00:00:25.173835246     13.626331   \n",
       "std    0 days 00:00:06.054553871  0 days 00:00:06.702798903      9.292165   \n",
       "min       0 days 00:00:29.991000     0 days 00:00:16.396000      1.000000   \n",
       "25%       0 days 00:00:37.224000     0 days 00:00:21.293000      6.000000   \n",
       "50%       0 days 00:00:39.879000     0 days 00:00:24.026000     12.000000   \n",
       "75%       0 days 00:00:42.034000     0 days 00:00:26.934750     19.000000   \n",
       "max       0 days 00:01:32.611000     0 days 00:01:36.011000     69.000000   \n",
       "\n",
       "            SpeedI1       SpeedI2       SpeedFL       SpeedST  \n",
       "count  18914.000000  22124.000000  21288.000000  20033.000000  \n",
       "mean     260.271968    237.564997    252.587326    296.487196  \n",
       "std       44.508356     40.623522     41.053033     35.907749  \n",
       "min       69.000000     40.000000      3.000000     63.000000  \n",
       "25%      225.000000    217.000000    241.000000    292.000000  \n",
       "50%      282.000000    250.000000    248.000000    301.000000  \n",
       "75%      297.000000    261.000000    282.000000    317.000000  \n",
       "max      333.000000    300.000000    344.000000    362.000000  "
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lap_data_combined.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data Description\n",
    "Our data comes from the FastF1 API, which provides detailed Formula One racing data. Each observation represents a single lap during a race or qualifying session, including:\n",
    "\n",
    "Key Variables:\n",
    "- **Time**: Timestamp of the lap\n",
    "- **Driver**: Driver identifier\n",
    "- **LapTime**: Time taken to complete the lap\n",
    "- **Weather Conditions**:\n",
    "  - TrackTemp: Track temperature in Celsius\n",
    "  - AirTemp: Air temperature in Celsius\n",
    "  - Humidity: Percentage\n",
    "  - Rainfall: Boolean indicating presence of rain\n",
    "- **Performance Metrics**:\n",
    "  - Sector times (1,2,3)\n",
    "  - Speed measurements at various points\n",
    "  - Compound: Tire compound used\n",
    "  - TyreLife: Age of tires in laps\n",
    "\n",
    "Each lap is represented as a fixed-length vector containing these attributes, making it suitable for machine learning algorithms."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data Preprocessing Steps\n",
    "1. Time Conversion:\n",
    "   - Converting lap times from timedelta to seconds\n",
    "   - Standardizing timestamps for weather correlation\n",
    "\n",
    "2. Missing Value Handling:\n",
    "   - Removing incomplete laps\n",
    "   - Handling missing weather data\n",
    "\n",
    "3. Feature Engineering:\n",
    "   - Creating derived features from raw data\n",
    "   - Normalizing numerical values\n",
    "\n",
    "4. Data Integration:\n",
    "   - Merging weather and lap data\n",
    "   - Ensuring temporal alignment of measurements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Time conversion\n",
    "# Function to convert timedelta to datetime\n",
    "def convert_timedelta_to_datetime(df, base_date='2021-01-01'):\n",
    "    if 'Time' in df.columns:\n",
    "        # Create a base datetime and add the timedelta\n",
    "        base = pd.Timestamp(base_date)\n",
    "        if df['Time'].dtype == 'timedelta64[ns]':\n",
    "            df['Time'] = base + df['Time']\n",
    "    return df\n",
    "\n",
    "# Apply conversion to both dataframes\n",
    "weather_data_combined = convert_timedelta_to_datetime(weather_data_combined)\n",
    "lap_data_combined = convert_timedelta_to_datetime(lap_data_combined)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "      <th>Event</th>\n",
       "      <th>Session</th>\n",
       "      <th>AirTemp</th>\n",
       "      <th>Humidity</th>\n",
       "      <th>Pressure</th>\n",
       "      <th>Rainfall</th>\n",
       "      <th>TrackTemp</th>\n",
       "      <th>WindDirection</th>\n",
       "      <th>WindSpeed</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2021-01-01 00:00:43.040</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.9</td>\n",
       "      <td>56.4</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>6</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2021-01-01 00:01:43.040</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.8</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>8</td>\n",
       "      <td>1.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2021-01-01 00:02:43.040</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.8</td>\n",
       "      <td>1014.7</td>\n",
       "      <td>False</td>\n",
       "      <td>30.2</td>\n",
       "      <td>11</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2021-01-01 00:03:43.039</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.7</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>30.2</td>\n",
       "      <td>7</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2021-01-01 00:04:43.041</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.1</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>0</td>\n",
       "      <td>0.9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     Time  Year               Event Session  AirTemp  \\\n",
       "0 2021-01-01 00:00:43.040  2021  Bahrain Grand Prix    Race     20.9   \n",
       "1 2021-01-01 00:01:43.040  2021  Bahrain Grand Prix    Race     20.8   \n",
       "2 2021-01-01 00:02:43.040  2021  Bahrain Grand Prix    Race     20.8   \n",
       "3 2021-01-01 00:03:43.039  2021  Bahrain Grand Prix    Race     20.8   \n",
       "4 2021-01-01 00:04:43.041  2021  Bahrain Grand Prix    Race     20.8   \n",
       "\n",
       "   Humidity  Pressure  Rainfall  TrackTemp  WindDirection  WindSpeed  \n",
       "0      56.4    1014.8     False       29.9              6        1.0  \n",
       "1      56.8    1014.8     False       29.9              8        1.1  \n",
       "2      56.8    1014.7     False       30.2             11        1.0  \n",
       "3      56.7    1014.8     False       30.2              7        1.0  \n",
       "4      56.1    1014.8     False       29.9              0        0.9  "
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Verify the conversion\n",
    "lap_data_combined.head(5)\n",
    "weather_data_combined.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time             0\n",
      "Year             0\n",
      "Event            0\n",
      "Session          0\n",
      "AirTemp          0\n",
      "Humidity         0\n",
      "Pressure         0\n",
      "Rainfall         0\n",
      "TrackTemp        0\n",
      "WindDirection    0\n",
      "WindSpeed        0\n",
      "dtype: int64\n",
      "Time              0\n",
      "Year              0\n",
      "Event             0\n",
      "Session           0\n",
      "Driver            0\n",
      "Team              0\n",
      "LapNumber         0\n",
      "LapTime         694\n",
      "Sector1Time     506\n",
      "Sector2Time      43\n",
      "Sector3Time      40\n",
      "Compound          0\n",
      "TyreLife          0\n",
      "FreshTyre         0\n",
      "SpeedI1        3250\n",
      "SpeedI2          40\n",
      "SpeedFL         876\n",
      "SpeedST        2131\n",
      "dtype: int64\n"
     ]
    }
   ],
   "source": [
    "# Missing value handling\n",
    "# Are there any missing values?\n",
    "print(weather_data_combined.isnull().sum())\n",
    "print(lap_data_combined.isnull().sum())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Remove missing values\n",
    "weather_data_combined = weather_data_combined.dropna()\n",
    "lap_data_combined = lap_data_combined.dropna()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "      <th>Event</th>\n",
       "      <th>Session</th>\n",
       "      <th>AirTemp</th>\n",
       "      <th>Humidity</th>\n",
       "      <th>Pressure</th>\n",
       "      <th>Rainfall</th>\n",
       "      <th>TrackTemp</th>\n",
       "      <th>WindDirection</th>\n",
       "      <th>WindSpeed</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2021-01-01 00:00:43.040</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.9</td>\n",
       "      <td>56.4</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>6</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2021-01-01 00:01:43.040</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.8</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>8</td>\n",
       "      <td>1.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2021-01-01 00:02:43.040</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.8</td>\n",
       "      <td>1014.7</td>\n",
       "      <td>False</td>\n",
       "      <td>30.2</td>\n",
       "      <td>11</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2021-01-01 00:03:43.039</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.7</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>30.2</td>\n",
       "      <td>7</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2021-01-01 00:04:43.041</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>20.8</td>\n",
       "      <td>56.1</td>\n",
       "      <td>1014.8</td>\n",
       "      <td>False</td>\n",
       "      <td>29.9</td>\n",
       "      <td>0</td>\n",
       "      <td>0.9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     Time  Year               Event Session  AirTemp  \\\n",
       "0 2021-01-01 00:00:43.040  2021  Bahrain Grand Prix    Race     20.9   \n",
       "1 2021-01-01 00:01:43.040  2021  Bahrain Grand Prix    Race     20.8   \n",
       "2 2021-01-01 00:02:43.040  2021  Bahrain Grand Prix    Race     20.8   \n",
       "3 2021-01-01 00:03:43.039  2021  Bahrain Grand Prix    Race     20.8   \n",
       "4 2021-01-01 00:04:43.041  2021  Bahrain Grand Prix    Race     20.8   \n",
       "\n",
       "   Humidity  Pressure  Rainfall  TrackTemp  WindDirection  WindSpeed  \n",
       "0      56.4    1014.8     False       29.9              6        1.0  \n",
       "1      56.8    1014.8     False       29.9              8        1.1  \n",
       "2      56.8    1014.7     False       30.2             11        1.0  \n",
       "3      56.7    1014.8     False       30.2              7        1.0  \n",
       "4      56.1    1014.8     False       29.9              0        0.9  "
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Verify the drop\n",
    "lap_data_combined.head(5)\n",
    "weather_data_combined.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "      <th>Event</th>\n",
       "      <th>Session</th>\n",
       "      <th>Driver</th>\n",
       "      <th>Team</th>\n",
       "      <th>LapNumber</th>\n",
       "      <th>LapTime</th>\n",
       "      <th>Sector1Time</th>\n",
       "      <th>Sector2Time</th>\n",
       "      <th>Sector3Time</th>\n",
       "      <th>Compound</th>\n",
       "      <th>TyreLife</th>\n",
       "      <th>FreshTyre</th>\n",
       "      <th>SpeedI1</th>\n",
       "      <th>SpeedI2</th>\n",
       "      <th>SpeedFL</th>\n",
       "      <th>SpeedST</th>\n",
       "      <th>LapTime_seconds</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2021-01-01 00:41:37.134</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0 days 00:02:22.263000</td>\n",
       "      <td>0 days 00:00:45.220000</td>\n",
       "      <td>0 days 00:01:00.086000</td>\n",
       "      <td>0 days 00:00:36.957000</td>\n",
       "      <td>MEDIUM</td>\n",
       "      <td>5.0</td>\n",
       "      <td>False</td>\n",
       "      <td>120.0</td>\n",
       "      <td>134.0</td>\n",
       "      <td>182.0</td>\n",
       "      <td>236.0</td>\n",
       "      <td>142.263</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2021-01-01 00:48:28.044</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>5.0</td>\n",
       "      <td>0 days 00:02:11.534000</td>\n",
       "      <td>0 days 00:01:05.748000</td>\n",
       "      <td>0 days 00:00:41.956000</td>\n",
       "      <td>0 days 00:00:23.830000</td>\n",
       "      <td>HARD</td>\n",
       "      <td>1.0</td>\n",
       "      <td>True</td>\n",
       "      <td>231.0</td>\n",
       "      <td>251.0</td>\n",
       "      <td>275.0</td>\n",
       "      <td>213.0</td>\n",
       "      <td>131.534</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>2021-01-01 00:50:04.721</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>6.0</td>\n",
       "      <td>0 days 00:01:36.677000</td>\n",
       "      <td>0 days 00:00:30.990000</td>\n",
       "      <td>0 days 00:00:41.802000</td>\n",
       "      <td>0 days 00:00:23.885000</td>\n",
       "      <td>HARD</td>\n",
       "      <td>2.0</td>\n",
       "      <td>True</td>\n",
       "      <td>233.0</td>\n",
       "      <td>254.0</td>\n",
       "      <td>275.0</td>\n",
       "      <td>280.0</td>\n",
       "      <td>96.677</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>2021-01-01 00:51:41.675</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>7.0</td>\n",
       "      <td>0 days 00:01:36.954000</td>\n",
       "      <td>0 days 00:00:31.176000</td>\n",
       "      <td>0 days 00:00:41.678000</td>\n",
       "      <td>0 days 00:00:24.100000</td>\n",
       "      <td>HARD</td>\n",
       "      <td>3.0</td>\n",
       "      <td>True</td>\n",
       "      <td>232.0</td>\n",
       "      <td>252.0</td>\n",
       "      <td>274.0</td>\n",
       "      <td>282.0</td>\n",
       "      <td>96.954</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>2021-01-01 00:54:56.129</td>\n",
       "      <td>2021</td>\n",
       "      <td>Bahrain Grand Prix</td>\n",
       "      <td>Race</td>\n",
       "      <td>GAS</td>\n",
       "      <td>AlphaTauri</td>\n",
       "      <td>9.0</td>\n",
       "      <td>0 days 00:01:37.030000</td>\n",
       "      <td>0 days 00:00:31.256000</td>\n",
       "      <td>0 days 00:00:41.911000</td>\n",
       "      <td>0 days 00:00:23.863000</td>\n",
       "      <td>HARD</td>\n",
       "      <td>5.0</td>\n",
       "      <td>True</td>\n",
       "      <td>234.0</td>\n",
       "      <td>248.0</td>\n",
       "      <td>276.0</td>\n",
       "      <td>286.0</td>\n",
       "      <td>97.030</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     Time  Year               Event Session Driver  \\\n",
       "1 2021-01-01 00:41:37.134  2021  Bahrain Grand Prix    Race    GAS   \n",
       "4 2021-01-01 00:48:28.044  2021  Bahrain Grand Prix    Race    GAS   \n",
       "5 2021-01-01 00:50:04.721  2021  Bahrain Grand Prix    Race    GAS   \n",
       "6 2021-01-01 00:51:41.675  2021  Bahrain Grand Prix    Race    GAS   \n",
       "8 2021-01-01 00:54:56.129  2021  Bahrain Grand Prix    Race    GAS   \n",
       "\n",
       "         Team  LapNumber                LapTime            Sector1Time  \\\n",
       "1  AlphaTauri        2.0 0 days 00:02:22.263000 0 days 00:00:45.220000   \n",
       "4  AlphaTauri        5.0 0 days 00:02:11.534000 0 days 00:01:05.748000   \n",
       "5  AlphaTauri        6.0 0 days 00:01:36.677000 0 days 00:00:30.990000   \n",
       "6  AlphaTauri        7.0 0 days 00:01:36.954000 0 days 00:00:31.176000   \n",
       "8  AlphaTauri        9.0 0 days 00:01:37.030000 0 days 00:00:31.256000   \n",
       "\n",
       "             Sector2Time            Sector3Time Compound  TyreLife  FreshTyre  \\\n",
       "1 0 days 00:01:00.086000 0 days 00:00:36.957000   MEDIUM       5.0      False   \n",
       "4 0 days 00:00:41.956000 0 days 00:00:23.830000     HARD       1.0       True   \n",
       "5 0 days 00:00:41.802000 0 days 00:00:23.885000     HARD       2.0       True   \n",
       "6 0 days 00:00:41.678000 0 days 00:00:24.100000     HARD       3.0       True   \n",
       "8 0 days 00:00:41.911000 0 days 00:00:23.863000     HARD       5.0       True   \n",
       "\n",
       "   SpeedI1  SpeedI2  SpeedFL  SpeedST  LapTime_seconds  \n",
       "1    120.0    134.0    182.0    236.0          142.263  \n",
       "4    231.0    251.0    275.0    213.0          131.534  \n",
       "5    233.0    254.0    275.0    280.0           96.677  \n",
       "6    232.0    252.0    274.0    282.0           96.954  \n",
       "8    234.0    248.0    276.0    286.0           97.030  "
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Feature engineering\n",
    "# Create a new column for lap time in seconds\n",
    "lap_data_combined['LapTime_seconds'] = lap_data_combined['LapTime'].dt.total_seconds()\n",
    "# Display the first few rows of the updated DataFrame\n",
    "lap_data_combined.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Weather Data Shape: (3340, 11)\n",
      "Lap Data Shape: (16051, 19)\n",
      "\n",
      "Weather Data Columns:\n",
      "['Time', 'Year', 'Event', 'Session', 'AirTemp', 'Humidity', 'Pressure', 'Rainfall', 'TrackTemp', 'WindDirection', 'WindSpeed']\n",
      "\n",
      "Lap Data Columns:\n",
      "['Time', 'Year', 'Event', 'Session', 'Driver', 'Team', 'LapNumber', 'LapTime', 'Sector1Time', 'Sector2Time', 'Sector3Time', 'Compound', 'TyreLife', 'FreshTyre', 'SpeedI1', 'SpeedI2', 'SpeedFL', 'SpeedST', 'LapTime_seconds']\n",
      "\n",
      "Weather Data Time Range:\n",
      "Start: 2021-01-01 00:00:05.091000\n",
      "End: 2021-01-01 03:22:50.536000\n",
      "\n",
      "Lap Data Time Range:\n",
      "Start: 2021-01-01 00:41:30.825000\n",
      "End: 2021-01-01 03:20:47.648000\n",
      "\n",
      "Merged Data Shape: (16051, 27)\n",
      "\n",
      "Sample of merged data:\n",
      "                     Time  Year               Event Session_x Driver  \\\n",
      "0 2021-01-01 00:41:30.825  2021  Bahrain Grand Prix      Race    VER   \n",
      "1 2021-01-01 00:41:32.424  2021  Bahrain Grand Prix      Race    HAM   \n",
      "2 2021-01-01 00:41:34.055  2021  Bahrain Grand Prix      Race    LEC   \n",
      "3 2021-01-01 00:41:35.424  2021  Bahrain Grand Prix      Race    BOT   \n",
      "4 2021-01-01 00:41:37.134  2021  Bahrain Grand Prix      Race    GAS   \n",
      "\n",
      "              Team  LapNumber                LapTime            Sector1Time  \\\n",
      "0  Red Bull Racing        2.0 0 days 00:02:22.406000 0 days 00:00:45.874000   \n",
      "1         Mercedes        2.0 0 days 00:02:22.712000 0 days 00:00:46.763000   \n",
      "2          Ferrari        2.0 0 days 00:02:21.183000 0 days 00:00:44.935000   \n",
      "3         Mercedes        2.0 0 days 00:02:21.478000 0 days 00:00:44.932000   \n",
      "4       AlphaTauri        2.0 0 days 00:02:22.263000 0 days 00:00:45.220000   \n",
      "\n",
      "             Sector2Time  ... SpeedST LapTime_seconds  Session_y  AirTemp  \\\n",
      "0 0 days 00:01:01.922000  ...   238.0         142.406       Race     20.5   \n",
      "1 0 days 00:01:01.387000  ...   246.0         142.712       Race     20.5   \n",
      "2 0 days 00:01:00.775000  ...   251.0         141.183       Race     20.5   \n",
      "3 0 days 00:01:00.820000  ...   249.0         141.478       Race     20.5   \n",
      "4 0 days 00:01:00.086000  ...   236.0         142.263       Race     20.5   \n",
      "\n",
      "   Humidity  Pressure  Rainfall  TrackTemp  WindDirection WindSpeed  \n",
      "0      54.5    1014.8     False       27.9              8       1.0  \n",
      "1      54.5    1014.8     False       27.9              8       1.0  \n",
      "2      54.5    1014.8     False       27.9              8       1.0  \n",
      "3      54.5    1014.8     False       27.9              8       1.0  \n",
      "4      54.5    1014.8     False       27.9              8       1.0  \n",
      "\n",
      "[5 rows x 27 columns]\n"
     ]
    }
   ],
   "source": [
    "# Data integration\n",
    "# Merge weather and lap data on time and event\n",
    "# First, let's check our data before merging\n",
    "print(\"Weather Data Shape:\", weather_data_combined.shape)\n",
    "print(\"Lap Data Shape:\", lap_data_combined.shape)\n",
    "\n",
    "print(\"\\nWeather Data Columns:\")\n",
    "print(weather_data_combined.columns.tolist())\n",
    "print(\"\\nLap Data Columns:\")\n",
    "print(lap_data_combined.columns.tolist())\n",
    "\n",
    "# Check the time ranges in both datasets\n",
    "print(\"\\nWeather Data Time Range:\")\n",
    "print(\"Start:\", weather_data_combined['Time'].min())\n",
    "print(\"End:\", weather_data_combined['Time'].max())\n",
    "\n",
    "print(\"\\nLap Data Time Range:\")\n",
    "print(\"Start:\", lap_data_combined['Time'].min())\n",
    "print(\"End:\", lap_data_combined['Time'].max())\n",
    "\n",
    "# Merge the data\n",
    "merged_data = pd.merge_asof(\n",
    "    lap_data_combined.sort_values('Time'),\n",
    "    weather_data_combined.sort_values('Time'),\n",
    "    on='Time',\n",
    "    by=['Event', 'Year'],  # Match within same event and year\n",
    "    direction='nearest',\n",
    "    tolerance=pd.Timedelta('1 min')  # Allow matching within 1 minute\n",
    ")\n",
    "\n",
    "print(\"\\nMerged Data Shape:\", merged_data.shape)\n",
    "print(\"\\nSample of merged data:\")\n",
    "print(merged_data.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 83164 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 564032 characters]",
      "text/plain": [
       "<Figure size 1500x1000 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 101948 characters]",
      "text/plain": [
       "<Figure size 1500x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 438084 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 218280 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 45404 characters]",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 146328 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 77184 characters]",
      "text/plain": [
       "<Figure size 1000x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Set up the plotting style\n",
    "plt.rcParams['figure.figsize'] = [12, 6]\n",
    "\n",
    "# 1. Lap Time Distribution by Event\n",
    "plt.figure(figsize=(12, 6))\n",
    "sns.boxplot(data=lap_data_combined, x='Event', y='LapTime_seconds')\n",
    "plt.xticks(rotation=45)\n",
    "plt.title('Lap Time Distribution by Event')\n",
    "plt.xlabel('Event')\n",
    "plt.ylabel('Lap Time (seconds)')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 2. Weather Conditions Impact\n",
    "fig, axes = plt.subplots(2, 2, figsize=(15, 10))\n",
    "sns.scatterplot(data=merged_data, x='TrackTemp', y='LapTime_seconds', ax=axes[0,0])\n",
    "axes[0,0].set_title('Track Temperature vs Lap Time')\n",
    "\n",
    "sns.scatterplot(data=merged_data, x='AirTemp', y='LapTime_seconds', ax=axes[0,1])\n",
    "axes[0,1].set_title('Air Temperature vs Lap Time')\n",
    "\n",
    "sns.scatterplot(data=merged_data, x='Humidity', y='LapTime_seconds', ax=axes[1,0])\n",
    "axes[1,0].set_title('Humidity vs Lap Time')\n",
    "\n",
    "sns.scatterplot(data=merged_data, x='WindSpeed', y='LapTime_seconds', ax=axes[1,1])\n",
    "axes[1,1].set_title('Wind Speed vs Lap Time')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 3. Driver Performance Comparison\n",
    "plt.figure(figsize=(15, 6))\n",
    "sns.boxplot(data=lap_data_combined, x='Driver', y='LapTime_seconds')\n",
    "plt.xticks(rotation=45)\n",
    "plt.title('Lap Time Distribution by Driver')\n",
    "plt.xlabel('Driver')\n",
    "plt.ylabel('Lap Time (seconds)')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 4. Lap Time Evolution Over Race\n",
    "plt.figure(figsize=(12, 6))\n",
    "sns.lineplot(data=lap_data_combined, x='LapNumber', y='LapTime_seconds', hue='Driver')\n",
    "plt.title('Lap Time Evolution During Race')\n",
    "plt.xlabel('Lap Number')\n",
    "plt.ylabel('Lap Time (seconds)')\n",
    "plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 5. Track Temperature Changes\n",
    "plt.figure(figsize=(12, 6))\n",
    "sns.lineplot(data=weather_data_combined, x='Time', y='TrackTemp', hue='Event')\n",
    "plt.title('Track Temperature Evolution')\n",
    "plt.xlabel('Time')\n",
    "plt.ylabel('Track Temperature (°C)')\n",
    "plt.xticks(rotation=45)\n",
    "plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 6. Tire Compound Impact\n",
    "plt.figure(figsize=(10, 6))\n",
    "sns.boxplot(data=lap_data_combined, x='Compound', y='LapTime_seconds')\n",
    "plt.title('Lap Time Distribution by Tire Compound')\n",
    "plt.xlabel('Tire Compound')\n",
    "plt.ylabel('Lap Time (seconds)')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 7. Year-over-Year Comparison\n",
    "plt.figure(figsize=(12, 6))\n",
    "sns.boxplot(data=lap_data_combined, x='Event', y='LapTime_seconds', hue='Year')\n",
    "plt.xticks(rotation=45)\n",
    "plt.title('Lap Time Distribution by Event and Year')\n",
    "plt.xlabel('Event')\n",
    "plt.ylabel('Lap Time (seconds)')\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 8. Weather Correlation Heatmap\n",
    "weather_vars = ['TrackTemp', 'AirTemp', 'Humidity', 'Pressure', 'WindSpeed', 'LapTime_seconds']\n",
    "correlation = merged_data[weather_vars].corr()\n",
    "plt.figure(figsize=(10, 8))\n",
    "sns.heatmap(correlation, annot=True, cmap='coolwarm', center=0)\n",
    "plt.title('Correlation between Weather Variables and Lap Time')\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Modeling Approach\n",
    "This is primarily a regression problem as we're predicting continuous lap times. We plan to use:\n",
    "\n",
    "1. Basic Models:\n",
    "   - Linear Regression (baseline)\n",
    "   - Random Forest Regression\n",
    "   - XGBoost\n",
    "\n",
    "2. Advanced Techniques:\n",
    "   - Cross-validation for model evaluation\n",
    "   - Hyperparameter tuning\n",
    "\n",
    "Challenges:\n",
    "1. Handling weather variability\n",
    "2. Accounting for track-specific characteristics\n",
    "3. Dealing with different race conditions\n",
    "\n",
    "Project Milestones:\n",
    "1. Data Collection & Cleaning (Complete)\n",
    "2. EDA & Feature Engineering (Complete)\n",
    "3. Initial Model Development (Dec 1)\n",
    "4. Model Optimization (Dec 4)\n",
    "5. Final Report Preparation (Dec 8)\n",
    "6. Video Presentation (Dec 12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Project Goals and Expected Outcomes\n",
    "\n",
    "Primary Objectives:\n",
    "1. Create accurate lap time prediction models\n",
    "2. Understand key factors affecting F1 performance\n",
    "3. Develop insights for race strategy optimization\n",
    "\n",
    "Hypotheses:\n",
    "1. Weather conditions significantly impact lap times\n",
    "2. Track temperature has a non-linear relationship with performance\n",
    "3. Different drivers show varying sensitivity to weather conditions\n",
    "\n",
    "Success Metrics:\n",
    "- RMSE < 2 seconds for lap time predictions\n",
    "- R² > 0.8 for our best model\n",
    "- Meaningful insights into weather-performance relationships"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "csci349",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
