{"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":"code","source":"from IPython.core.display import display, HTML, Javascript\nfrom string import Template\nimport IPython.display","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:21.493339Z","iopub.execute_input":"2022-10-12T15:55:21.493740Z","iopub.status.idle":"2022-10-12T15:55:21.498500Z","shell.execute_reply.started":"2022-10-12T15:55:21.493708Z","shell.execute_reply":"2022-10-12T15:55:21.497756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"html_contents =\"\"\"\n<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n    <style>\n    .title{\n        background-color: white;\n        color: black;\n        font-family: Helvetica;\n        font-size: 30px;\n        padding: 6px 12px;\n        margin-bottom: 5px;\n    }\n    \n    .toc div{\n        color: white;\n        background: gray;\n        font-weight: 600;\n        font-family: Helvetica;\n        font-size: 23px;\n        padding: 6px 12px;\n        margin-bottom: 2px;\n    }\n    \n    .toc ol li{\n        list-style:none;\n        line-height:normal;\n        }\n     \n    .toc li{\n        background: teal;\n        color: white;\n        font-weight: 600;\n        font-family: Helvetica;\n        font-size: 18px;\n        margin-bottom: 2px;\n        padding: 6px 12px;\n    }\n\n    .toc ol ol li{\n        background: #fff;\n        color: #4d4d4d;\n        font-weight: 400;\n        font-size: 15px;\n        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n        margin-top: 0px;\n        margin-bottom: 0px;\n        padding: 3px 12px;\n    } \n    \n    .section_title{\n        background-color: teal;\n        color: white;\n        font-family: Helvetica;\n        font-size: 25px;\n        padding: 6px 12px;\n        margin-bottom: 5px;\n    }\n    .subsection_title{\n        background: #235f83;\n        color: white;\n        font-family: Helvetica;\n        font-size: 21px;\n        padding: 6px 12px;\n        margin-bottom: 0px;\n    }\n    .sidenote{\n        font-size: 13px;\n        border: 1px solid #d7d7d7;\n        padding: 1px 10px 2px;\n        box-shadow: 1px 1px 2px 1px rgba(0,0,0,0.3);\n        margin-bottom: 3px;\n    }\n    </style>\n    </head>\n    <body>\n        <div class=\"title\">Big Data Derby 2022 - EDA - Jockeys' Journeys in a year </div>\n        <br>\n        <div class=\"sidenote\">\n        \n        This notebook is rewrapping the content in the notebook\n        <a href=https://www.kaggle.com/code/xxxxyyyy80008/derby-2022-eda-jockeys-journeys>Derby 2022 - EDA - Jockeys Journeys</a>. \n        I am experimenting different ways of presenting information. Kindly let me know if any suggestions or feedback! Thanks a lot!!!\n\n        \n        </div>\n        <br>\n        <div class=\"toc\"; id=\"toc\">\n        \n        <ol> \n        <div> Table of Contents </div>\n        <li>1. Who were the top jockeys?</li>\n        <ol>  \n            <li>1.1 Who won most races in 2019? Who finish in top 3 position in most races? </li>\n            <li>1.2 Who has the highest win rate? Who has the place rate (finished in 1st, 2nd, and 3rd palces)? </li> \n        </ol>\n        <li>2. How did jockeys' performance progress over time? </li>\n        <ol> \n            <li>2.1 The journey of Manuel Franco, Jose Lezcano, Javier Castellano, Irad Ortiz Jr. </li> \n        </ol>\n        <li>3. Zero-sum game </li>\n        <ol> \n            <li>3.1 Who frequently competed in the same races? </li> \n            <li>3.2 Can one jockey maintain his advantage over another jockey throughout all races? </li> \n        </ol>\n        <li>4. Take aways </li>\n        </ol>\n        </div>\n    </body>\n</html>\n\"\"\"\n\nHTML(html_contents)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T16:09:48.988478Z","iopub.execute_input":"2022-10-12T16:09:48.988911Z","iopub.status.idle":"2022-10-12T16:09:49.003902Z","shell.execute_reply.started":"2022-10-12T16:09:48.988873Z","shell.execute_reply":"2022-10-12T16:09:49.001621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport matplotlib.pyplot as plt\nimport matplotlib.lines as mlines\nimport pandas as pd\nimport statsmodels.api as sm\nimport seaborn as sns\n\nimport pyarrow.parquet as pq\nimport pyarrow as pa","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:21.520231Z","iopub.execute_input":"2022-10-12T15:55:21.520580Z","iopub.status.idle":"2022-10-12T15:55:22.794234Z","shell.execute_reply.started":"2022-10-12T15:55:21.520550Z","shell.execute_reply":"2022-10-12T15:55:22.793383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#/kaggle/input/derby-2022-merge-and-convert-data-to-parquet-file/nyra_2019_complete.parquet\n\nrace_table = pd.read_csv('/kaggle/input/big-data-derby-2022/nyra_race_table.csv')\nstart_table = pd.read_csv('/kaggle/input/big-data-derby-2022/nyra_start_table.csv', header=None)\n# tracking_table = pd.read_csv('/kaggle/input/big-data-derby-2022/nyra_tracking_table.csv')\nstart_table.columns=['track_id', 'race_date', 'race_number', 'program_number', 'weight_carried', 'jockey', 'odds', 'position_at_finish']","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:22.795650Z","iopub.execute_input":"2022-10-12T15:55:22.795933Z","iopub.status.idle":"2022-10-12T15:55:22.854102Z","shell.execute_reply.started":"2022-10-12T15:55:22.795899Z","shell.execute_reply":"2022-10-12T15:55:22.853289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"race_type_dict =   {  'STK': 'Stakes', \n                      'WCL': 'Waiver Claiming', \n                      'WMC': 'Waiver Maiden Claiming', \n                      'SST': 'Starter Stakes', \n                      'SHP': 'Starter Handicap',\n                      'CLM': 'Claiming', \n                      'STR': 'Starter Allowance', \n                      'AOC': 'Allowance Optionl Claimer', \n                      'SOC': 'Starter Optional Claimer', \n                      'MCL': 'Maiden Claiming', \n                      'ALW': 'Allowance', \n                      'MSW': 'Maiden Special Weight'\n                      }\n\ntrack_id_dict = dict(AQU = 'Aqueduct', BEL = 'Belmont', SAR = 'Saratoga')\ncourse_type_dict = dict(M = 'Hurdle', D = 'Dirt', O = 'Outer turf', I = 'Inner turf', T = 'turf')\ntrack_condition_dict =  dict(YL = 'Yielding', FM ='Firm', SY = 'Sloppy', GD = 'Good', FT = 'Fast', MY = 'Muddy', SF = 'Soft')\n\nrace_table['race_type'] = race_table['race_type'].map(race_type_dict)\nrace_table['track_id'] = race_table['track_id'].map(track_id_dict)\nrace_table['course_type'] = race_table['course_type'].map(course_type_dict)\n\nrace_table['track_condition']=race_table['track_condition'].apply(lambda x:x.replace(\" \", ''))\nrace_table['track_condition'] = race_table['track_condition'].map(track_condition_dict)\n\n\nstart_table['track_id'] = start_table['track_id'].map(track_id_dict)\n\nprint(start_table.shape, race_table.shape)\nstart_table = start_table.merge(race_table, on=['track_id','race_date', 'race_number'], how='inner')\nprint(start_table.shape, race_table.shape)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:22.855415Z","iopub.execute_input":"2022-10-12T15:55:22.856152Z","iopub.status.idle":"2022-10-12T15:55:22.903494Z","shell.execute_reply.started":"2022-10-12T15:55:22.856117Z","shell.execute_reply":"2022-10-12T15:55:22.902441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"html_contents =\"\"\"\n<div class=\"section_title\"; id=\"1\">1. Who were the top jockeys?</div>\n\n\"\"\"\nHTML(html_contents)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T16:03:41.128329Z","iopub.execute_input":"2022-10-12T16:03:41.128739Z","iopub.status.idle":"2022-10-12T16:03:41.136421Z","shell.execute_reply.started":"2022-10-12T16:03:41.128703Z","shell.execute_reply":"2022-10-12T16:03:41.135087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"[back to top](#toc)\n","metadata":{}},{"cell_type":"code","source":"#https://blog.hubspot.com/website/how-to-bold-in-html#:~:text=How%20to%20Italicize%20Text%20in,property%20set%20to%20%E2%80%9Citalic.%E2%80%9D\ncs=pd.pivot_table(start_table[start_table['position_at_finish']<=3], values='race_date', \n               index=['jockey'], columns=['position_at_finish'], aggfunc=np.size)\ncs['Total'] = cs.sum(axis=1)\ncs.sort_values(by='Total', ascending=False, inplace=True)\ncs = cs.head(30)\ntop30jockeys = cs.index.values.tolist()\ncs.columns.name=''\n#cs.sort_values(by='sum', ascending=True, inplace=True)\ncs.columns=['1st Place', '2nd Place', '3rd Place', 'Total']\ncs.index = [f'{i+1}: {val}' for i, val in enumerate(cs.index.values)]\n\n#https://stackoverflow.com/questions/53142921/table-with-and-link-format-for-pandas-style-formatting\ncs.iloc[:30].style.set_table_attributes('style=\"width: 100%;\"')\\\n.set_table_styles(\n    [\n      {\"selector\": \"td, th\", \"props\": [(\"border\", \"2px solid white !important\")]},\n      {'selector': 'tr:hover','props': 'background-color: wheat; font-size: 1em;'},\n      {'selector': 'caption','props': [('text-align', 'left'),  ('color', 'black')]},#('font-size', '18px'),\n    ]\n).set_caption('''\n<h3>Who won most races in 2019? Who finish in top 3 position  in most races? [Top 30]</h3> \n\n<i>Note: Top 30 jockeys are jockeys who ranked in top 30 by number of races finished in 1st, 2nd, or 3rd position.</i>\n\n\n<br><br>While there were 178 jockeys participated in the 2000 races in 2019, only 43 of them raced in 30 or more races. And the number goes down to 21 (the number of jockeys) who raced in 200 or more races.\n\n<br><br>Among the 2000 races in 2019, Manuel Franco participated in 1274 (63.7%) races, and won 214 of them. This means among all the races took place in 2019, more than one in ten races had the 1st place taken by him! He had a win rate of 17% and place rate around 49%.\n\n<br><br>But was he the one who finished in 1st, 2nd, or 3rd position in most races? The answer is YES!\n\nManuel Franco finished in 2nd position in 214 races and in 3rd position in 192 races. In total, he finished in top 3 positions in 620 races, which is 31% of all races!\n<br><br>The stunning numbers undoubtly proves Manuel Franco was the best jockey in 2019. Who is the 2nd best? \n\n<br><br>The answer is Jose Lezcano. he raced in 990 races, won 206 races and had win rate of 20.8%. He finished in top 3 positions in 491 races, which is 49.6% out of all races he participated.               \n              ''')\\\n.format(precision=0, na_rep='', thousands=\", \",)\\\n.bar(subset=['1st Place'], color='teal')\\\n.bar(subset=['2nd Place'], color='lightseagreen')\\\n.bar(subset=['3rd Place'], color='powderblue')\\\n.bar(subset=['Total'], color='salmon')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:22.905649Z","iopub.execute_input":"2022-10-12T15:55:22.905957Z","iopub.status.idle":"2022-10-12T15:55:23.017955Z","shell.execute_reply.started":"2022-10-12T15:55:22.905929Z","shell.execute_reply":"2022-10-12T15:55:23.016867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cs=pd.pivot_table(start_table[start_table['position_at_finish']<=3], values='race_date', \n               index=['jockey'], columns=['position_at_finish'], aggfunc=np.size)\ncs['sum'] = cs.sum(axis=1)\ncs.sort_values(by='sum', ascending=False, inplace=True)\ncs = cs.head(30)\n#cs.sort_values(by='sum', ascending=True, inplace=True)\ncs0=pd.pivot_table(start_table, values='race_date', \n               index=['jockey'],aggfunc=np.size)\ncs0.columns=['total']\ncs0 = cs.merge(cs0, left_index=True, right_index=True, how='inner')\nfor i in [1, 2, 3, 'sum']:\n    cs0[i] = (100*cs0[i]/cs0['total'])\n    \ncs0 = cs0[[1, 2, 3, 'sum']]\ncs0.columns=['1st Place', '2nd Place', '3rd Place', 'Total']\ncs0.index = [f'{i+1}: {val}' for i, val in enumerate(cs0.index.values)]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.019237Z","iopub.execute_input":"2022-10-12T15:55:23.019581Z","iopub.status.idle":"2022-10-12T15:55:23.057315Z","shell.execute_reply.started":"2022-10-12T15:55:23.019550Z","shell.execute_reply":"2022-10-12T15:55:23.056462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cs0.iloc[:30].style.set_table_attributes('style=\"width: 100%;\"')\\\n.set_table_styles(\n    [\n      {\"selector\": \"td, th\", \"props\": [(\"border\", \"2px solid white !important\"), (\"height\", \"2px\")]},\n      {'selector': 'tr:hover','props': 'background-color: wheat; font-size: 1em;'},\n      {'selector': 'caption','props': [('text-align', 'left'),  ('color', 'black')]},#('font-size', '18px'),\n    ]\n).set_caption('''\n<h3>Win rates of top 30 jockeys</h3> \n\n<i>Note: In the following analysis, we define `win rate` as percentage of races a jockey finished in 1st position out of all the races he participated in. <br>And we define `place rate` as percentage of races a jockey finished in 1st, 2nd, or 3rd position out of all the races he perticipated in.</i>\n\n\n<br><br>\n\nManuel Franco won 17% of races he ran and had 49% place rate; There were 5 jockeys who had higher place rate than Franco.\n\n<br><br>Javier Castellano had the highest place rate and win rate. Both Javier Castellano and Jose Lezcano had win rate over 21%.\n\n\n''')\\\n.format(precision=1, na_rep='', thousands=\", \",)\\\n.bar(subset=['1st Place'], color='teal')\\\n.bar(subset=['2nd Place'], color='lightseagreen')\\\n.bar(subset=['3rd Place'], color='powderblue')\\\n.bar(subset=['Total'], color='salmon')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.058391Z","iopub.execute_input":"2022-10-12T15:55:23.059344Z","iopub.status.idle":"2022-10-12T15:55:23.087280Z","shell.execute_reply.started":"2022-10-12T15:55:23.059311Z","shell.execute_reply":"2022-10-12T15:55:23.086325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cs=pd.pivot_table(start_table[start_table['position_at_finish']<=1], values='race_date', \n               index=['jockey'], columns=['track_id'], aggfunc=np.size)\ncs['sum'] = cs.sum(axis=1)\ncs.sort_values(by='sum', ascending=False, inplace=True)\ncs = cs.head(30)\n#cs.sort_values(by='sum', ascending=True, inplace=True)\ncs0=pd.pivot_table(start_table, values='race_date', \n               index=['jockey'],columns=['track_id'], aggfunc=np.size)\ncs0['sum'] = cs0.sum(axis=1)\ncols = cs.columns.tolist()\n\ncs0 = cs.merge(cs0, left_index=True, right_index=True, how='inner')\nfor c in cols:\n    cs0[f'{c}_x'] = (100*cs0[f'{c}_x']/cs0[f'{c}_y'])\n    cs0.loc[cs0[f'{c}_y']<30, f'{c}_x']=np.nan\n\n    \ncs0 = cs0.iloc[:, :4]\ncols = cols[:-1] + ['Total']\ncs0.columns=cols\n\ncs0.index = [f'{i+1}: {val}' for i, val in enumerate(cs0.index.values)]\ncs0.iloc[:30].style.set_table_attributes('style=\"width: 1250px;\"')\\\n.set_table_styles(\n    [\n      {\"selector\": \"td, th\", \"props\": [(\"border\", \"2px solid white !important\"), (\"height\", \"2px\")]},\n      {'selector': 'tr:hover','props': 'background-color: wheat; font-size: 1em;'},\n      {'selector': 'caption','props': [('text-align', 'left'),  ('color', 'black')]},#('font-size', '18px'),\n    ]\n).set_caption('''\n<h3>Did jockeys have better luck on certain tracks? Win rates by track of top 30 jockeys</h3> \n<i>the win rate is set as 0 if a jockey's total number of races on the corresponding track is less than 30 </i>\n\n<br><br>For Manuel Franco had a overall win rate around 17%, but his win rate at Aqueduct was more than 22%. The overall rate was dragged down the his performance on Saratoga. \n\n<br><br>Javier Castellano had the highest win rate. But his performances on 3 tracks were almost the same.\n\n<br><br>So it seems, some jockeys did have their lucks on on track but not another.\n\n\n''')\\\n.format(precision=1, na_rep='', thousands=\", \",)\\\n.bar(subset=cols[0], color='teal')\\\n.bar(subset=cols[1], color='lightseagreen')\\\n.bar(subset=cols[2], color='powderblue')\\\n.bar(subset=cols[3], color='salmon')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.088807Z","iopub.execute_input":"2022-10-12T15:55:23.089266Z","iopub.status.idle":"2022-10-12T15:55:23.160024Z","shell.execute_reply.started":"2022-10-12T15:55:23.089205Z","shell.execute_reply":"2022-10-12T15:55:23.159190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cs=pd.pivot_table(start_table[start_table['position_at_finish']<=3], values='race_date', \n               index=['jockey'], columns=['track_id'], aggfunc=np.size)\ncs['sum'] = cs.sum(axis=1)\ncs.sort_values(by='sum', ascending=False, inplace=True)\ncs = cs.head(30)\n#cs.sort_values(by='sum', ascending=True, inplace=True)\ncs0=pd.pivot_table(start_table, values='race_date', \n               index=['jockey'],columns=['track_id'], aggfunc=np.size)\ncs0['sum'] = cs0.sum(axis=1)\ncols = cs.columns.tolist()\n\ncs0 = cs.merge(cs0, left_index=True, right_index=True, how='inner')\nfor c in cols:\n    cs0[f'{c}_x'] = (100*cs0[f'{c}_x']/cs0[f'{c}_y'])\n    cs0.loc[cs0[f'{c}_y']<30, f'{c}_x']=np.nan\n\n    \ncs0 = cs0.iloc[:, :4]\ncols = cols[:-1] + ['Total']\ncs0.columns=cols\n\ncs0.index = [f'{i+1}: {val}' for i, val in enumerate(cs0.index.values)]\n\ncs0.iloc[:30].style.set_table_attributes('style=\"width: 1250px;\"')\\\n.set_table_styles(\n    [\n      {\"selector\": \"td, th\", \"props\": [(\"border\", \"2px solid white !important\"), (\"height\", \"2px\")]},\n      {'selector': 'tr:hover','props': 'background-color: wheat; font-size: 1em;'},\n      {'selector': 'caption','props': [('text-align', 'left'),  ('color', 'black')]},#('font-size', '18px'),\n    ]\n).set_caption('''\n<h3>Did jockeys have better luck on certain tracks? Place rates by track of top 30 jockeys</h3> \n\n<i>the place rate is set as 0 if a jockey's total number of races on the corresponding track is less than 30 </i>\n\n''')\\\n.format(precision=1, na_rep='', thousands=\", \",)\\\n.bar(subset=cols[0], color='teal')\\\n.bar(subset=cols[1], color='lightseagreen')\\\n.bar(subset=cols[2], color='powderblue')\\\n.bar(subset=cols[3], color='salmon')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.161113Z","iopub.execute_input":"2022-10-12T15:55:23.161371Z","iopub.status.idle":"2022-10-12T15:55:23.226541Z","shell.execute_reply.started":"2022-10-12T15:55:23.161347Z","shell.execute_reply":"2022-10-12T15:55:23.225650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cs=pd.pivot_table(start_table[start_table['position_at_finish']<=3], values='race_date', \n               index=['jockey'], columns=['position_at_finish'], aggfunc=np.size, fill_value=0)\ncs['sum'] = cs.sum(axis=1)\n\ncs0=pd.pivot_table(start_table, values='race_number', \n               index=['jockey'],aggfunc=np.size)\ncs0.columns=['total']\ncs0 = cs.merge(cs0, left_index=True, right_index=True, how='inner')\nfor i in [1, 2, 3, 'sum']:\n    cs0[i] = (100*cs0[i]/cs0['total']).round(0)\n    \ncs0 = cs0[cs0['total']>=30].sort_values(by='sum', ascending=False)[[1, 2, 3, 'sum']]\ncs0.columns=['1st Place', '2nd Place', '3rd Place', 'Total']   \ncs0.index = [f'{i+1}: {val}' for i, val in enumerate(cs0.index.values)]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.228235Z","iopub.execute_input":"2022-10-12T15:55:23.228670Z","iopub.status.idle":"2022-10-12T15:55:23.272312Z","shell.execute_reply.started":"2022-10-12T15:55:23.228630Z","shell.execute_reply":"2022-10-12T15:55:23.271220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cs0.iloc[:30].style.set_table_attributes('style=\"width: 1250px;\"')\\\n.set_table_styles(\n    [\n      {\"selector\": \"td, th\", \"props\": [(\"border\", \"2px solid white !important\"), (\"height\", \"2px\")]},\n      {'selector': 'tr:hover','props': 'background-color: wheat; font-size: 1em;'},\n      {'selector': 'caption','props': [('text-align', 'left'),  ('color', 'black')]},#('font-size', '18px'),\n    ]\n).set_caption('''\n<h3>Who has the highest win rate? Who has the place rate (finished in 1st, 2nd, and 3rd palces)[Top 30 by place rate]?</h3> \n\n<i>Note: this part of analysis excludes jockeys who ran less than 30 races to make the results statistical meaningful.</i>\n\n\n<br><br>Javier Castellano and Jose Lezcano had win rate around 21%. Jose Lezcano raced in 990 races which is nearly half of the 2000 races in 2019. He was also in 2nd place in terms of number of races won by jockeys and number of races finished in 1st, 2nd, and 3rd places.\n\n<br><br>Four jockeys had place rate more than 50%, and they were Javier Castellano, Irad Ortiz Jr. Joel Rosario, and Jose L. Ortiz. Despite the fact that Manuel Franco won most number of races and had most number races in top 3 positions, his place rate was slightly below 50%.\n\n<br><br>Javier Castellano raced in 541 races (i.e. 27% out of 2000 races) and had 55% place rate. Irad Ortiz Jr. raced in over 800 races (i.e. over 40% races) and had a place rate of 54%. \n\n\n\n''')\\\n.format(precision=0, na_rep='', thousands=\", \",)\\\n.bar(subset=['1st Place'], color='teal')\\\n.bar(subset=['2nd Place'], color='lightseagreen')\\\n.bar(subset=['3rd Place'], color='powderblue')\\\n.bar(subset=['Total'], color='salmon')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.276822Z","iopub.execute_input":"2022-10-12T15:55:23.277167Z","iopub.status.idle":"2022-10-12T15:55:23.307539Z","shell.execute_reply.started":"2022-10-12T15:55:23.277135Z","shell.execute_reply":"2022-10-12T15:55:23.306418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"html_contents =\"\"\"\n\n<div class=\"section_title\"; id=\"2\">2. How did jockeys' performance progress over time?</div>\n\n\"\"\"\nHTML(html_contents)","metadata":{"execution":{"iopub.status.busy":"2022-10-12T16:05:41.360341Z","iopub.execute_input":"2022-10-12T16:05:41.360735Z","iopub.status.idle":"2022-10-12T16:05:41.368366Z","shell.execute_reply.started":"2022-10-12T16:05:41.360704Z","shell.execute_reply":"2022-10-12T16:05:41.367185Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\n[back to top](#toc)\n","metadata":{}},{"cell_type":"code","source":"top10winrates = {}\n\nfor jk in top30jockeys[:10]:\n    cs = start_table[start_table['jockey']==jk].sort_values(by=['race_date', 'race_number'])\n    cs.reset_index(drop=True, inplace=True)\n    cs['win'] = (cs['position_at_finish']<2).astype(int)\n    cs['place'] = (cs['position_at_finish']<4).astype(int)\n    cs['win_cumsum'] = cs['win'].cumsum()\n    cs['place_cumsum'] = cs['place'].cumsum()\n    top10winrates[jk]=cs","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.308886Z","iopub.execute_input":"2022-10-12T15:55:23.309208Z","iopub.status.idle":"2022-10-12T15:55:23.374154Z","shell.execute_reply.started":"2022-10-12T15:55:23.309178Z","shell.execute_reply":"2022-10-12T15:55:23.373066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(5, 2, figsize=(18, 4*5))\nlabels = ['cumulative wins', 'cumulative places']\ni=0\nfor jk, data in top10winrates.items():\n    data = data[['win_cumsum', 'place_cumsum']]\n    #caption=f\"{jk}'s journey: Num of wins and places over time\" \n    caption=f\"{jk}\"\n    ax = axs[i//2, i%2]\n    \n    ax2 = ax.twinx()\n    ax.set_title(caption, fontsize=13, loc='left')\n    #ax.set_xlabel('time')\n\n    ax.plot(data.index, data.iloc[:, 0], marker='', markerfacecolor='teal', markersize=2, color='lightseagreen', linewidth=2)\n    ax2.plot(data.index, data.iloc[:, 1], marker='', markerfacecolor='tomato', color='salmon', linewidth=2, linestyle='--')\n\n    ax.set_ylabel(labels[0])\n    ax2.set_ylabel(labels[1])\n    ax.legend([labels[0]], loc='upper left')\n    ax2.legend([labels[1]], loc='upper center')\n    ax.yaxis.grid(color='lightgray', linestyle='dashed')\n    \n    i = i + 1\n    \n\n\nfig.text(.012, 1.035, '''\nHow did a jockey's performance progress over time? The journeys of top 10 jockeys.\n''', fontweight='bold', fontfamily='monospace', fontsize=15,ha='left')  \n\nfig.text(0.012, 1., '''\n\nwin: means finish in the 1st position. place: means finish in 1st, 2nd, or 3rd position.\n\n''',ha='left', fontsize=13,) \n\n    \nplt.tight_layout()\nplt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.3, hspace=None) # useful for adjusting space between subplots\nplt.show()  ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:23.375663Z","iopub.execute_input":"2022-10-12T15:55:23.375972Z","iopub.status.idle":"2022-10-12T15:55:25.886299Z","shell.execute_reply.started":"2022-10-12T15:55:23.375943Z","shell.execute_reply":"2022-10-12T15:55:25.885543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"jockeys = ['Manuel Franco', 'Jose Lezcano', 'Javier Castellano', 'Irad Ortiz Jr.']\n\ncs_ = start_table[['race_date', 'race_number']].drop_duplicates()\n\n\nfor jk in jockeys:\n    cs = start_table[start_table['jockey']==jk].sort_values(by=['race_date', 'race_number'])\n    cs.reset_index(drop=True, inplace=True)\n    cs['win'] = (cs['position_at_finish']<2).astype(int)\n    #cs['place'] = (cs['position_at_finish']<4).astype(int)\n    cs_ = cs_.merge(cs[['race_date', 'race_number', 'win']], on=['race_date', 'race_number'], how='left')\n    cs_.sort_values(by=['race_date', 'race_number'], inplace=True)\n    cs_.rename(columns={'win':jk}, inplace=True)\n    cs_[jk].fillna(0, inplace=True)\n    cs_[jk] = cs_[jk].cumsum()\n    \n    \ncs_.sort_values(by=['race_date', 'race_number'], inplace=True)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:25.887330Z","iopub.execute_input":"2022-10-12T15:55:25.887664Z","iopub.status.idle":"2022-10-12T15:55:25.950257Z","shell.execute_reply.started":"2022-10-12T15:55:25.887633Z","shell.execute_reply":"2022-10-12T15:55:25.948944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cs2=race_table.sort_values(by=['race_date', 'race_number'])[['track_id']]\ncs2.reset_index(drop=True, inplace=True)\ncs2['seq']=cs2.index.values\ncs2['val']=1\ncs2.loc[cs2['track_id']=='Aqueduct', 'val']=1\ncs2.loc[cs2['track_id']=='Belmont', 'val']=2\ncs2.loc[cs2['track_id']=='Saratoga', 'val']=3\n\ncs2 = cs2.pivot(columns='track_id', index='seq', values='val')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:25.951851Z","iopub.execute_input":"2022-10-12T15:55:25.952323Z","iopub.status.idle":"2022-10-12T15:55:25.968773Z","shell.execute_reply.started":"2022-10-12T15:55:25.952280Z","shell.execute_reply":"2022-10-12T15:55:25.968003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = cs_.iloc[:, 2:]\nlabels = cs_.columns[2:]\n\ncolors = ['lightseagreen', 'salmon', 'lightskyblue', 'mediumseagreen', 'sandybrown', 'lightslategray', 'wheat', 'crimson']\nmcolors = ['teal', 'tomato', 'skyblue', 'mediumseagreen', 'peru', 'slategray', 'tan',  'firebrick']\n\n\nfig, axs = plt.subplots(2, 1, figsize=(15, 9), sharex=True, gridspec_kw={'height_ratios': [8, 1]})\n\nax = axs[0]\nfor i in range(data.shape[1]):\n    ax.plot(data.index, data.iloc[:, i], marker='', markerfacecolor=mcolors[i], markersize=2, color=colors[i], linewidth=2, label=labels[i])\n    ax.text(data.iloc[:, i].dropna().size + 1, data.iloc[:, i].dropna().values[-1], labels[i], fontsize=11, color=mcolors[i])\n    ax.yaxis.grid(color='lightgray', linestyle='dashed')\n    #ax.grid(visible=True, which='major', axis='both', color='lightgray', linestyle='-', linewidth=0.2)\n    ax.spines[['top', 'right']].set_visible(False)\n    ax.spines[['bottom', 'left']].set_edgecolor('whitesmoke')\n    ax.set_ylabel('')\n    #ax.set_xticks([])\n    \ndata = cs2\nax = axs[1]\nlabels = data.columns.tolist()\nfor i in range(data.shape[1]):\n    ax.plot(data.index, data.iloc[:, i], marker='', markerfacecolor=mcolors[i], markersize=2, color=colors[i], linewidth=2, label=labels[i])\n    #ax.text(data.iloc[:, i].dropna().size + 1, data.iloc[:, i].dropna().values[-1], labels[i], fontsize=11, color=mcolors[i])\n    ax.yaxis.grid(color='lightgray', linestyle='dashed')\n    ax.grid(visible=True, which='major', axis='both', color='lightgray', linestyle='-', linewidth=0.2)\n    ax.spines[['top', 'right']].set_visible(False)\n    ax.spines[['bottom', 'left']].set_edgecolor('whitesmoke')\n    \n    ax.set_ylabel('')\n    ax.set_xlabel('race number', fontsize=13,)\n    ax.set_yticks([])\n    ax.set_title('track', fontsize=10, loc='left')\n    ax.legend(loc='upper right')\n\n\nfig.text(.012, 1.28, '''\nThe win rate of Manuel Franco, Jose Lezcano, Javier Castellano, Irad Ortiz Jr.\n''', fontweight='bold', fontfamily='monospace', fontsize=15,ha='left')  \n\nfig.text(0.012, 1.0, '''\n Manuel Franco, Jose Lezcano were the top 2 by total number of races finished in top 3 positions.\n Javier Castellano, Irad Ortiz Jr. were the top 2 by place race. \n\n Manuel was unstoppable in the first 500 races. But once Javier and Irad joined the game, Manuel's performance hit a plateau. \n \n Irad and Javier joined the game around the 500th races in the year, and their winnings kept climbing linearly until around the 1500th race.\n \n It seemed that before the 500th and after the 1500th races when races were mostly on track Aqueduct, Manuel and Jose had their advantages,\n and between the 500th and 1250th race when races were on Belmont track, Irad and Javier had their adavantages. \n\n''',ha='left', fontsize=13,) \n\n    \nplt.tight_layout()\nplt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.3, hspace=None) # useful for adjusting space between subplots\nplt.show()  ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:25.970145Z","iopub.execute_input":"2022-10-12T15:55:25.970462Z","iopub.status.idle":"2022-10-12T15:55:26.415717Z","shell.execute_reply.started":"2022-10-12T15:55:25.970434Z","shell.execute_reply":"2022-10-12T15:55:26.414944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"html_contents =\"\"\"\n\n\n<div class=\"section_title\"; id=\"3\">3. Zero-sum game</div>\n\n\"\"\"\nHTML(html_contents)","metadata":{"execution":{"iopub.status.busy":"2022-10-12T16:06:02.297855Z","iopub.execute_input":"2022-10-12T16:06:02.298290Z","iopub.status.idle":"2022-10-12T16:06:02.306599Z","shell.execute_reply.started":"2022-10-12T16:06:02.298240Z","shell.execute_reply":"2022-10-12T16:06:02.305229Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\n\n[back to top](#toc)\n","metadata":{}},{"cell_type":"code","source":"cs = start_table[['track_id', 'race_date', 'race_number', 'jockey', 'program_number']]\n#cs.set_index(keys=['track_id', 'race_date', 'jockey'], inplace=True)\npcs = cs.pivot(index=['track_id', 'race_date',  'race_number',], columns='jockey', values='program_number')\n\npcs[pcs>'0']=1\npcs.fillna(0, inplace=True)\ncoocc = pcs.T.dot(pcs)\nnp.fill_diagonal(coocc.values, 0)\n\ncoocc_s = coocc.unstack().sort_values()\ncoocc_s.index.names = ['jockey1', 'jockey2']\ncoocc_s = coocc_s.reset_index()\ncoocc_s.columns = ['jockey1', 'jockey2', 'race_cnt']","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:26.416697Z","iopub.execute_input":"2022-10-12T15:55:26.417705Z","iopub.status.idle":"2022-10-12T15:55:26.649099Z","shell.execute_reply.started":"2022-10-12T15:55:26.417654Z","shell.execute_reply":"2022-10-12T15:55:26.648263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#-----data-------------------------------------\ncs = coocc.loc[top30jockeys[:20], top30jockeys[:20]]\n\n#------plot-----------------------------------------------------\nfig, ax = plt.subplots(1, 1, figsize=(15, 12))\n\nmask = np.zeros_like(cs, dtype=bool)\nmask = np.triu(np.ones_like(cs, dtype=bool)) #uncomment if only show under the diagnoal line\n\nvmax = np.round(np.nanmax(cs.where(~mask)) - 0.05, 2)\nvmin = np.round(np.nanmin(cs.where(~mask)) + 0.05, 2)\n\n\n# Specify kwargs for the heatmap\nkwargs = {\n    \"mask\": mask,\n    \"cmap\": \"BrBG\",\n    \"annot\": True,\n    \"vmax\": vmax,\n    \"vmin\": vmin,\n    \"square\": False,\n    \"linewidths\": 2.5,\n    \"annot_kws\": {\"fontsize\": 12},\n    \"cbar\":False, \n    #\"cbar_kws\": {\"shrink\": 0.95, \"aspect\": 30},\n}\n\n# Draw heatmap with mask and default settings\nsns.heatmap(cs, center=0, fmt=\".0f\",ax=ax, **kwargs)\n# sns.heatmap(cs, xticklabels=cs.columns, yticklabels=cs.index, cmap='RdYlGn', square=True, linewidth=2.5,cbar=False,\n#             center=0, annot=True,  fmt='.0f', \n#             ax=ax,annot_kws={\"fontsize\":12})#YlGnBu#RdYlGn\n\n\nax.spines['top'].set_visible(True)\n\nfig.text(.99, 1.005, 'Who frequently raced in the same races?', fontweight='bold', fontfamily='monospace', fontsize=15,ha='right')   \nfig.text(0.99, 0.75, '''\n\nThis part focuses on the top 20 jockeys by total number of races finished in top 3 positions.\n\nManuel Franco and Dylan Davis competed against each in most number of races. \nThey ran together in 726 races which accounted for more than 36% of all races in 2019.\n\nJose Lezcano and Manuel Franco competed in 659 (33% out of 2000) races. \nJose Lezcano and Dylan Davis competed in 575 (28.8%) races.\n\n\n\n''',ha='right', fontsize=14, ) \n\n\n\nax.set_yticklabels(ax.get_yticklabels(), rotation = 0, fontsize=12)\nax.set_xticklabels(ax.get_xticklabels(), rotation = 80, fontsize=12)#fontfamily='serif', \n\nax.set_ylabel('')    \nax.set_xlabel('')\nax.tick_params(axis=u'both', which=u'both',length=0)\n\n# plt.xticks(fontsize=10)\n# plt.yticks(fontsize=10)\n\nplt.tight_layout()\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:26.650469Z","iopub.execute_input":"2022-10-12T15:55:26.651138Z","iopub.status.idle":"2022-10-12T15:55:27.907525Z","shell.execute_reply.started":"2022-10-12T15:55:26.651105Z","shell.execute_reply":"2022-10-12T15:55:27.906408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pair_perfs = {'win_rate': [], 'score': []}\npairs = [['Manuel Franco', 'Dylan Davis'], ['Jose Lezcano', 'Manuel Franco'], ['Jose Lezcano', 'Dylan Davis']]\nfor pair in pairs:\n    cs = pcs[pcs[pair].sum(axis=1)==2][pair].reset_index()[['track_id', 'race_date', 'race_number']]\n    cs.columns.name=''\n    # print(cs.shape)\n    cs = cs.merge(start_table, on = ['track_id', 'race_date', 'race_number'], how='inner')\n    cs = cs[cs['jockey'].isin(pair)]\n    # print(cs.shape)\n    cs.sort_values(by=['race_date', 'race_number'], ascending=[True, True], inplace=True)\n    cs_ = pd.pivot_table(cs[cs['position_at_finish']<=1], values='position_at_finish', \n                   index=['race_date', 'race_number'], columns=['jockey'], aggfunc=np.size, fill_value=0)\n    cs_.reset_index(drop=True, inplace=True)\n    for jk in pair:\n        cs_[jk] = (cs_[jk].cumsum())/(cs_.index+1)\n        \n    pair_perfs['win_rate'].append(cs_)\n    \n\n\n    cs0 = cs.pivot(index=['race_date', 'race_number'], columns=['jockey'], values=['position_at_finish'])\n    cs0.columns = [b for _, b in cs0.columns]\n    cs_ = cs0.copy()\n    cs_[pair[0]]=(cs0[pair[0]]>cs0[pair[1]]).astype(int)\n    cs_[pair[1]]=(cs0[pair[0]]<cs0[pair[1]]).astype(int)\n    cs_.reset_index(drop=True, inplace=True)\n    \n    for jk in pair:\n        cs_[jk] = (cs_[jk].cumsum())/(cs_.index+1)  \n        \n    pair_perfs['score'].append(cs_)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:27.909200Z","iopub.execute_input":"2022-10-12T15:55:27.909848Z","iopub.status.idle":"2022-10-12T15:55:28.053379Z","shell.execute_reply.started":"2022-10-12T15:55:27.909807Z","shell.execute_reply":"2022-10-12T15:55:28.052098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(3, 2, figsize=(18, 16))\n\nfor j in range(3):\n    \n    for n, k in enumerate(list(pair_perfs.keys())):\n    \n        data = pair_perfs[k][j]\n        ax = axs[j, n]\n        labels = data.columns.tolist()\n        if n<1:\n            caption=f'Races {labels[0]} and {labels[1]} ran together: win rate over time for each jockey'\n        else:\n            caption=f'Races {labels[0]} and {labels[1]} ran together: scores over time time for each jockey'\n\n        for i in range(data.shape[1]):\n            ax.plot(data.index, data.iloc[:, i], marker='', markerfacecolor=mcolors[i], markersize=2, color=colors[i], linewidth=2, label=labels[i])\n            ax.text(data.iloc[:, i].dropna().size + 1, data.iloc[:, i].dropna().values[-1], labels[i], fontsize=11, color=mcolors[i])\n            ax.yaxis.grid(color='lightgray', linestyle='dashed')\n            #ax.grid(visible=True, which='major', axis='both', color='lightgray', linestyle='-', linewidth=0.2)\n            ax.spines[['top', 'right']].set_visible(False)\n            ax.spines[['bottom', 'left']].set_edgecolor('whitesmoke')\n            ax.set_ylabel('')\n            ax.set_title(caption)\n            #ax.set_xticks([])\n\n\n\nfig.text(.012, 1.2, '''\nCan one jockey maintain his advantage over another jockey throughout all races?\n''', fontweight='bold', fontfamily='monospace', fontsize=15,ha='left')  \n\n\nfig.text(.012, 1.18, '''\nWe look at 3 pairs of jockeys (Manuel Franco and Dylan Davis, Jose Lezcano and Manuel Franco, Jose Lezcano and Dylan Davis) and see how they outperformed each other over time. \n''', fontweight='bold', fontfamily='monospace', fontsize=14,ha='left')  \n\nfig.text(0.012, 1.05, '''\n\nFirst, we only look at the races either one in a pair won, and examine how the the win rates change over time.\nThen, we look at all the races each pair ran together and see how each one outperformed each other over time. For example, in a race, if one finished in 3rd position and the other finished in 5th position, then the one at 3rd position gets a point. \n\nManuel Franco and Dylan Davis: after the initial fluctuations in the first 100ish races, these two gained certain equilibrium.\n\nJose Lezcano and Manuel Franco: Jose gradually lost more and more to Manuel even though Manuel did not cath up with Jose - in terms of points got - in the end.\n\nJose Lezcano and Dylan Davis: Dylan quickly outperformed Jose in the first 50 races they two ran together. The pace slowed down after 250 races together, but Dylan maintained outperforming Jose to the end.\n\n''',ha='left', fontsize=13,) \n\n    \nplt.tight_layout()\nplt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.3, hspace=None) # useful for adjusting space between subplots\nplt.show()  ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-12T15:55:28.055012Z","iopub.execute_input":"2022-10-12T15:55:28.055454Z","iopub.status.idle":"2022-10-12T15:55:29.260267Z","shell.execute_reply.started":"2022-10-12T15:55:28.055412Z","shell.execute_reply":"2022-10-12T15:55:29.259197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"html_contents =\"\"\"\n\n<div class=\"section_title\"; id=\"4\">4. Take aways</div>\n\n\"\"\"\nHTML(html_contents)","metadata":{"execution":{"iopub.status.busy":"2022-10-12T16:06:34.948170Z","iopub.execute_input":"2022-10-12T16:06:34.948641Z","iopub.status.idle":"2022-10-12T16:06:34.957012Z","shell.execute_reply.started":"2022-10-12T16:06:34.948602Z","shell.execute_reply":"2022-10-12T16:06:34.955888Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\n\n[back to top](#toc)\n\n\n\n**The competitions were among a small group of jockeys**\n\n- 178 jockeys participated in the 2000 races in 2019 \n- 43 of them raced in 30+ races \n- 21 jockeys raced in 200+ races\n\n**anuel Franco was the KING on tracks**\n\n*Of all 2000 races in 2019:*\n\n- he raced in ~ 64% races\n- he won 10%+ races\n- he had a win rate of 17%  \n- he place rate around 49%\n\n**A sure thing for Javier Castellano?**\n\nJavier Castellano had a win rate over 20% and 55% place rate, both numbers were the highest among all jockeys.\n\n\n**Some wins, some losses**\n\n - Manuel was unstoppable in the first 500 races. But once Javier and Irad joined the game, Manuel's performance hit a plateau. \n - Irad and Javier joined the game around the 500th races in the year, and their winnings kept climbing linearly until around the 1500th race.\n - It seemed that before the 500th and after the 1500th races, Manuel and Jose had their advantages, and between the 500th and 1250th race, Irad and Javier had their adavantages. ","metadata":{}}]}