{"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":"\n\nThis analysis uses data provided by [Mark Green](https://www.kaggle.com/themarkgreen): [Big Data Derby 2022: Global Horse IDs and places](https://www.kaggle.com/datasets/themarkgreen/big-data-derby-2022-global-horse-ids-and-places)","metadata":{}},{"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-03T14:45:23.271748Z","iopub.execute_input":"2022-10-03T14:45:23.272158Z","iopub.status.idle":"2022-10-03T14:45:25.326941Z","shell.execute_reply.started":"2022-10-03T14:45:23.272056Z","shell.execute_reply":"2022-10-03T14:45:25.325713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"start_table = pd.read_csv('/kaggle/input/big-data-derby-2022/nyra_start_table.csv', header=None)\nstart_table.columns=['track_id', 'race_date', 'race_number', 'program_number', 'weight_carried', 'jockey', 'odds', 'position_at_finish']\n\nhorse_names = pd.read_csv(r\"/kaggle/input/big-data-derby-2022-global-horse-ids-and-places/horse_names.csv\", index_col=0)\nhorse_ids = pd.read_csv(r\"/kaggle/input/big-data-derby-2022-global-horse-ids-and-places/horse_ids.csv\", index_col=0)\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:25.328601Z","iopub.execute_input":"2022-10-03T14:45:25.328935Z","iopub.status.idle":"2022-10-03T14:45:25.449049Z","shell.execute_reply.started":"2022-10-03T14:45:25.328904Z","shell.execute_reply":"2022-10-03T14:45:25.447869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(horse_ids.shape, horse_names.shape)\nhorse_ids = horse_ids.merge(horse_names, on='horse_id', how='inner')\nprint(horse_ids.shape, horse_names.shape)\nhorse_ids['program_number'] = horse_ids['program_number'].apply(lambda x: x.ljust(3, ' '))","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:40.873549Z","iopub.execute_input":"2022-10-03T14:45:40.873933Z","iopub.status.idle":"2022-10-03T14:45:40.908483Z","shell.execute_reply.started":"2022-10-03T14:45:40.873900Z","shell.execute_reply":"2022-10-03T14:45:40.906838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(start_table.shape, horse_ids.shape)\nstart_table = start_table.merge(horse_ids, \n                                left_on=['track_id', 'race_date', 'race_number', 'program_number'],\n                                right_on=['track_id', 'race_date', 'race', 'program_number'],\n                                how='inner'\n                               )\nprint(start_table.shape, horse_ids.shape)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:41.940512Z","iopub.execute_input":"2022-10-03T14:45:41.940923Z","iopub.status.idle":"2022-10-03T14:45:41.971371Z","shell.execute_reply.started":"2022-10-03T14:45:41.940890Z","shell.execute_reply":"2022-10-03T14:45:41.969585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"race_table = pd.read_csv('/kaggle/input/big-data-derby-2022/nyra_race_table.csv')\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)\n\n","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:43.255483Z","iopub.execute_input":"2022-10-03T14:45:43.255901Z","iopub.status.idle":"2022-10-03T14:45:43.284376Z","shell.execute_reply.started":"2022-10-03T14:45:43.255868Z","shell.execute_reply":"2022-10-03T14:45:43.283413Z"},"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\nstart_table['race_type'] = start_table['race_type'].map(race_type_dict)\nstart_table['track_id'] = start_table['track_id'].map(track_id_dict)\nstart_table['course_type'] = start_table['course_type'].map(course_type_dict)\n\nstart_table['track_condition']=start_table['track_condition'].apply(lambda x:x.replace(\" \", ''))\nstart_table['track_condition'] = start_table['track_condition'].map(track_condition_dict)\n\n\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:44.210097Z","iopub.execute_input":"2022-10-03T14:45:44.210674Z","iopub.status.idle":"2022-10-03T14:45:44.238434Z","shell.execute_reply.started":"2022-10-03T14:45:44.210629Z","shell.execute_reply":"2022-10-03T14:45:44.237274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://www.kaggle.com/code/gaetanlopez/how-to-make-clean-visualizations\nfig=plt.figure(figsize=(8,2),facecolor= \"#fbfbfb\")\n\nax0=fig.add_subplot(1,1,1)\nax0.text(1.1,1,\"NYRA/NYTHA Horse Racing 2019 - Racehorse Key Numbers\",color='black',fontsize=22, fontweight='bold', fontfamily='monospace',ha='center')\n\nax0.text(0,0.4,start_table['horse_id'].nunique(),color='teal',fontsize=25, fontweight='bold', fontfamily='monospace',ha='center')\nax0.text(0,0.001,\"Racehorses\",color='dimgrey',fontsize=17, fontweight='light', fontfamily='monospace',ha='center')\n\nax0.text(0.45,0.4,start_table.shape[0],color='teal',fontsize=25, fontweight='bold', fontfamily='monospace',ha='center')\nax0.text(0.45,0.001,\"Starts\",color='dimgrey',fontsize=17, fontweight='light', fontfamily='monospace',ha='center')\n\nax0.text(1.1,0.4,(start_table['horse_id'].value_counts()>10).sum(),color='tomato',fontsize=25, fontweight='bold', fontfamily='monospace',ha='center')\nax0.text(1.1,0.001,\"Racehorse ran more than 10 races\",color='dimgrey',fontsize=17, fontweight='light', fontfamily='monospace',ha='center')\n\nax0.text(2.,0.4,(start_table['horse_id'].value_counts()<5).sum(),color='tomato',fontsize=25, fontweight='bold', fontfamily='monospace',ha='center')\nax0.text(2.,0.001,\"Racehorse ran less than 10 races\",color='dimgrey',fontsize=17, fontweight='light', fontfamily='monospace',ha='center')\n\nax0.set_yticklabels('')\nax0.tick_params(axis='y',length=0)\nax0.tick_params(axis='x',length=0)\nax0.set_xticklabels('')\n\nfor direction in ['top','right','left','bottom']:\n    ax0.spines[direction].set_visible(False)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:45.305450Z","iopub.execute_input":"2022-10-03T14:45:45.306202Z","iopub.status.idle":"2022-10-03T14:45:45.504893Z","shell.execute_reply.started":"2022-10-03T14:45:45.306161Z","shell.execute_reply":"2022-10-03T14:45:45.503572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://www.kaggle.com/code/joshuaswords/netflix-data-visualization\ndata = start_table['horse_id'].value_counts().to_frame()['horse_id'].value_counts()\ndata.index = data.index.astype(str)\ndata = data[data>0.1]\n# Plot\n\ncolor_map = ['lightseagreen' ]*5 + ['wheat']*(data.size - 5)\n\n\nfig, ax = plt.subplots(1,1, figsize=(18, 7),facecolor= \"#fbfbfb\")\nax.set_facecolor(\"#fbfbfb\")\nax.bar(data.index, data, width=0.5, \n       #edgecolor='darkgray',\n       linewidth=0.6,color=color_map)\n\n#annotations\nfor i in data.index:\n    ax.annotate(f\"{data[i]}\", \n                   xy=(i, data[i] + 25), \n                   va = 'center', ha='center',fontweight='light', )\n\n\n\n# Remove border from plot\n\nfor s in ['top', 'left', 'right']:\n    ax.spines[s].set_visible(False)\n    \n\nfig.text(0.09, 1.05, 'Num. of racehorses by Num. of races',  \n         fontfamily='monospace',fontweight='bold',fontsize=15,color='#323232', ha='left')\n\nfig.text(0.09, 0.9, f'''\nAmong the {start_table[\"horse_id\"].nunique()} racehorses raced in 2019, {data[0]} ran only 1 races, accounted for {data[0]/(start_table[\"horse_id\"].nunique()):.2%} of racehorses.\n\nOnly a few racehorses ran more than 15 races. \n'''\n         , fontfamily='monospace',fontweight='light',fontsize=14,color='#323232', ha='left')\n\nax.grid(axis='y', linestyle='-', alpha=0.4)   \n\n# grid_y_ticks = np.arange(0, 1650, 200) # y ticks, min, max, then step\n# ax.set_yticks(grid_y_ticks)\nax.set_yticks([])\nax.set_axisbelow(True)\nax.set_xlabel('Num of races')\nplt.axhline(y = 0, color = 'black', linewidth = 1.3, alpha = .7)\n\nax.tick_params(axis='both', which='major', labelsize=12)\nax.grid(visible=True, which='major', axis='both', color='lightgray', linestyle='-', linewidth=0.2)\nax.spines[['top', 'right']].set_visible(False)\nax.spines[['bottom', 'left']].set_edgecolor('whitesmoke')\n\n\nax.tick_params(axis=u'both', which=u'both',length=0)\n\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:46.769165Z","iopub.execute_input":"2022-10-03T14:45:46.769808Z","iopub.status.idle":"2022-10-03T14:45:47.332609Z","shell.execute_reply.started":"2022-10-03T14:45:46.769768Z","shell.execute_reply":"2022-10-03T14:45:47.331439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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, values='race_date', \n               index=['horse_name'], columns=['position_at_finish'], aggfunc=np.size)\ncs['Total'] = cs.sum(axis=1)\ncs.sort_values(by='Total', ascending=False, inplace=True)\ncs['>4'] = cs[list(range(5,15))].sum(axis=1)\ncs = cs[[1, 2, 3, 4, '>4', 'Total']]\ntop30horses = cs.index.values.tolist()\ncs = cs.head(30)\ncs.columns.name=''\n#cs.sort_values(by='sum', ascending=True, inplace=True)\ncs.columns=['1st Place', '2nd Place', '3rd Place', '4th Place', '>4' ,'Total']\n\n\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: 90%;\"')\\\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(f'''\n<h3>Top 30 racehorses by Num of races</h3> \n\nRacehorse Wisecrack ran 21 races but did not won any, and only 1 race in 2nd place.\n\n<br><br>Bon Raison ran 17 races but won 6 of them, making the win rate {6/17:.2%}.\n\n<br><br>Orpheus (ARG) ran 16 races, won only 1 races but finished in top 3 in 12 races, \nmaking the place rate (finish in top 3 positions) {12/16:.2%}.\n \n<br><br>H Man and T Loves a Fight both raced in 16 races and each made 5 wins, making the win rate {5/16:.2%}\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=['4th Place'], color='aliceblue')\\\n.bar(subset=['>4'], color='lightgray')\\\n.bar(subset=['Total'], color='salmon')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:48.690887Z","iopub.execute_input":"2022-10-03T14:45:48.691682Z","iopub.status.idle":"2022-10-03T14:45:48.900970Z","shell.execute_reply.started":"2022-10-03T14:45:48.691637Z","shell.execute_reply":"2022-10-03T14:45:48.899853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://stackoverflow.com/questions/19412462/getting-distance-between-two-points-based-on-latitude-longitude\nfrom math import sin, cos, sqrt, atan2\n#returns the distance in meters\ndef cal_distance(data):\n    \"\"\"\n    data is a pd.Series, must have 'latitude', 'longitude', 'latitude2', 'longitude2'\n    \"\"\"\n    if (data is None)|(data is np.nan):\n        return 0\n\n    R = 6373.0 ## approximate radius of earth in km\n\n    lat1, lon1, lat2, lon2 = data[['latitude', 'longitude', 'latitude2', 'longitude2']].values\n  \n\n    dlon = lon2 - lon1\n    dlat = lat2 - lat1\n    a = (sin(dlat/2))**2 + cos(lat1) * cos(lat2) * (sin(dlon/2))**2\n    c = 2 * atan2(sqrt(a), sqrt(1-a))\n    distance = R * c*1000\n    return distance","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:45:59.981242Z","iopub.execute_input":"2022-10-03T14:45:59.981666Z","iopub.status.idle":"2022-10-03T14:45:59.993026Z","shell.execute_reply.started":"2022-10-03T14:45:59.981631Z","shell.execute_reply":"2022-10-03T14:45:59.991501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://geopy.readthedocs.io/en/stable/#module-geopy.distance\nfrom geopy.distance import distance as GO_DIS","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:46:00.409308Z","iopub.execute_input":"2022-10-03T14:46:00.410350Z","iopub.status.idle":"2022-10-03T14:46:00.548095Z","shell.execute_reply.started":"2022-10-03T14:46:00.410294Z","shell.execute_reply":"2022-10-03T14:46:00.546883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracking_table = pd.read_parquet('/kaggle/input/derby-2022-merge-and-convert-data-to-parquet-file/nyra_2019_complete.parquet')\ntracking_table['course_type'] = tracking_table['course_type'].map(course_type_dict)\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:46:05.032553Z","iopub.execute_input":"2022-10-03T14:46:05.033199Z","iopub.status.idle":"2022-10-03T14:46:08.797721Z","shell.execute_reply.started":"2022-10-03T14:46:05.033159Z","shell.execute_reply":"2022-10-03T14:46:08.795879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trakus_index_max = pd.pivot_table(tracking_table, index = ['race_id','track_id', 'race_date', 'race_number'], \n                                  values=['trakus_index'], aggfunc=np.max)\ntrakus_index_max.reset_index(drop=False, inplace=True)\ntrakus_index_max.rename(columns={'trakus_index':'race_trakus_index'}, inplace=True)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:46:08.799355Z","iopub.execute_input":"2022-10-03T14:46:08.800173Z","iopub.status.idle":"2022-10-03T14:46:10.399013Z","shell.execute_reply.started":"2022-10-03T14:46:08.800132Z","shell.execute_reply":"2022-10-03T14:46:10.397765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"horse_trakus_index_max = pd.pivot_table(tracking_table, index = ['race_id', 'race_horse_id', 'program_number'], \n                                  values=['trakus_index'], aggfunc=np.max)\nhorse_trakus_index_max.reset_index(drop=False, inplace=True)\nhorse_trakus_index_max.rename(columns={'trakus_index':'horse_trakus_index'}, inplace=True)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:46:10.401685Z","iopub.execute_input":"2022-10-03T14:46:10.402378Z","iopub.status.idle":"2022-10-03T14:46:11.380111Z","shell.execute_reply.started":"2022-10-03T14:46:10.402324Z","shell.execute_reply":"2022-10-03T14:46:11.378891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(horse_trakus_index_max.shape, trakus_index_max.shape)\nhorse_trakus_index_max = horse_trakus_index_max.merge(trakus_index_max, \n                                                      on=['race_id', ],\n                                                      how='inner'\n                                                     )\nprint(horse_trakus_index_max.shape, trakus_index_max.shape)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:46:11.383339Z","iopub.execute_input":"2022-10-03T14:46:11.384568Z","iopub.status.idle":"2022-10-03T14:46:11.398177Z","shell.execute_reply.started":"2022-10-03T14:46:11.384513Z","shell.execute_reply":"2022-10-03T14:46:11.397192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"horse_trakus_index_max['unfinished']=(horse_trakus_index_max['horse_trakus_index']<horse_trakus_index_max['race_trakus_index']).astype(int)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:46:11.399567Z","iopub.execute_input":"2022-10-03T14:46:11.400147Z","iopub.status.idle":"2022-10-03T14:46:11.416230Z","shell.execute_reply.started":"2022-10-03T14:46:11.400111Z","shell.execute_reply":"2022-10-03T14:46:11.415000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nspeed_data = []\nfor _, row in horse_trakus_index_max.iterrows():\n    \n    data = tracking_table[(tracking_table['race_horse_id']==row['race_horse_id'])][['race_horse_id','trakus_index','latitude','longitude']].copy(deep=True)\n    data.sort_values(by=['race_horse_id', 'trakus_index'], ascending=[True]*2, inplace=True)\n    data_next = data[['race_horse_id','trakus_index','latitude','longitude']].shift(-1)\n    data_next.columns = [f'{c}2' for c in data_next.columns]\n    data = pd.concat([data, data_next], axis=1)\n#     data['distance'] = data.apply(lambda x: cal_distance(x), axis=1)\n#     data['speed'] = data['distance']/0.25\n    \n    data.dropna(how='any', inplace=True)\n    data['distance'] = data.apply(lambda x: GO_DIS(x[['latitude', 'longitude']].values,x[['latitude2', 'longitude2']].values).meters, axis=1)\n    data['speed'] = data['distance']/0.25\n    \n    \n    speed_data.append([row['race_horse_id'], data['distance'].sum(), data['speed'].mean(), data['speed'].median(), \\\n                       data['speed'].min(), data['speed'].max(), \\\n                       data['speed'].quantile(q=0.25), data['speed'].quantile(q=0.75)\n                      ]\n                     )\n    ","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-10-03T14:46:51.652085Z","iopub.execute_input":"2022-10-03T14:46:51.652648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_speed = pd.DataFrame(data=speed_data, columns=['race_horse_id', 'total_distance', 'mean_speed', 'median_speed', \n                                               'min_speed', 'max_speed', 'q25_speed', 'q75_speed'\n                                              ])","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(horse_trakus_index_max.shape, df_speed.shape)\nhorse_trakus_index_max = horse_trakus_index_max.merge(df_speed, on=['race_horse_id'], how='inner')\nprint(horse_trakus_index_max.shape, df_speed.shape)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(horse_trakus_index_max.shape, start_table.shape)\nhorse_trakus_index_max = horse_trakus_index_max.merge(start_table, \n                             on=['race_date', 'race_number', 'program_number'],\n                             how='inner'\n                            )\nprint(horse_trakus_index_max.shape, start_table.shape)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"horse_trakus_index_max.drop(columns=['track_id_x'], inplace=True)\nhorse_trakus_index_max.rename(columns={'track_id_y':'track_id'}, inplace=True)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"background = \"#fbfbfb\"\n\nfig, ax = plt.subplots(1,1, figsize=(15, 14),dpi=100)\nfig.patch.set_facecolor(background) # figure background color\n\nax.set_facecolor(background)\n\n\ndata = horse_trakus_index_max[horse_trakus_index_max['horse_name'].isin(top30horses[:15])][['horse_name', 'mean_speed']]\n\nax = sns.violinplot(y='horse_name', x='mean_speed', data=data)\n\n# Add jitter with the swarmplot function\nax = sns.swarmplot(y='horse_name', x='mean_speed', data=data, ec='black',linewidth=1.5,)\n\n\nfig.text(0,0.96,'Racehorse speed variance - the mean speed (meters/seconds) in each race',\n         fontfamily='monospace',fontweight='bold',fontsize=15,color='#323232', ha='left')\n\nfig.text(0,.935,'top 15 racehorse by num. of races',\n         fontfamily='monospace',fontweight='light',fontsize=14,color='#323232', ha='left')\n\n\nax.spines[['top','left','bottom','right']].set_visible(False)\n    \nax.set_xlabel(\"\")\nax.set_ylabel(\"\")\nax.tick_params(axis=u'both', which=u'both',length=0)\n\nplt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]}]}