{
 "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": 1,
   "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": 2,
   "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": 3,
   "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', 'Belgian Grand Prix', 'United States Grand Prix', 'Mexico City 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",
    "- Belgian: Overcast and cool, with frequent weather changes\n",
    "- United States: Very hot, with high track temperatures\n",
    "- Mexico City: Cool and changeable, with frequent 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": 4,
   "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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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: ['44', '33', '77', '4', '11', '16', '3', '55', '22', '18', '7', '99', '31', '63', '5', '47', '10', '6', '14', '9']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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: ['44', '16', '77', '4', '3', '55', '14', '18', '31', '22', '10', '63', '99', '6', '7', '11', '9', '47', '5', '33']\n",
      "core           INFO \tLoading data for Belgian 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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 Belgian Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '63', '44', '3', '5', '10', '31', '16', '6', '55', '14', '77', '99', '4', '22', '47', '9', '7', '11', '18']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 United States Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "core        WARNING \tDriver  7: Lap timing integrity check failed for 1 lap(s)\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', '3', '77', '55', '4', '22', '5', '99', '18', '7', '63', '6', '47', '9', '14', '31', '10']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2021 Mexico City Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '10', '16', '55', '5', '7', '14', '4', '99', '3', '31', '18', '77', '63', '6', '9', '47', '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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '44', '63', '20', '77', '31', '22', '14', '24', '47', '18', '23', '3', '4', '6', '27', '11', '1', '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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '11', '44', '16', '14', '4', '1', '47', '5', '20', '18', '6', '3', '22', '31', '10', '77', '63', '24', '23']\n",
      "core           INFO \tLoading data for Belgian 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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 Belgian Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '55', '63', '14', '16', '31', '5', '10', '23', '18', '4', '22', '24', '3', '20', '47', '6', '77', '44']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 United States Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '44', '16', '11', '63', '4', '14', '5', '20', '22', '31', '24', '23', '10', '47', '3', '6', '18', '77', '55']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2022 Mexico City Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '44', '11', '63', '55', '16', '3', '31', '4', '77', '10', '23', '24', '5', '18', '47', '20', '6', '14', '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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '14', '55', '44', '18', '63', '77', '10', '23', '22', '2', '20', '21', '27', '24', '4', '31', '16', '81']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '44', '81', '63', '11', '14', '23', '16', '55', '2', '77', '27', '18', '24', '22', '21', '10', '20', '31']\n",
      "core           INFO \tLoading data for Belgian 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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 Belgian Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '44', '14', '63', '4', '31', '18', '22', '10', '77', '24', '23', '20', '3', '2', '27', '55', '81']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 United States Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '55', '11', '63', '10', '18', '22', '23', '2', '27', '77', '24', '20', '3', '14', '81', '31', '44', '16']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2023 Mexico City Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '44', '16', '55', '4', '63', '3', '81', '23', '31', '10', '22', '27', '24', '77', '2', '18', '14', '20', '11']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 Bahrain Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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', '55', '16', '63', '4', '44', '81', '14', '18', '24', '20', '3', '22', '23', '27', '31', '10', '77', '2']\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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 British Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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: ['44', '1', '4', '81', '55', '27', '18', '14', '23', '22', '2', '20', '3', '16', '77', '31', '11', '24', '63', '10']\n",
      "core           INFO \tLoading data for Belgian 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",
      "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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 2024 Belgian Grand Prix - Race\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "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: ['44', '81', '16', '1', '4', '55', '11', '14', '31', '3', '18', '23', '10', '20', '77', '22', '2', '27', '24', '63']\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": [
      "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",
      "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', '4', '81', '63', '11', '27', '30', '43', '20', '10', '14', '22', '18', '23', '77', '31', '24', '44']\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": [
      "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",
      "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', '4', '16', '44', '63', '1', '20', '81', '27', '10', '18', '43', '31', '77', '24', '30', '11', '14', '23', '22']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Weather Data Structure:\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 3364 entries, 0 to 3363\n",
      "Data columns (total 11 columns):\n",
      " #   Column         Non-Null Count  Dtype          \n",
      "---  ------         --------------  -----          \n",
      " 0   Time           3364 non-null   timedelta64[ns]\n",
      " 1   Year           3364 non-null   int64          \n",
      " 2   Event          3364 non-null   object         \n",
      " 3   Session        3364 non-null   object         \n",
      " 4   AirTemp        3364 non-null   float64        \n",
      " 5   Humidity       3364 non-null   float64        \n",
      " 6   Pressure       3364 non-null   float64        \n",
      " 7   Rainfall       3364 non-null   bool           \n",
      " 8   TrackTemp      3364 non-null   float64        \n",
      " 9   WindDirection  3364 non-null   int64          \n",
      " 10  WindSpeed      3364 non-null   float64        \n",
      "dtypes: bool(1), float64(5), int64(2), object(2), timedelta64[ns](1)\n",
      "memory usage: 266.2+ KB\n",
      "None\n",
      "\n",
      "Lap Data Structure:\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 19810 entries, 0 to 19809\n",
      "Data columns (total 18 columns):\n",
      " #   Column       Non-Null Count  Dtype          \n",
      "---  ------       --------------  -----          \n",
      " 0   Time         19810 non-null  timedelta64[ns]\n",
      " 1   Year         19810 non-null  int64          \n",
      " 2   Event        19810 non-null  object         \n",
      " 3   Session      19810 non-null  object         \n",
      " 4   Driver       19810 non-null  object         \n",
      " 5   Team         19810 non-null  object         \n",
      " 6   LapNumber    19810 non-null  float64        \n",
      " 7   LapTime      19478 non-null  timedelta64[ns]\n",
      " 8   Sector1Time  19338 non-null  timedelta64[ns]\n",
      " 9   Sector2Time  19771 non-null  timedelta64[ns]\n",
      " 10  Sector3Time  19773 non-null  timedelta64[ns]\n",
      " 11  Compound     19810 non-null  object         \n",
      " 12  TyreLife     19810 non-null  float64        \n",
      " 13  FreshTyre    19810 non-null  bool           \n",
      " 14  SpeedI1      17083 non-null  float64        \n",
      " 15  SpeedI2      19775 non-null  float64        \n",
      " 16  SpeedFL      19038 non-null  float64        \n",
      " 17  SpeedST      17727 non-null  float64        \n",
      "dtypes: bool(1), float64(6), int64(1), object(5), timedelta64[ns](5)\n",
      "memory usage: 2.6+ 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": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Events per Year:\n",
      "Event  Bahrain Grand Prix  Belgian Grand Prix  British Grand Prix  \\\n",
      "Year                                                                \n",
      "2021                 1028                  60                 970   \n",
      "2022                 1125                 792                 815   \n",
      "2023                 1056                 816                 971   \n",
      "2024                 1129                 841                 961   \n",
      "\n",
      "Event  Mexico City Grand Prix  United States Grand Prix  \n",
      "Year                                                     \n",
      "2021                     1261                      1044  \n",
      "2022                     1379                       992  \n",
      "2023                     1282                      1014  \n",
      "2024                     1215                      1059  \n",
      "\n",
      "Drivers per Event:\n",
      "Driver\n",
      "ALB    5\n",
      "ALO    5\n",
      "BOT    5\n",
      "COL    2\n",
      "DEV    2\n",
      "GAS    5\n",
      "GIO    5\n",
      "HAM    5\n",
      "HUL    5\n",
      "LAT    5\n",
      "LAW    2\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    1074\n",
      "LEC    1060\n",
      "STR    1033\n",
      "VER    1024\n",
      "PER    1004\n",
      "RUS    1003\n",
      "SAI    1001\n",
      "HAM     982\n",
      "BOT     958\n",
      "ALO     951\n",
      "GAS     934\n",
      "OCO     931\n",
      "TSU     914\n",
      "RIC     837\n",
      "MAG     776\n",
      "ZHO     742\n",
      "ALB     716\n",
      "HUL     614\n",
      "LAT     506\n",
      "VET     445\n",
      "MSC     442\n",
      "SAR     430\n",
      "PIA     427\n",
      "RAI     235\n",
      "GIO     234\n",
      "MAZ     177\n",
      "LAW     126\n",
      "COL     126\n",
      "DEV     108\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": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 3364 entries, 0 to 3363\n",
      "Data columns (total 11 columns):\n",
      " #   Column         Non-Null Count  Dtype          \n",
      "---  ------         --------------  -----          \n",
      " 0   Time           3364 non-null   timedelta64[ns]\n",
      " 1   Year           3364 non-null   int64          \n",
      " 2   Event          3364 non-null   object         \n",
      " 3   Session        3364 non-null   object         \n",
      " 4   AirTemp        3364 non-null   float64        \n",
      " 5   Humidity       3364 non-null   float64        \n",
      " 6   Pressure       3364 non-null   float64        \n",
      " 7   Rainfall       3364 non-null   bool           \n",
      " 8   TrackTemp      3364 non-null   float64        \n",
      " 9   WindDirection  3364 non-null   int64          \n",
      " 10  WindSpeed      3364 non-null   float64        \n",
      "dtypes: bool(1), float64(5), int64(2), object(2), timedelta64[ns](1)\n",
      "memory usage: 266.2+ KB\n"
     ]
    }
   ],
   "source": [
    "weather_data_combined.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "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": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weather_data_combined.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "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>3364</td>\n",
       "      <td>3364.000000</td>\n",
       "      <td>3364.000000</td>\n",
       "      <td>3364.000000</td>\n",
       "      <td>3364.000000</td>\n",
       "      <td>3364.000000</td>\n",
       "      <td>3364.000000</td>\n",
       "      <td>3364.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0 days 01:27:15.795649227</td>\n",
       "      <td>2022.415577</td>\n",
       "      <td>22.508621</td>\n",
       "      <td>49.090369</td>\n",
       "      <td>951.933859</td>\n",
       "      <td>34.621344</td>\n",
       "      <td>181.135553</td>\n",
       "      <td>1.495392</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0 days 00:55:08.961025957</td>\n",
       "      <td>1.116340</td>\n",
       "      <td>5.135820</td>\n",
       "      <td>19.590571</td>\n",
       "      <td>86.575596</td>\n",
       "      <td>9.794653</td>\n",
       "      <td>111.188990</td>\n",
       "      <td>1.377857</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>12.400000</td>\n",
       "      <td>16.000000</td>\n",
       "      <td>778.500000</td>\n",
       "      <td>14.500000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0 days 00:42:08.192500</td>\n",
       "      <td>2021.000000</td>\n",
       "      <td>18.500000</td>\n",
       "      <td>36.000000</td>\n",
       "      <td>969.600000</td>\n",
       "      <td>28.100000</td>\n",
       "      <td>99.000000</td>\n",
       "      <td>0.600000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0 days 01:24:10.835500</td>\n",
       "      <td>2022.000000</td>\n",
       "      <td>22.000000</td>\n",
       "      <td>49.000000</td>\n",
       "      <td>992.000000</td>\n",
       "      <td>35.100000</td>\n",
       "      <td>183.000000</td>\n",
       "      <td>1.100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>0 days 02:06:13.047750</td>\n",
       "      <td>2023.000000</td>\n",
       "      <td>27.300000</td>\n",
       "      <td>59.000000</td>\n",
       "      <td>1006.700000</td>\n",
       "      <td>42.100000</td>\n",
       "      <td>286.000000</td>\n",
       "      <td>1.900000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>0 days 04:49:16.818000</td>\n",
       "      <td>2024.000000</td>\n",
       "      <td>31.000000</td>\n",
       "      <td>97.500000</td>\n",
       "      <td>1017.500000</td>\n",
       "      <td>53.100000</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                       3364  3364.000000  3364.000000  3364.000000   \n",
       "mean   0 days 01:27:15.795649227  2022.415577    22.508621    49.090369   \n",
       "std    0 days 00:55:08.961025957     1.116340     5.135820    19.590571   \n",
       "min       0 days 00:00:05.091000  2021.000000    12.400000    16.000000   \n",
       "25%       0 days 00:42:08.192500  2021.000000    18.500000    36.000000   \n",
       "50%       0 days 01:24:10.835500  2022.000000    22.000000    49.000000   \n",
       "75%       0 days 02:06:13.047750  2023.000000    27.300000    59.000000   \n",
       "max       0 days 04:49:16.818000  2024.000000    31.000000    97.500000   \n",
       "\n",
       "          Pressure    TrackTemp  WindDirection    WindSpeed  \n",
       "count  3364.000000  3364.000000    3364.000000  3364.000000  \n",
       "mean    951.933859    34.621344     181.135553     1.495392  \n",
       "std      86.575596     9.794653     111.188990     1.377857  \n",
       "min     778.500000    14.500000       0.000000     0.000000  \n",
       "25%     969.600000    28.100000      99.000000     0.600000  \n",
       "50%     992.000000    35.100000     183.000000     1.100000  \n",
       "75%    1006.700000    42.100000     286.000000     1.900000  \n",
       "max    1017.500000    53.100000     359.000000    10.100000  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weather_data_combined.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 19810 entries, 0 to 19809\n",
      "Data columns (total 18 columns):\n",
      " #   Column       Non-Null Count  Dtype          \n",
      "---  ------       --------------  -----          \n",
      " 0   Time         19810 non-null  timedelta64[ns]\n",
      " 1   Year         19810 non-null  int64          \n",
      " 2   Event        19810 non-null  object         \n",
      " 3   Session      19810 non-null  object         \n",
      " 4   Driver       19810 non-null  object         \n",
      " 5   Team         19810 non-null  object         \n",
      " 6   LapNumber    19810 non-null  float64        \n",
      " 7   LapTime      19478 non-null  timedelta64[ns]\n",
      " 8   Sector1Time  19338 non-null  timedelta64[ns]\n",
      " 9   Sector2Time  19771 non-null  timedelta64[ns]\n",
      " 10  Sector3Time  19773 non-null  timedelta64[ns]\n",
      " 11  Compound     19810 non-null  object         \n",
      " 12  TyreLife     19810 non-null  float64        \n",
      " 13  FreshTyre    19810 non-null  bool           \n",
      " 14  SpeedI1      17083 non-null  float64        \n",
      " 15  SpeedI2      19775 non-null  float64        \n",
      " 16  SpeedFL      19038 non-null  float64        \n",
      " 17  SpeedST      17727 non-null  float64        \n",
      "dtypes: bool(1), float64(6), int64(1), object(5), timedelta64[ns](5)\n",
      "memory usage: 2.6+ MB\n"
     ]
    }
   ],
   "source": [
    "lap_data_combined.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "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>0 days 00:02:04.697000</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 0 days 00:02:04.697000                    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": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lap_data_combined.head(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "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>19810</td>\n",
       "      <td>19810.000000</td>\n",
       "      <td>19810.000000</td>\n",
       "      <td>19478</td>\n",
       "      <td>19338</td>\n",
       "      <td>19771</td>\n",
       "      <td>19773</td>\n",
       "      <td>19810.000000</td>\n",
       "      <td>17083.000000</td>\n",
       "      <td>19775.000000</td>\n",
       "      <td>19038.000000</td>\n",
       "      <td>17727.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0 days 01:52:08.540997677</td>\n",
       "      <td>2022.564664</td>\n",
       "      <td>28.698486</td>\n",
       "      <td>0 days 00:01:38.341967604</td>\n",
       "      <td>0 days 00:00:31.143330178</td>\n",
       "      <td>0 days 00:00:40.651893935</td>\n",
       "      <td>0 days 00:00:27.420627926</td>\n",
       "      <td>12.823069</td>\n",
       "      <td>259.646842</td>\n",
       "      <td>233.138812</td>\n",
       "      <td>236.515075</td>\n",
       "      <td>301.719580</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0 days 00:32:11.194678818</td>\n",
       "      <td>1.100844</td>\n",
       "      <td>17.318220</td>\n",
       "      <td>0 days 00:00:13.032210105</td>\n",
       "      <td>0 days 00:00:05.740951832</td>\n",
       "      <td>0 days 00:00:07.269305744</td>\n",
       "      <td>0 days 00:00:06.211696305</td>\n",
       "      <td>9.062348</td>\n",
       "      <td>45.762868</td>\n",
       "      <td>43.747139</td>\n",
       "      <td>33.113846</td>\n",
       "      <td>32.694864</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:17.774000</td>\n",
       "      <td>0 days 00:00:26.007000</td>\n",
       "      <td>0 days 00:00:29.991000</td>\n",
       "      <td>0 days 00:00:20.139000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>76.000000</td>\n",
       "      <td>40.000000</td>\n",
       "      <td>7.000000</td>\n",
       "      <td>65.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0 days 01:25:39.044750</td>\n",
       "      <td>2022.000000</td>\n",
       "      <td>14.000000</td>\n",
       "      <td>0 days 00:01:30.654250</td>\n",
       "      <td>0 days 00:00:28.862000</td>\n",
       "      <td>0 days 00:00:36.303000</td>\n",
       "      <td>0 days 00:00:23.399000</td>\n",
       "      <td>6.000000</td>\n",
       "      <td>223.000000</td>\n",
       "      <td>185.000000</td>\n",
       "      <td>208.000000</td>\n",
       "      <td>295.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0 days 01:51:00.233000</td>\n",
       "      <td>2023.000000</td>\n",
       "      <td>28.000000</td>\n",
       "      <td>0 days 00:01:37.846500</td>\n",
       "      <td>0 days 00:00:29.728000</td>\n",
       "      <td>0 days 00:00:40.783000</td>\n",
       "      <td>0 days 00:00:25.472000</td>\n",
       "      <td>11.000000</td>\n",
       "      <td>279.000000</td>\n",
       "      <td>250.000000</td>\n",
       "      <td>245.000000</td>\n",
       "      <td>304.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>0 days 02:16:05.674000</td>\n",
       "      <td>2024.000000</td>\n",
       "      <td>42.000000</td>\n",
       "      <td>0 days 00:01:43.256000</td>\n",
       "      <td>0 days 00:00:31.325000</td>\n",
       "      <td>0 days 00:00:42.779500</td>\n",
       "      <td>0 days 00:00:31.346000</td>\n",
       "      <td>18.000000</td>\n",
       "      <td>295.000000</td>\n",
       "      <td>265.000000</td>\n",
       "      <td>250.000000</td>\n",
       "      <td>320.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>0 days 04:27:30.514000</td>\n",
       "      <td>2024.000000</td>\n",
       "      <td>71.000000</td>\n",
       "      <td>0 days 00:04:42.084000</td>\n",
       "      <td>0 days 00:01:38.794000</td>\n",
       "      <td>0 days 00:01:37.122000</td>\n",
       "      <td>0 days 00:01:39.664000</td>\n",
       "      <td>56.000000</td>\n",
       "      <td>357.000000</td>\n",
       "      <td>300.000000</td>\n",
       "      <td>297.000000</td>\n",
       "      <td>362.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                            Time          Year     LapNumber  \\\n",
       "count                      19810  19810.000000  19810.000000   \n",
       "mean   0 days 01:52:08.540997677   2022.564664     28.698486   \n",
       "std    0 days 00:32:11.194678818      1.100844     17.318220   \n",
       "min       0 days 00:39:08.419000   2021.000000      1.000000   \n",
       "25%       0 days 01:25:39.044750   2022.000000     14.000000   \n",
       "50%       0 days 01:51:00.233000   2023.000000     28.000000   \n",
       "75%       0 days 02:16:05.674000   2024.000000     42.000000   \n",
       "max       0 days 04:27:30.514000   2024.000000     71.000000   \n",
       "\n",
       "                         LapTime                Sector1Time  \\\n",
       "count                      19478                      19338   \n",
       "mean   0 days 00:01:38.341967604  0 days 00:00:31.143330178   \n",
       "std    0 days 00:00:13.032210105  0 days 00:00:05.740951832   \n",
       "min       0 days 00:01:17.774000     0 days 00:00:26.007000   \n",
       "25%       0 days 00:01:30.654250     0 days 00:00:28.862000   \n",
       "50%       0 days 00:01:37.846500     0 days 00:00:29.728000   \n",
       "75%       0 days 00:01:43.256000     0 days 00:00:31.325000   \n",
       "max       0 days 00:04:42.084000     0 days 00:01:38.794000   \n",
       "\n",
       "                     Sector2Time                Sector3Time      TyreLife  \\\n",
       "count                      19771                      19773  19810.000000   \n",
       "mean   0 days 00:00:40.651893935  0 days 00:00:27.420627926     12.823069   \n",
       "std    0 days 00:00:07.269305744  0 days 00:00:06.211696305      9.062348   \n",
       "min       0 days 00:00:29.991000     0 days 00:00:20.139000      1.000000   \n",
       "25%       0 days 00:00:36.303000     0 days 00:00:23.399000      6.000000   \n",
       "50%       0 days 00:00:40.783000     0 days 00:00:25.472000     11.000000   \n",
       "75%       0 days 00:00:42.779500     0 days 00:00:31.346000     18.000000   \n",
       "max       0 days 00:01:37.122000     0 days 00:01:39.664000     56.000000   \n",
       "\n",
       "            SpeedI1       SpeedI2       SpeedFL       SpeedST  \n",
       "count  17083.000000  19775.000000  19038.000000  17727.000000  \n",
       "mean     259.646842    233.138812    236.515075    301.719580  \n",
       "std       45.762868     43.747139     33.113846     32.694864  \n",
       "min       76.000000     40.000000      7.000000     65.000000  \n",
       "25%      223.000000    185.000000    208.000000    295.000000  \n",
       "50%      279.000000    250.000000    245.000000    304.000000  \n",
       "75%      295.000000    265.000000    250.000000    320.000000  \n",
       "max      357.000000    300.000000    297.000000    362.000000  "
      ]
     },
     "execution_count": 11,
     "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": 12,
   "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": 13,
   "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": 13,
     "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": 14,
   "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         332\n",
      "Sector1Time     472\n",
      "Sector2Time      39\n",
      "Sector3Time      37\n",
      "Compound          0\n",
      "TyreLife          0\n",
      "FreshTyre         0\n",
      "SpeedI1        2727\n",
      "SpeedI2          35\n",
      "SpeedFL         772\n",
      "SpeedST        2083\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": 15,
   "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": 16,
   "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": 16,
     "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": 17,
   "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": 17,
     "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": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Weather Data Shape: (3364, 11)\n",
      "Lap Data Shape: (14238, 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 04:49:16.818000\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: (14238, 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": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 83940 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 561484 characters]",
      "text/plain": [
       "<Figure size 1500x1000 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 112872 characters]",
      "text/plain": [
       "<Figure size 1500x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 449876 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 119788 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 46568 characters]",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 139768 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 79012 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
}
