{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Big Data Derby is (not) decadent and depraved","metadata":{}},{"cell_type":"markdown","source":"**TABLE OF CONTENTS**<br>\n\n* [1. Editor's Note](#chapter_1)   \n* [2. Data Preparation](#chapter_2)\n* [3. Data Exploration](#chapter_3)\n* [4. Winning Odds](#chapter_4)\n* [5. Track Conditions](#chapter_5)\n* [6. The King of Aqueduct](#chapter_6)","metadata":{}},{"cell_type":"markdown","source":"### 1. Editor's note <a class=\"anchor\" id=\"chapter_1\"></a>\n\nTo be honest, there's really nothing special in this notebook. Rather than a contest entry, this notebook was a thinly veiled excuse to paraphrase the title of the classic piece of gonzo journalism by **Hunter S. Thompson** (for more, see __[Wikipedia article](https://en.wikipedia.org/wiki/The_Kentucky_Derby_Is_Decadent_and_Depraved)__).\n\nThen again, the ***Big Data Derby*** briefing says they want to prevent injuries in horse racing, but if I didn't miss something completely, there's no data whatsoever about injuries in the related dataset. That's basically like NFL trying to reduce the number of concussions by using data on hot dog prices at different venues. In Miami they probably do exactly that, but it is a whole another story altogether...\n\nIt is also notable that this notebook neither advocates nor advices anyone to get into serious gambling. Were it actually possible to predict winners, the world would be full of race track millionaires and the bookers were all bankrupt. Also, somewhere along the line the element of contingency in its entirety would have been suspended (for more, see __[Free Dictionary](https://www.thefreedictionary.com/contingency)__).\n\nAs this is not the case, ***this humble notebook concentrates on the odds given to those race participants who later became race winners***. In other words, this notebook concentrates on exploring ***how accurate the given odds are compared to race results when winners are concerned***. \n\n**October 17th, 2022<br>\nJari Peltola**","metadata":{}},{"cell_type":"markdown","source":"### 2. Data Preparation <a class=\"anchor\" id=\"chapter_2\"></a>","metadata":{}},{"cell_type":"markdown","source":"First we load the necessary modules along with the first dataset we will use.","metadata":{}},{"cell_type":"code","source":"# import modules\nimport pandas as pd\nimport numpy as np\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:28.451926Z","iopub.execute_input":"2022-10-17T07:01:28.452893Z","iopub.status.idle":"2022-10-17T07:01:29.703446Z","shell.execute_reply.started":"2022-10-17T07:01:28.452756Z","shell.execute_reply":"2022-10-17T07:01:29.702350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# dataset to dataframe\ndf = pd.read_csv('../input/big-data-derby-2022/nyra_start_table.csv', low_memory=False)","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:29.705365Z","iopub.execute_input":"2022-10-17T07:01:29.705764Z","iopub.status.idle":"2022-10-17T07:01:29.752262Z","shell.execute_reply.started":"2022-10-17T07:01:29.705730Z","shell.execute_reply":"2022-10-17T07:01:29.750974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# dataframe shape\ndf.shape","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:29.753972Z","iopub.execute_input":"2022-10-17T07:01:29.754996Z","iopub.status.idle":"2022-10-17T07:01:29.766768Z","shell.execute_reply.started":"2022-10-17T07:01:29.754956Z","shell.execute_reply":"2022-10-17T07:01:29.765333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There's some fifteen thousand datapoints altogether to bet on, but the *column names are notably absent*. Probably someone actually bet on them and lost or something. Hence inserting column names in accordance with the dataset description.","metadata":{}},{"cell_type":"code","source":"# insert column names\ndf.columns =['track_id', 'race_date', 'race_number', 'program_number', \n             'weight_carried', 'jockey', 'odds', 'position_at_finish']","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:29.771609Z","iopub.execute_input":"2022-10-17T07:01:29.772714Z","iopub.status.idle":"2022-10-17T07:01:29.777153Z","shell.execute_reply.started":"2022-10-17T07:01:29.772674Z","shell.execute_reply":"2022-10-17T07:01:29.776290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print dataframe head\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:29.778443Z","iopub.execute_input":"2022-10-17T07:01:29.779827Z","iopub.status.idle":"2022-10-17T07:01:29.807851Z","shell.execute_reply.started":"2022-10-17T07:01:29.779786Z","shell.execute_reply":"2022-10-17T07:01:29.806779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Between the two dataframes we need, *there is no common id column*. Thus we make one applying the method coined by **Nolan Conaway**.","metadata":{}},{"cell_type":"code","source":"# Thank you to Nolan Conaway for the following method\n# Stack Overflow thread link:\n# https://stackoverflow.com/questions/36646923/in-pandas-how-to-create-a-unique-id-based-on-the-combination-of-many-columns\n\n\n# function to make indentifier column based on other columns\ndef make_identifier(df):\n    str_id = df.apply(lambda x: '_'.join(map(str, x)), axis=1)\n    return pd.factorize(str_id)[0]\n\n# run function on preferred columns\ndf['combined_id'] = make_identifier(df[['track_id','race_date', 'race_number']])","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:29.809254Z","iopub.execute_input":"2022-10-17T07:01:29.809613Z","iopub.status.idle":"2022-10-17T07:01:29.978714Z","shell.execute_reply.started":"2022-10-17T07:01:29.809581Z","shell.execute_reply":"2022-10-17T07:01:29.977488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we can open the gates for the other dataset, consisting of more race data. Right at the start, a similar **combined_id** column like before is created.","metadata":{}},{"cell_type":"code","source":"# import dataset\ndf2 = pd.read_csv('../input/big-data-derby-2022/nyra_race_table.csv', low_memory=False)\n\n# create id column\ndf2['combined_id'] = make_identifier(df2[['track_id','race_date', 'race_number']])\n\ndf2.head()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:29.980193Z","iopub.execute_input":"2022-10-17T07:01:29.980533Z","iopub.status.idle":"2022-10-17T07:01:30.028083Z","shell.execute_reply.started":"2022-10-17T07:01:29.980502Z","shell.execute_reply":"2022-10-17T07:01:30.027055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As **race_date** and some other columns are not in our scope of interest, we'll leave them to stables from our column selection.","metadata":{}},{"cell_type":"code","source":"# define preferred columns\ncolumns =['distance_id', 'course_type', 'track_condition', 'run_up_distance', \n          'race_type', 'purse', 'post_time', 'combined_id']\n\n# select preferred columns\ndf2 = df2[columns]\n\ndf2.head()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.029501Z","iopub.execute_input":"2022-10-17T07:01:30.030119Z","iopub.status.idle":"2022-10-17T07:01:30.047051Z","shell.execute_reply.started":"2022-10-17T07:01:30.030087Z","shell.execute_reply":"2022-10-17T07:01:30.045846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we can merge the two dataframes based on the new id column. All this has already been done in the dataset consisting the actual tracking data, but as we're not into tracking, it was easier to use two smaller separate datasets.","metadata":{}},{"cell_type":"code","source":"# merge the datasets on common column\ndf_all = pd.merge(df, df2, on=['combined_id'])","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.048413Z","iopub.execute_input":"2022-10-17T07:01:30.048775Z","iopub.status.idle":"2022-10-17T07:01:30.075800Z","shell.execute_reply.started":"2022-10-17T07:01:30.048744Z","shell.execute_reply":"2022-10-17T07:01:30.074587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As for odds, in this dataset one must divide them by 100 to derive the \"odd-to-1\", as it says in the description. So, the value 1280 in the dataset would actually be 12.8-1 at the blackboard. However the same principle goes to both: *the smaller the figure, the lower the odds.*\n\nTaking a quick look at the data beforehand, some values were in my opinion *too* low, meaning they were either zero or below one. This is why next only values larger than one hundred are selected, meaning in odds they are at least 1.01-to-1. ","metadata":{}},{"cell_type":"code","source":"# select odds larger than 100\ndf_all = df_all[df_all['odds'] > 100]","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.079408Z","iopub.execute_input":"2022-10-17T07:01:30.079778Z","iopub.status.idle":"2022-10-17T07:01:30.093397Z","shell.execute_reply.started":"2022-10-17T07:01:30.079740Z","shell.execute_reply":"2022-10-17T07:01:30.092414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can also separate winnners from the riff raff now. The new column **is_winner** will tell us whether the datapoint represents race winner (column value is 1) or not (column value is 0). ","metadata":{}},{"cell_type":"code","source":"# separate race winners from other dataset rows\ndf_all['is_winner'] = df_all['position_at_finish'].apply(lambda x: 1 if x==1 else 0)","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.097345Z","iopub.execute_input":"2022-10-17T07:01:30.098350Z","iopub.status.idle":"2022-10-17T07:01:30.111999Z","shell.execute_reply.started":"2022-10-17T07:01:30.098310Z","shell.execute_reply":"2022-10-17T07:01:30.110691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3. Data Exploration <a class=\"anchor\" id=\"chapter_3\"></a>","metadata":{}},{"cell_type":"markdown","source":"Let's take a look at what kind of odds we actually have in the data. ","metadata":{}},{"cell_type":"code","source":"#plot odds column histogram\ndf_all.hist(column='odds')","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.113741Z","iopub.execute_input":"2022-10-17T07:01:30.114518Z","iopub.status.idle":"2022-10-17T07:01:30.360914Z","shell.execute_reply.started":"2022-10-17T07:01:30.114472Z","shell.execute_reply":"2022-10-17T07:01:30.359677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# see odd column description\ndf_all['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.362585Z","iopub.execute_input":"2022-10-17T07:01:30.363044Z","iopub.status.idle":"2022-10-17T07:01:30.377723Z","shell.execute_reply.started":"2022-10-17T07:01:30.363007Z","shell.execute_reply":"2022-10-17T07:01:30.376373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As we can see, our average odds for a horse/jockey is about 15.4-to-1. However, the 50% percentile is set only to about 7.7-to-1. This means the larger values in our data provide us with a skewed overall view. Next we take a look at some higher percentiles for better understanding.","metadata":{}},{"cell_type":"code","source":"# print percentiles\nprint(np.percentile(df_all['odds'], [80, 85, 90, 95]))","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.379880Z","iopub.execute_input":"2022-10-17T07:01:30.380390Z","iopub.status.idle":"2022-10-17T07:01:30.389939Z","shell.execute_reply.started":"2022-10-17T07:01:30.380343Z","shell.execute_reply":"2022-10-17T07:01:30.387458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The 95-percent percentile (i.e. it covers 95 percent of all datapoints) is set to 5775, which in odds is 57-to-1. Let's use that to limit our selection for now.","metadata":{}},{"cell_type":"code","source":"# select the 95-percent percentile\ndf_all = df_all[df_all['odds'] <= 5775]","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.391888Z","iopub.execute_input":"2022-10-17T07:01:30.392384Z","iopub.status.idle":"2022-10-17T07:01:30.405867Z","shell.execute_reply.started":"2022-10-17T07:01:30.392335Z","shell.execute_reply":"2022-10-17T07:01:30.404038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print histogram\ndf_all.hist(column='odds')","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.407784Z","iopub.execute_input":"2022-10-17T07:01:30.408460Z","iopub.status.idle":"2022-10-17T07:01:30.620619Z","shell.execute_reply.started":"2022-10-17T07:01:30.408328Z","shell.execute_reply":"2022-10-17T07:01:30.619799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can also take a peek at the winners' odds projected against the not-winning participants.","metadata":{}},{"cell_type":"code","source":"# print histogram on is_winner column values\nsns.histplot(data=df_all, x=\"odds\", hue=\"is_winner\", multiple=\"stack\")","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:30.622072Z","iopub.execute_input":"2022-10-17T07:01:30.623177Z","iopub.status.idle":"2022-10-17T07:01:31.188417Z","shell.execute_reply.started":"2022-10-17T07:01:30.623131Z","shell.execute_reply":"2022-10-17T07:01:31.187133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The ***is_winner*** column values seem pretty identical when it comes to distribution. Also - and not surprisingly - most winners were given relatively low odds. Let's take a quick look at how the odds correlate with winners.","metadata":{}},{"cell_type":"code","source":"columns =['odds', 'position_at_finish', 'is_winner']\n\ndf_correlate = df_all[columns]\n\ndf_correlate.corr()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.189766Z","iopub.execute_input":"2022-10-17T07:01:31.190372Z","iopub.status.idle":"2022-10-17T07:01:31.205289Z","shell.execute_reply.started":"2022-10-17T07:01:31.190336Z","shell.execute_reply":"2022-10-17T07:01:31.203878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"It looks like the odds are far better a prediction for overall finishing positions than winners. However this was an expected outcome, and our goal was not to predict winners either. Rather we want to see how accurate the given odds are compared to race results, as noted in the beginning.","metadata":{}},{"cell_type":"markdown","source":"### 4. Winning Odds <a class=\"anchor\" id=\"chapter_4\"></a>","metadata":{}},{"cell_type":"markdown","source":"We continue by separating all race winners to their respected dataframe **df_winners**.","metadata":{}},{"cell_type":"code","source":"# new dataframe\ndf_winners = df_all[df_all['is_winner'] == 1]\n\ndf_winners['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.211256Z","iopub.execute_input":"2022-10-17T07:01:31.211676Z","iopub.status.idle":"2022-10-17T07:01:31.224034Z","shell.execute_reply.started":"2022-10-17T07:01:31.211643Z","shell.execute_reply":"2022-10-17T07:01:31.222719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The average odds for winners are about 5.1-to-1. Also, the 75-percent percentile is set to 5.8-to-1. This means the winners dataset is more balanced than the overall data. Next we select columns to be applied in our further analysis.","metadata":{}},{"cell_type":"code","source":"new_columns =['odds', 'track_condition', 'course_type', 'race_type', 'track_id', 'jockey']\n\ndf_winners = df_winners[new_columns]\n\ndf_winners.head()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.225605Z","iopub.execute_input":"2022-10-17T07:01:31.226858Z","iopub.status.idle":"2022-10-17T07:01:31.242665Z","shell.execute_reply.started":"2022-10-17T07:01:31.226821Z","shell.execute_reply":"2022-10-17T07:01:31.241436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Our dataset includes data from three different racetracks **(AQU = Aqueduct, BEL = Belmont, SAR = Saratoga)**. Let's find out the data distribution between the three tracks.","metadata":{}},{"cell_type":"code","source":"# track id percentage\ndf_winners['track_id'].value_counts(normalize=True) * 100","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.244152Z","iopub.execute_input":"2022-10-17T07:01:31.244631Z","iopub.status.idle":"2022-10-17T07:01:31.257360Z","shell.execute_reply.started":"2022-10-17T07:01:31.244586Z","shell.execute_reply":"2022-10-17T07:01:31.256012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Aqueduct and Belmont together form some 80 percent of our data. Since the amount of data on both tracks is somewhat similar, we will next see if there is a difference between winning odds average at the two tracks. For comparison, we also take take same figure also from Saratoga.","metadata":{}},{"cell_type":"code","source":"# select Aqueduct data\ndf_aqu = df_winners[df_winners['track_id'] == \"AQU\"]\n\ndf_aqu['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.258921Z","iopub.execute_input":"2022-10-17T07:01:31.260402Z","iopub.status.idle":"2022-10-17T07:01:31.273637Z","shell.execute_reply.started":"2022-10-17T07:01:31.260352Z","shell.execute_reply":"2022-10-17T07:01:31.272665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# select Belmont data\ndf_bel = df_winners[df_winners['track_id'] == \"BEL\"]\n\ndf_bel['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.275566Z","iopub.execute_input":"2022-10-17T07:01:31.276089Z","iopub.status.idle":"2022-10-17T07:01:31.290602Z","shell.execute_reply.started":"2022-10-17T07:01:31.276042Z","shell.execute_reply":"2022-10-17T07:01:31.288567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# select Saratoga data\ndf_sar = df_winners[df_winners['track_id'] == \"SAR\"]\n\ndf_sar['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.292333Z","iopub.execute_input":"2022-10-17T07:01:31.292962Z","iopub.status.idle":"2022-10-17T07:01:31.305044Z","shell.execute_reply.started":"2022-10-17T07:01:31.292928Z","shell.execute_reply":"2022-10-17T07:01:31.303937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As we see,  in Aqueduct the average odds for winning horse/jockey are slightly higher than in Belmont or Saratoga. However the difference is well inside any margin of error and the dataset was collected in the pre-pandemic era, so one should not race right to Aqueduct because of this.","metadata":{}},{"cell_type":"markdown","source":"### 5. Track Conditions <a class=\"anchor\" id=\"chapter_5\"></a>","metadata":{}},{"cell_type":"markdown","source":"From now on we concentrate only on the Aqueduct track, as it offered the highest average odds for winners.\n\nLet's see if the track condition is any precursor for changes in odds. As the dataset description has it, the condition of the course the race was run on is divided as follows: **YL = Yielding, FM = Firm, SY = Sloppy, GD = Good, FT = Fast, MY = Muddy, SF = Soft**.","metadata":{}},{"cell_type":"code","source":"# track condition percentage\ndf_aqu['track_condition'].value_counts(normalize=True) * 100","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.306168Z","iopub.execute_input":"2022-10-17T07:01:31.306970Z","iopub.status.idle":"2022-10-17T07:01:31.324105Z","shell.execute_reply.started":"2022-10-17T07:01:31.306932Z","shell.execute_reply":"2022-10-17T07:01:31.322716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In most cases the track condition was labeled FT, which is fast. Next we check the odds average on fast tracks as well as non-fast conditions (selected as !=FT).\n\nHowever, we can see from the unique values that there is whitespace at the end of condition label's strings. One might of course just remove it, but here we settle for including it in the name i.e. hitting space when typing the label names. ","metadata":{}},{"cell_type":"code","source":"# unique column values\ndf_aqu['track_condition'].unique()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.326231Z","iopub.execute_input":"2022-10-17T07:01:31.326746Z","iopub.status.idle":"2022-10-17T07:01:31.334658Z","shell.execute_reply.started":"2022-10-17T07:01:31.326697Z","shell.execute_reply":"2022-10-17T07:01:31.333558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# select label with one space in the end\ndf_aqu_ft = df_aqu[df_aqu['track_condition'] == \"FT \"]\n\ndf_aqu_ft['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.336068Z","iopub.execute_input":"2022-10-17T07:01:31.336395Z","iopub.status.idle":"2022-10-17T07:01:31.350969Z","shell.execute_reply.started":"2022-10-17T07:01:31.336367Z","shell.execute_reply":"2022-10-17T07:01:31.349705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_aqu_ft = df_aqu[df_aqu['track_condition'] != \"FT \"]\n\ndf_aqu_ft['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.352649Z","iopub.execute_input":"2022-10-17T07:01:31.353083Z","iopub.status.idle":"2022-10-17T07:01:31.369446Z","shell.execute_reply.started":"2022-10-17T07:01:31.353050Z","shell.execute_reply":"2022-10-17T07:01:31.368152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In Aqueduct the non-fast conditions offer slightly higher odds to winners, but this is no news for anyone with betting history. Lousy conditions usually act as the great equalizer in all sports, leaving a fighting chance for apparent underdogs. For example, no NFL elite quarterback has a four-touchdown game with 570 passing yards in a mid-November hailstorm at Lambeau Field, whether naturally immunized or not...\n\nA quick peek shows that the Aqueduct course type is almost always dirt (D), so there's not point analyzing it.","metadata":{}},{"cell_type":"code","source":"df_aqu['course_type'].value_counts(normalize=True) * 100","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.370811Z","iopub.execute_input":"2022-10-17T07:01:31.372093Z","iopub.status.idle":"2022-10-17T07:01:31.381837Z","shell.execute_reply.started":"2022-10-17T07:01:31.372056Z","shell.execute_reply":"2022-10-17T07:01:31.380701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Rather we hop on to the actual race types.\n\n\nIn our data, the race types are divided as following:\n\n**STK = Stakes, WCL = Waiver Claiming, WMC = Waiver Maiden Claiming, SST = Starter Stakes, SHP = Starter Handicap, CLM = Claiming, STR = Starter Allowance, AOC = Allowance Optional Claimer, SOC = Starter Optional Claimer, MCL = Maiden Claiming, ALW = Allowance, MSW = Maiden Special Weight.**\n\n\nWhat they actually are, I will leave to racing experts.","metadata":{}},{"cell_type":"code","source":"# show unique values\ndf_aqu['race_type'].unique()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.383722Z","iopub.execute_input":"2022-10-17T07:01:31.384215Z","iopub.status.idle":"2022-10-17T07:01:31.394502Z","shell.execute_reply.started":"2022-10-17T07:01:31.384170Z","shell.execute_reply":"2022-10-17T07:01:31.393214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#show percentages\ndf_aqu['race_type'].value_counts(normalize=True) * 100","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.395809Z","iopub.execute_input":"2022-10-17T07:01:31.396825Z","iopub.status.idle":"2022-10-17T07:01:31.407894Z","shell.execute_reply.started":"2022-10-17T07:01:31.396787Z","shell.execute_reply":"2022-10-17T07:01:31.406783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The three most popular categories form about 60 percent of all data, so let's take a closer look at them.","metadata":{}},{"cell_type":"code","source":"df_aqu_clm = df_aqu[df_aqu['race_type'] == \"CLM\"]\n\ndf_aqu_clm['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.412235Z","iopub.execute_input":"2022-10-17T07:01:31.412860Z","iopub.status.idle":"2022-10-17T07:01:31.425556Z","shell.execute_reply.started":"2022-10-17T07:01:31.412817Z","shell.execute_reply":"2022-10-17T07:01:31.424379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_aqu_mcl = df_aqu[df_aqu['race_type'] == \"MCL\"]\n\ndf_aqu_mcl['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.427101Z","iopub.execute_input":"2022-10-17T07:01:31.427572Z","iopub.status.idle":"2022-10-17T07:01:31.444984Z","shell.execute_reply.started":"2022-10-17T07:01:31.427528Z","shell.execute_reply":"2022-10-17T07:01:31.443642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_aqu_msw = df_aqu[df_aqu['race_type'] == \"MSW\"]\n\ndf_aqu_msw['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.446492Z","iopub.execute_input":"2022-10-17T07:01:31.447692Z","iopub.status.idle":"2022-10-17T07:01:31.460667Z","shell.execute_reply.started":"2022-10-17T07:01:31.447645Z","shell.execute_reply":"2022-10-17T07:01:31.459457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The ***Maiden Claiming*** and ***Maiden Special Weight*** races at Aqueduct seem to offer slightly worse odds for people willing to lose their money, or better odds for trying to win some. Again, there is only a handful of relatively old data available on the subject matter, so this is definitely not a recommendation or betting tip of any sort.","metadata":{}},{"cell_type":"markdown","source":"### 5. The King of Aqueduct <a class=\"anchor\" id=\"chapter_6\"></a>","metadata":{}},{"cell_type":"markdown","source":"For a worthy final straight, let's find out who's the most victorious jockey at Aqueduct, or at least the one with the best horses under him.","metadata":{}},{"cell_type":"code","source":"#show percentages\ndf_aqu['jockey'].value_counts(normalize=True) * 100","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.462600Z","iopub.execute_input":"2022-10-17T07:01:31.463488Z","iopub.status.idle":"2022-10-17T07:01:31.476541Z","shell.execute_reply.started":"2022-10-17T07:01:31.463453Z","shell.execute_reply":"2022-10-17T07:01:31.475285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_aqu_franco = df_aqu[df_aqu['jockey'] == \"Manuel Franco\"]\n\ndf_aqu_franco['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.498410Z","iopub.execute_input":"2022-10-17T07:01:31.498853Z","iopub.status.idle":"2022-10-17T07:01:31.513137Z","shell.execute_reply.started":"2022-10-17T07:01:31.498817Z","shell.execute_reply":"2022-10-17T07:01:31.511868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_aqu_lezcano = df_aqu[df_aqu['jockey'] == \"Jose Lezcano\"]\n\ndf_aqu_lezcano['odds'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-17T07:01:31.558756Z","iopub.execute_input":"2022-10-17T07:01:31.559400Z","iopub.status.idle":"2022-10-17T07:01:31.571647Z","shell.execute_reply.started":"2022-10-17T07:01:31.559355Z","shell.execute_reply":"2022-10-17T07:01:31.570376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We finally have a winner. **Manuel Franco** is the uncrowned king of Aqueduct, however only with a slight margin to **Jose Lezcano**, whose average winning odds are a titch higher. When the two race together, put your money on them and you'll have a combined 25-percent statistical chance to win cash at Aqueduct.\n\n***But of course, there's always bitcoin or old baseball cards***.","metadata":{}}]}