From 53e326513fffecbd2a62c4a2f1832dab49ec42fa Mon Sep 17 00:00:00 2001 From: Kedasha Date: Fri, 17 May 2024 15:04:50 -0400 Subject: [PATCH 1/3] explore some data --- Flight_Delay_Prediction.ipynb | 506 ++++++++++++++++++++++++++++++++++ 1 file changed, 506 insertions(+) diff --git a/Flight_Delay_Prediction.ipynb b/Flight_Delay_Prediction.ipynb index e69de29..9d7590a 100644 --- a/Flight_Delay_Prediction.ipynb +++ b/Flight_Delay_Prediction.ipynb @@ -0,0 +1,506 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
YearMonthDayofMonthDayOfWeekCarrierOriginAirportIDOriginAirportNameOriginCityOriginStateDestAirportIDDestAirportNameDestCityDestStateCRSDepTimeDepDelayDepDel15CRSArrTimeArrDelayArrDel15Cancelled
020139161DL15304Tampa InternationalTampaFL12478John F. Kennedy InternationalNew YorkNY153940.018241300
120139231WN14122Pittsburgh InternationalPittsburghPA13232Chicago Midway InternationalChicagoIL71030.07402210
22013976AS14747Seattle/Tacoma InternationalSeattleWA11278Ronald Reagan Washington NationalWashingtonDC810-30.01614-700
320137221OO13930Chicago O'Hare InternationalChicagoIL11042Cleveland-Hopkins InternationalClevelandOH804351.010273310
420135164DL13931Norfolk InternationalNorfolkVA10397Hartsfield-Jackson Atlanta InternationalAtlantaGA545-10.0728-900
\n", + "
" + ], + "text/plain": [ + " Year Month DayofMonth DayOfWeek Carrier OriginAirportID \\\n", + "0 2013 9 16 1 DL 15304 \n", + "1 2013 9 23 1 WN 14122 \n", + "2 2013 9 7 6 AS 14747 \n", + "3 2013 7 22 1 OO 13930 \n", + "4 2013 5 16 4 DL 13931 \n", + "\n", + " OriginAirportName OriginCity OriginState DestAirportID \\\n", + "0 Tampa International Tampa FL 12478 \n", + "1 Pittsburgh International Pittsburgh PA 13232 \n", + "2 Seattle/Tacoma International Seattle WA 11278 \n", + "3 Chicago O'Hare International Chicago IL 11042 \n", + "4 Norfolk International Norfolk VA 10397 \n", + "\n", + " DestAirportName DestCity DestState CRSDepTime \\\n", + "0 John F. Kennedy International New York NY 1539 \n", + "1 Chicago Midway International Chicago IL 710 \n", + "2 Ronald Reagan Washington National Washington DC 810 \n", + "3 Cleveland-Hopkins International Cleveland OH 804 \n", + "4 Hartsfield-Jackson Atlanta International Atlanta GA 545 \n", + "\n", + " DepDelay DepDel15 CRSArrTime ArrDelay ArrDel15 Cancelled \n", + "0 4 0.0 1824 13 0 0 \n", + "1 3 0.0 740 22 1 0 \n", + "2 -3 0.0 1614 -7 0 0 \n", + "3 35 1.0 1027 33 1 0 \n", + "4 -1 0.0 728 -9 0 0 " + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "# Load the dataset\n", + "df = pd.read_csv('data/flights.csv')\n", + "\n", + "# Display the first few lines\n", + "df.head()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
YearMonthDayofMonthDayOfWeekCarrierOriginAirportIDOriginAirportNameOriginCityOriginStateDestAirportIDDestAirportNameDestCityDestStateCRSDepTimeDepDelayDepDel15CRSArrTimeArrDelayArrDel15Cancelled
020139161DL15304Tampa InternationalTampaFL12478John F. Kennedy InternationalNew YorkNY153940.018241300
120139231WN14122Pittsburgh InternationalPittsburghPA13232Chicago Midway InternationalChicagoIL71030.07402210
22013976AS14747Seattle/Tacoma InternationalSeattleWA11278Ronald Reagan Washington NationalWashingtonDC810-30.01614-700
320137221OO13930Chicago O'Hare InternationalChicagoIL11042Cleveland-Hopkins InternationalClevelandOH804351.010273310
420135164DL13931Norfolk InternationalNorfolkVA10397Hartsfield-Jackson Atlanta InternationalAtlantaGA545-10.0728-900
\n", + "
" + ], + "text/plain": [ + " Year Month DayofMonth DayOfWeek Carrier OriginAirportID \\\n", + "0 2013 9 16 1 DL 15304 \n", + "1 2013 9 23 1 WN 14122 \n", + "2 2013 9 7 6 AS 14747 \n", + "3 2013 7 22 1 OO 13930 \n", + "4 2013 5 16 4 DL 13931 \n", + "\n", + " OriginAirportName OriginCity OriginState DestAirportID \\\n", + "0 Tampa International Tampa FL 12478 \n", + "1 Pittsburgh International Pittsburgh PA 13232 \n", + "2 Seattle/Tacoma International Seattle WA 11278 \n", + "3 Chicago O'Hare International Chicago IL 11042 \n", + "4 Norfolk International Norfolk VA 10397 \n", + "\n", + " DestAirportName DestCity DestState CRSDepTime \\\n", + "0 John F. Kennedy International New York NY 1539 \n", + "1 Chicago Midway International Chicago IL 710 \n", + "2 Ronald Reagan Washington National Washington DC 810 \n", + "3 Cleveland-Hopkins International Cleveland OH 804 \n", + "4 Hartsfield-Jackson Atlanta International Atlanta GA 545 \n", + "\n", + " DepDelay DepDel15 CRSArrTime ArrDelay ArrDel15 Cancelled \n", + "0 4 0.0 1824 13 0 0 \n", + "1 3 0.0 740 22 1 0 \n", + "2 -3 0.0 1614 -7 0 0 \n", + "3 35 1.0 1027 33 1 0 \n", + "4 -1 0.0 728 -9 0 0 " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# find all the null values and replace them\n", + "null_values = df.isnull()\n", + "\n", + "# replace the null values with 0\n", + "df.fillna(0, inplace=True)\n", + "\n", + "# normalize the data by removing outliers\n", + "\n", + "# Calculate the z-scores of DepDelay and ArrDelay\n", + "z_scores = (df[['DepDelay', 'ArrDelay']] - df[['DepDelay', 'ArrDelay']].mean()) / df[['DepDelay', 'ArrDelay']].std()\n", + "\n", + "# calculate the absolute z-scores\n", + "z_scores = z_scores.abs()\n", + "\n", + "# get the rows with the outliers and remove them\n", + "outliers = z_scores[(z_scores['DepDelay'] > 3) | (z_scores['ArrDelay'] > 3)].index\n", + "df = df.drop(outliers)\n", + "\n", + "# Display the first few lines\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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ls2cO3cuyetff/11kyVLFufXPTkvvfSSkWR27tx5yyzXLVu2zLz22mtm+vTpZtmyZWbWrFmmefPmxs/Pz/z111/O5ZYsWeL8fWnRooX5+eefzdy5c83p06dN+/btjbe3twkPDzdDhw41v/32m1m4cKExxpj27dubsLCwJNt88cUXjbe3t3nttdfMggULzLfffmtKlixpcufObY4dO+ZcrlatWiZHjhwmNDTUfPHFF2bJkiVm2bJlKdovAPcWChOATO+bb74xksxXX31ljDHm/Pnzxt/f3zzyyCPOZbZu3WokmXHjxiV57YMPPmgqV67sfD506FDj4eFh1q1bl2S56dOnG0lm/vz5zmmSTFBQkDlz5swt8yUkJJirV6+a999/3+TMmdP55nv79u1GknnjjTeSLP/dd98ZSUnelL/88svG39/fHDx4MMmyn3zyiZFktm/ffssMxhhTt25dkyVLFnP27FljjDETJkwwkkxERESS5a4XpnffffemdYSFhRlPT0+za9euZOfdmPnnn382ksyiRYuc065du2by5ctnnn76acuc165dM1evXjX16tUzTz75ZJJ5qVWY3njjDSPJ/PHHH8YY177v/91Pq/ydO3c2FStWdE5PSEgwhQsXNk888USS5Rs3bmyKFCmSpJQlJywszDgcDrN58+Yk0+vXr28CAwPNxYsXjTHG7N2713h4eJgRI0Y4l7l8+bLJmTOn6dix4y230ahRIyPJxMXF3XI5K9euXTNXrlwxxYoVM71793ZOv16YatasedNr2rdvbySZyMjIZOfdWJhWr15tJJlPP/00yXKHDx82fn5+pl+/fs5ptWrVMpLMb7/9dkf7AuDewSl5ADK9iIgI+fn5qVWrVpIkf39/PfPMM1qxYoV2794tSSpXrpwqV66sCRMmOF+3c+dOrV27NslpOnPnzlXZsmVVoUIFXbt2zflo2LChHA6Hli5dmmTbdevWVXBw8E2ZFi9erEcffVRBQUHy9PSUt7e33n33XZ0+fVonTpyQJC1btkyS1LJlyySvbdGixU3XdcydO1d16tRRvnz5kuRq3LhxknVZ2b9/v5YsWaKnnnpK2bNnlyQ988wzCggISPa0PEl6+umnk51evnx5FS9e/Jbbk/49dStPnjxJvuYLFy7U0aNHbzo16quvvlKlSpWUJUsWeXl5ydvbW7/99pt27tx52+3cCfOf0+Jc/b7/148//qgaNWrI39/fmT8iIiJJfg8PD3Xv3l1z587VoUOHJP07wMKCBQvUtWtXORyO2+YuU6aM7r///iTTWrdurdjYWOfodYULF1azZs00evRo535+++23On36tLp3737bbbji2rVrGjJkiEqXLi0fHx95eXnJx8dHu3fvTvZ7Z/Uzdbt5182dO1cOh0Nt2rRJ8n3KkyeP7r///pu+T8HBwapbt67L+wXg3kJhApCp7dmzR8uXL1fTpk1ljNG5c+d07tw5tWjRQlLSa3Q6deqk1atX66+//pIkTZgwQb6+vnruueecyxw/flxbt26Vt7d3kkdAQICMMTp16lSS7efNm/emTGvXrlWDBg0kSV9//bVWrVqldevW6e2335b07yAJknT69GlJ/w5OcCMvLy/lzJkzybTjx49rzpw5N+UqU6aMJN2U678iIyNljFGLFi2cX6OrV6/q8ccf16pVq5xfk9vt262m/5eXl5fatm2rWbNm6dy5c5KkiRMnKm/evGrYsKFzueHDh6tLly6qWrWqZsyYoTVr1mjdunVq1KiR82uV2g4ePChJypcvnyTXv+83mjlzplq2bKn8+fNrypQpWr16tdatW6dOnTopLi4uybKdOnWSn5+fvvrqK0nSl19+KT8/vxRfW5MnTx7Ladd/niSpZ8+e2r17t6KiopzbqVatmipVqnTL9RcsWFDSvwU7Jfr06aMBAwaoefPmmjNnjv744w+tW7dO999/f7LfO6ufnaxZsyowMPC22zt+/LiMMcqdO/dN36s1a9ak6PcTAP6LUfIAZGrXi8D06dM1ffr0m+ZPmjRJH374oTw9PfXcc8+pT58+mjhxogYPHqzJkyerefPmSY4QhYSEyM/Pz/KoS0hISJLnyR0VmDZtmry9vTV37lxlyZLFOX327NlJlrteio4fP678+fM7p1+7di3Jm9/r2y1fvrwGDx6cbK7rb/yTk5iYqIkTJ0qSnnrqqWSXiYyM1EcffZRkmtURj5QcCbmuY8eO+vjjjzVt2jQ9++yz+vnnn9WrVy95eno6l5kyZYpq166tMWPGJHnt+fPnU7wdV1y+fFm//vqrihQpogIFCkhy/ft+oylTpqhQoUL6/vvvk3xt4uPjb1o2KChI7du31/jx49W3b19NmDBBrVu3dh71u51jx45ZTruxZNetW1dly5bVqFGj5O/vr40bN2rKlCm3XX/Dhg01btw4zZ49W2+++eZtl58yZYratWunIUOGJJl+6tSpZPfpbn+mQkJC5HA4tGLFCvn6+t40/7/TXPlZBXDvojAByLQSEhI0adIkFSlSxDlc9o3mzp2rTz/9VL/88ouaNWum4OBgNW/eXN98842qVaumY8eO3fTJfrNmzTRkyBDlzJlThQoVuqNc14dKvrEUXL58WZMnT06yXM2aNSVJ33//fZJP/qdPn37TyHfNmjXT/PnzVaRIkWRPAbyVhQsX6p9//lG3bt2cR95u1L17d33zzTcaMmRIskM8341SpUqpatWqmjBhghISEhQfH6+OHTsmWcbhcNz0Rnfr1q1avXq1QkNDUzVPQkKCunfvrtOnT2vo0KHO6XfzfXc4HPLx8Uny5vzYsWM3jZJ3XY8ePTR69Gjn0T5XTpPbvn27tmzZkuS0vG+//VYBAQE3HT3q0aOHXnnlFcXExCh37tx65plnbrv+J554QuXKldPQoUPVrFmzZEfKW7hwoR555BFlzZo12e/dvHnzdOTIERUtWjTF+5VSzZo107Bhw3TkyJGbTmUFgDtFYQKQaf3yyy86evSo/ve//6l27do3zb/+CXtERISaNWsm6d9Tor7//nt1795dBQoU0KOPPprkNb169dKMGTNUs2ZN9e7dW+XLl1diYqIOHTqkRYsW6bXXXrvt/Z2aNm2q4cOHq3Xr1nrppZd0+vRpffLJJze9sSxTpoyee+45ffrpp/L09FTdunW1fft2ffrppwoKCpKHx/+dVf3+++8rKipK1atXV48ePVSiRAnFxcXpwIEDmj9/vr766ivn0ZL/ioiIkJeXl956661kj0S9/PLL6tGjh+bNm6cnnnjilvt2Jzp16qSXX35ZR48eVfXq1VWiRIkk85s1a6YPPvhAAwcOVK1atbRr1y69//77KlSoUIqHTE/O8ePHtWbNGhljdP78eW3btk3ffPONtmzZot69e+vFF190Lns33/frw6x37dpVLVq00OHDh/XBBx8ob968zmvoblS8eHE1atRIv/zyix5++OGbrkm6lXz58unxxx/Xe++9p7x582rKlCmKiorS//73v5vuL9SmTRv1799fy5cv1zvvvCMfH5/brt/T01OzZs1SgwYNVK1aNXXp0kV16tRRtmzZdPDgQU2fPl1z5szR2bNnnfs+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Tdd/YFjTNF0/cKdSVJg2bdqUopVZ3dQWAAAAANxRigrTkiVL0joHAAAAAGQ4XMMEAAAAABZSdITpv9atW6cff/xRhw4d0pUrV5LMmzlzZqoEAwAAAAC7uXyEadq0aapRo4Z27NihWbNm6erVq9qxY4cWL16soKCgtMgIAAAAALZwuTANGTJEI0aM0Ny5c+Xj46PPPvtMO3fuVMuWLVWwYMG0yAgAAAAAtnC5MO3du1dNm/477KOvr68uXrwoh8Oh3r17a9y4cakeEAAAAADs4nJhypEjh86fPy9Jyp8/v7Zt2yZJOnfunC5dupS66QAAAADARi4P+vDII48oKipK5cqVU8uWLdWzZ08tXrxYUVFRqlevXlpkBAAAAABbuFyYRo0apbi4OElS//795e3trZUrV+qpp57SgAEDUj0gAAAAANjF5cKUI0cO5789PDzUr18/9evXL1VDAQAAAEBG4PI1THXq1FFERIRiYmLSIg8AAAAAZBguF6Zy5crpnXfeUZ48efT0009r9uzZN928FgAAAAAyA5cL0+eff64jR47op59+UkBAgNq3b688efLopZde0rJly9IiIwAAAADYwuXCJP177VKDBg00ceJEHT9+XGPHjtXatWtVt27d1M4HAAAAALZxedCHGx07dkzTpk3TlClTtHXrVj3wwAOplQsAAAAAbOfyEabY2FhNmDBB9evXV2hoqMaMGaPHHntMf//9t/7444+0yAgAAAAAtnD5CFPu3LkVHBysli1basiQIRxVAgAAAJBpuVyYfvrpJz366KPy8Lijy58AAAAAwG24XJgaNGiQFjkAAAAAIMNJUWGqVKmSfvvtNwUHB6tixYpyOByWy27cuDHVwgEAAACAnVJUmJ544gn5+vpKkpo3b56WeQAAAAAgw0hRYRo4cKAkKSEhQbVr11b58uUVHBycpsEAAAAAwG4ujdzg6emphg0b6ty5c2kUBwAAAAAyDpeHuitXrpz27duXFlkAAAAAIENxuTANHjxYffv21dy5cxUdHa3Y2NgkDwAAAADILFweVrxRo0aSpMcffzzJaHnGGDkcDiUkJKReOgAAAACwkcuFacmSJWmRI8VGjx6tjz/+WNHR0SpTpoxGjhypRx55xNZMAAAAADInlwrT1atX9d5772ns2LEqXrx4WmWy9P3336tXr14aPXq0atSoobFjx6px48basWOHChYsmO55AAAAAGRuLl3D5O3trW3btt3yxrVpafjw4ercubNeeOEFlSpVSiNHjlRoaKjGjBljSx4AAAAAmZvLgz60a9dOERERaZHllq5cuaINGzaoQYMGSaY3aNBAv//+e7KviY+PZ1AKAAAAAHfM5WuYrly5ovHjxysqKkpVqlRRtmzZkswfPnx4qoW70alTp5SQkKDcuXMnmZ47d24dO3Ys2dcMHTpUgwYNuqvthr85765efzsHhjVN0/WndX7J/feB/Lfn7vvg7vkl998H8t+eu+8D+W/P3fchPb5Gac3d94H89nC5MG3btk2VKlWSJP3999+pHuh2/ns64PXR+ZLTv39/9enTx/k8NjZWoaGhaZoPAAAAQObhNqPkhYSEyNPT86ajSSdOnLjpqNN1vr6+8vX1TY94AAAAADIhl69hSk5iYqLmzJmj5s2bp8bqkuXj46PKlSsrKioqyfSoqChVr149zbYLAAAA4N7l8hGmG+3evVuRkZGaNGmSzp49q4YNG6ZWrmT16dNHbdu2VZUqVVStWjWNGzdOhw4d0iuvvJKm2wUAAABwb3K5MF2+fFk//PCDIiIitGbNGiUkJGjEiBHq1KmT/P390yKj07PPPqvTp0/r/fffV3R0tMqWLav58+crLCwsTbcLAAAA4N6U4lPy1q5dq5deekl58uTRqFGj9PTTT+vw4cPy8PDQo48+muZl6bquXbvqwIEDio+P14YNG1SzZs102S4AAACAe0+KjzBVr15dr776qtauXasSJUqkZSYAAAAAyBBSXJjq1q2riIgInThxQm3btlXDhg0th/MGAAAAgMwgxYVp0aJFOnz4sCZMmKAuXbro8uXLevbZZyXdfG8kAAAAJOWuN+0E7nUuDSseGhqqd999V/v379fkyZN14sQJeXl56YknntBbb72ljRs3plVOAAAAAEh3d3wfpvr16+u7777T0aNH9eqrr+qXX37RAw88kJrZAAAAAMBWd33j2uDgYL366qvatGmT1q1blxqZAAAAACBDuOvCdKNKlSql5uoAAAAAwFapWpgAAAAAIDOhMAEAAACABQoTAAAAAFi4o8J07do1/frrrxo7dqzOnz8vSTp69KguXLiQquEAAAAAwE4pvnHtdQcPHlSjRo106NAhxcfHq379+goICNBHH32kuLg4ffXVV2mREwAAAADSnctHmHr27KkqVaro7Nmz8vPzc05/8skn9dtvv6VqOAAAAACwk8tHmFauXKlVq1bJx8cnyfSwsDAdOXIk1YIBAAAAgN1cLkyJiYlKSEi4afo///yjgICAVAkFAABwowPDmtodAcA9yuVT8urXr6+RI0c6nzscDl24cEEDBw5UkyZNUjMbAAAAANjK5SNMI0aMUJ06dVS6dGnFxcWpdevW2r17t0JCQvTdd9+lRUYAAAAAsIXLhSlfvnzavHmzvvvuO23cuFGJiYnq3Lmznn/++SSDQAAAAACAu3O5MEmSn5+fOnXqpE6dOqV2HgAAAADIMFwuTD///HOy0x0Oh7JkyaKiRYuqUKFCdx0MAAAAAOzmcmFq3ry5HA6HjDFJpl+f5nA49PDDD2v27NkKDg5OtaAAAAAAkN5cHiUvKipKDzzwgKKiohQTE6OYmBhFRUXpwQcf1Ny5c7V8+XKdPn1affv2TYu8AAAAAJBuXD7C1LNnT40bN07Vq1d3TqtXr56yZMmil156Sdu3b9fIkSO5vgkAAACA23P5CNPevXsVGBh40/TAwEDt27dPklSsWDGdOnXq7tMBAAAAgI1cLkyVK1fW66+/rpMnTzqnnTx5Uv369dMDDzwgSdq9e7cKFCiQeikBAAAAwAYun5IXERGhJ554QgUKFFBoaKgcDocOHTqkwoUL66effpIkXbhwQQMGDEj1sAAAAACQnlwuTCVKlNDOnTu1cOFC/f333zLGqGTJkqpfv748PP49YNW8efPUzgkAAAAA6e6OblzrcDjUqFEjNWrUKLXzAAAAAECGcUeF6eLFi1q2bJkOHTqkK1euJJnXo0ePVAkGAAAAAHZzuTBt2rRJTZo00aVLl3Tx4kXlyJFDp06dUtasWZUrVy4KEwAAAIBMw+VR8nr37q3HHntMZ86ckZ+fn9asWaODBw+qcuXK+uSTT9IiIwAAAADYwuXCtHnzZr322mvy9PSUp6en4uPjFRoaqo8++khvvfVWWmQEAAAAAFu4XJi8vb3lcDgkSblz59ahQ4ckSUFBQc5/AwAAAEBm4PI1TBUrVtT69etVvHhx1alTR++++65OnTqlyZMnq1y5cmmREQAAAABs4fIRpiFDhihv3rySpA8++EA5c+ZUly5ddOLECY0bNy7VAwIAAACAXVw6wmSM0X333acyZcpIku677z7Nnz8/TYIBAAAAgN1cOsJkjFGxYsX0zz//pFUeAAAAAMgwXDrC5OHhoWLFiun06dMqVqxYWmUCAACp7MCwpnZHAAC35PI1TB999JFef/11bdu2LS3yAAAAAECG4fIoeW3atNGlS5d0//33y8fHR35+fknmnzlzJtXCAQAAAICdXC5MI0eOTIMYAAAAAJDxuFyY2rdvnxY5bmvw4MGaN2+eNm/eLB8fH507d86WHAAAAADuHS5fwyRJe/fu1TvvvKPnnntOJ06ckCQtWLBA27dvT9VwN7py5YqeeeYZdenSJc22AQAAAAA3crkwLVu2TOXKldMff/yhmTNn6sKFC5KkrVu3auDAgake8LpBgwapd+/eKleuXJptAwAAAABu5HJhevPNN/Xhhx8qKipKPj4+zul16tTR6tWrUzXc3YqPj1dsbGySBwAAAACklMuF6c8//9STTz550/T77rtPp0+fTpVQqWXo0KEKCgpyPkJDQ+2OBAAAAMCNuFyYsmfPrujo6Jumb9q0Sfnz53dpXe+9954cDsctH+vXr3c1olP//v0VExPjfBw+fPiO1wUAAADg3uPyKHmtW7fWG2+8oR9//FEOh0OJiYlatWqV+vbtq3bt2rm0ru7du6tVq1a3XCY8PNzViE6+vr7y9fW949cDAAAAuLe5XJgGDx6sDh06KH/+/DLGqHTp0kpISFDr1q31zjvvuLSukJAQhYSEuBoBAAAAANKFy4XJ29tbU6dO1fvvv69NmzYpMTFRFStWVLFixdIin9OhQ4d05swZHTp0SAkJCdq8ebMkqWjRovL390/TbQMAAAC4N7lcmJYtW6ZatWqpSJEiKlKkSFpkSta7776rSZMmOZ9XrFhRkrRkyRLVrl073XIAAAAAuHe4XJjq16+vPHnyqHXr1mrTpo3Kli2bFrluMnHiRE2cODFdtgUAwI0ODGtqdwQAgE1cHiXv6NGj6tevn1asWKHy5curfPny+uijj/TPP/+kRT4AAAAAsI3LhSkkJETdu3fXqlWrtHfvXj377LP65ptvFB4errp166ZFRgAAAACwhcuF6UaFChXSm2++qWHDhqlcuXJatmxZauUCAAAAANvdcWFatWqVunbtqrx586p169YqU6aM5s6dm5rZAAAAAMBWLg/68NZbb+m7777T0aNH9eijj2rkyJFq3ry5smbNmhb5AAAAAMA2LhempUuX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TAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABa87A4A3M6BYU3tjgAAAIB7FEeYAAAAAMAChQkAAAAALFCYAAAAAMAChQkAAAAALFCYAAAAAMAChQkAAAAALFCYAAAAAMAChQkAAAAALFCYAAAAAMAChQkAAAAALFCYAAAAAMAChQkAAAAALFCYAAAAAMAChQkAAAAALHjZHQBp68CwpnZHAAAAANwWR5gAAAAAwAKFCQAAAAAsuF1hio+PV4UKFeRwOLR582a74wAAAADIxNyuMPXr10/58uWzOwYAAACAe4BbFaZffvlFixYt0ieffGJ3FAAAAAD3ALcZJe/48eN68cUXNXv2bGXNmjVFr4mPj1d8fLzzeWxsrMvbZZQ5AAAA4N7lFkeYjDHq0KGDXnnlFVWpUiXFrxs6dKiCgoKcj9DQ0DRMCQAAACCzsbUwvffee3I4HLd8rF+/Xl988YViY2PVv39/l9bfv39/xcTEOB+HDx9Ooz0BAAAAkBk5jDHGro2fOnVKp06duuUy4eHhatWqlebMmSOHw+GcnpCQIE9PTz3//POaNGlSirYXGxuroKAgxcTEKDAw8K6yAwAAAHBfKe0GthamlDp06FCS64+OHj2qhg0bavr06apataoKFCiQovVQmAAAAABIKe8GbjHoQ8GCBZM89/f3lyQVKVIkxWUJAAAAAFzlFoM+AAAAAIAd3OII03+Fh4fLDc4kBAAAAODmOMIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABggcIEAAAAABYoTAAAAABgwcvuAOnJGCNJio2NtTkJAAAAADtd7wTXO4KVe6ownT9/XpIUGhpqcxIAAAAAGcH58+cVFBRkOd9hblepMpHExEQdPXpUAQEBcjgcqb7+2NhYhYaG6vDhwwoMDEz19ac1d88vuf8+uHt+yf33wd3zS+6/D+S3n7vvg7vnl9x/H9w9v+T+++Du+aW03wdjjM6fP698+fLJw8P6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9u2rmTNnav78+TYnvbVdu3Zp1apVioiI0AMPPKDixYurTZs2kuQ2vwvSv0O4T5gwQdOnT1dCQoJatGihDz/8MMP/PyRJ4eHhGjRokN577z0tXLhQkZGRatOmjXr16qWnnnrqth+O2G3AgAFq166dvL291aNHD/Xu3VunT59WqVKltGvXLg0cOFBt27a1O6aldu3aqVu3btq+fbsWL16skiVLqnLlys75v//+u8qWLWtjwlurU6eOhgwZohkzZiQ7f9iwYapdu3b6hnJBwYIFlStXLrVp00adO3dWqVKl7I50R25XqoOCgtSuXbt0SnNnQkJCdODAAcvbGezfv1+5cuVK51Qp89BDD8nPz09dunRReHi4vv3222SX69GjRzonS7nmzZvrlVde0ccffyxfX1998MEHqlWrlvMDp127dil//vz2hLPluBYynD179pi3337bFChQwDgcDtO6dWuzaNEitx70wR2dO3fOfPnll6ZixYoZ/tSFIUOG3HL+wYMHzaOPPppOaVLH+fPnzbhx48xDDz1kHA6HqV27thk3bpw5ceKE3dEsDR482BQrVsx4eHiYBx980Hz11VcmJibG7lh37fTp02bkyJEZ+lS2G02fPt0UKFDAeHh4GIfD4XxkyZLF9OrVK0P/X5qQkGDeeecdU6FCBdOoUaObBqho0aKFGT9+vE3pbm/79u3G39/fVK1a1Xz//fdmy5YtZsuWLea7774zDz74oPH39zfbtm2zO6algICADP31Tam9e/cmOa3ZHXXq1MnUrFnTeQ3ijeLi4kytWrVMx44dbUh2e2FhYSY8PPyWj0KFCtkd85bOnz9vWrZsaby8vIzD4TDVq1dPcorewoULzQ8//GBLNocxxthT1dxfdHS0xowZo5UrVyo6Olqenp4qVKiQmjdvrg4dOrjlaW6JiYlasGCBIiMjNWfOHAUEBOjUqVN2x7KUmJioiRMnaubMmTpw4IAcDocKFy6sp59+Wm3btnWbIwSLFy9WZGSkZs6cqbCwMD399NN6+umnk5zWk9F4eHioYsWKeuGFF9S6desMfcrOndixY4ciIiI0ZcoUnTlzJsPey+W+++5zfjKdkY8CuCImJkZTp07V+PHjtWXLFiUkJNgdKUUSEhK0YcMG7d+/X4mJicqbN68qV66sgIAAu6NlemvWrFHnzp21c+dOORwOXX9rU7Jk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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "# Calculate the average arrival delay by carrier and sort\n", + "avg_delay_by_carrier = df.groupby('Carrier')['ArrDelay'].mean().sort_values()\n", + "\n", + "# Create a bar chart\n", + "avg_delay_by_carrier.plot(kind='bar', figsize=(10, 6))\n", + "\n", + "# Set the title and labels\n", + "plt.title('Average Arrival Delay by Carrier')\n", + "plt.xlabel('Carrier')\n", + "plt.ylabel('Average Arrival Delay')\n", + "\n", + "# Show the plot\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "q: what does CRSDepTime mean?\n", + "a: The scheduled departure time" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 183b783d89b84e9c103b0d3876a39b7c3cc5b16b Mon Sep 17 00:00:00 2001 From: Kedasha Date: Fri, 17 May 2024 15:10:27 -0400 Subject: [PATCH 2/3] Update Flight_Delay_Prediction.ipynb and add test_server.py --- Flight_Delay_Prediction.ipynb | 50 +++++++++++++++++++++++++++++++++-- server/test_server.py | 34 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 server/test_server.py diff --git a/Flight_Delay_Prediction.ipynb b/Flight_Delay_Prediction.ipynb index 9d7590a..17377b7 100644 --- a/Flight_Delay_Prediction.ipynb +++ b/Flight_Delay_Prediction.ipynb @@ -215,7 +215,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -411,7 +411,7 @@ "4 -1 0.0 728 -9 0 0 " ] }, - "execution_count": 8, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -480,6 +480,52 @@ "q: what does CRSDepTime mean?\n", "a: The scheduled departure time" ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy: 0.8619350139602638\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.metrics import accuracy_score\n", + "\n", + "# Convert 'DayOfWeek' and 'DestAirportID' to categorical variables\n", + "df['DayOfWeek'] = df['DayOfWeek'].astype('category')\n", + "df['DestAirportID'] = df['DestAirportID'].astype('category')\n", + "\n", + "# Create 'IsDelayed' column\n", + "df['IsDelayed'] = df['ArrDel15'].apply(lambda x: 1 if x > 0 else 0)\n", + "\n", + "# Define features and target\n", + "X = df[['DayOfWeek', 'DestAirportID']]\n", + "y = df['IsDelayed']\n", + "\n", + "# Split the data into training and testing sets\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n", + "\n", + "# Initialize a Logistic Regression model\n", + "model = LogisticRegression()\n", + "\n", + "# Fit the model with the training data\n", + "model.fit(X_train, y_train)\n", + "\n", + "# Predict the target for the testing data\n", + "y_pred = model.predict(X_test)\n", + "\n", + "# Calculate the accuracy of the model\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "print(f'Accuracy: {accuracy}')" + ] } ], "metadata": { diff --git a/server/test_server.py b/server/test_server.py new file mode 100644 index 0000000..00dfb28 --- /dev/null +++ b/server/test_server.py @@ -0,0 +1,34 @@ +import unittest +from server import app + +class TestServer(unittest.TestCase): + + def setUp(self): + self.app = app.test_client() + + def test_home(self): + response = self.app.get('/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data.decode(), "Let's build a flight delay prediction api!") + + def test_predict(self): + response = self.app.get('/predict?airport_id=123&day_of_week=1') + self.assertEqual(response.status_code, 200) + data = response.get_json() + self.assertIn('model_prediction', data) + self.assertIn('confidence_percent', data) + self.assertIn('delayed_percent', data) + self.assertIn('interpretation', data) + + def test_airports(self): + response = self.app.get('/airports') + self.assertEqual(response.status_code, 200) + data = response.get_json() + self.assertIn('airports', data) + airports = data['airports'] + self.assertIsInstance(airports, list) + self.assertTrue(all(isinstance(airport, dict) for airport in airports)) + self.assertTrue(all('id' in airport and 'name' in airport for airport in airports)) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From da7dc7a0df5448a6e1a6462b1eea3cfc301b8c01 Mon Sep 17 00:00:00 2001 From: Kedasha Kerr <47188731+LadyKerr@users.noreply.github.com> Date: Sat, 18 May 2024 09:28:29 -0400 Subject: [PATCH 3/3] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2190f4e..ba6ae74 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,6 @@ Build an ML Model live with GitHub Copilot - [Prompt crafting with GitHub Copilot](https://www.youtube.com/watch?v=GPLUGJsVx0s) --- -## You can find the slides in [this pdf](https://github.com/LadyKerr/gh-copilot-talk/blob/main/pycon/gh-copilot-vscode.pdf) +## You can find the slides in [this pdf](https://github.com/LadyKerr/gh-copilot-talk/blob/main/pycon/pycon-copilot.pdf) -![slide-1](https://github.com/LadyKerr/try-streamlit/assets/47188731/1af40df6-89a8-41bd-b7e0-dfa48682e652) \ No newline at end of file +![slide-1](https://github.com/LadyKerr/try-streamlit/assets/47188731/1af40df6-89a8-41bd-b7e0-dfa48682e652)