{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Statistiques descriptives \n# 2020 March Madness\nIn this notebook I explore the 2020 Men's and Women's NCAA basketball data. Hopefully you find the analysis and code helpful. Feel free to use any of the helper functions in your code but please reference this as the original source.\n\n![](https://upload.wikimedia.org/wikipedia/en/thumb/2/28/March_Madness_logo.svg/440px-March_Madness_logo.svg.png)"},{"metadata":{},"cell_type":"markdown","source":"# Import Libraries\n"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pylab as plt\nimport matplotlib as mpl\nfrom matplotlib.patches import Circle, Rectangle, Arc\nimport seaborn as sns\nplt.style.use('seaborn-dark-palette')\nmypal = plt.rcParams['axes.prop_cycle'].by_key()['color'] # Grab the color pal\nimport os\nimport gc\n\nMENS_DIR = '../input/google-cloud-ncaa-march-madness-2020-division-1-mens-tournament'\nWOMENS_DIR = '../input/google-cloud-ncaa-march-madness-2020-division-1-womens-tournament'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Loss Metric & Sample Submission\nLog Loss is the metric we will be evaluated on for the tournament prediction challenge. This metric provides a stronger punishment that are overly confident and wrong."},{"metadata":{"trusted":true},"cell_type":"code","source":"def logloss(true_label, predicted, eps=1e-15):\n    p = np.clip(predicted, eps, 1 - eps)\n    if true_label == 1:\n        return -np.log(p)\n    return -np.log(1 - p)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f'Confident Wrong Prediction: \\t\\t {logloss(1, 0.01):0.4f}')\nprint(f'Confident Correct Prediction: \\t\\t {logloss(0, 0.01):0.4f}')\nprint(f'Non-Confident Wrong Prediction: \\t {logloss(1, 0.49):0.4f}')\nprint(f'Non-Confident Correct Prediction: \\t {logloss(0, 0.49):0.4f}')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Your submission will have a prediction for every possible combination of tournament teams. \n- Stage 1 (not final) will be graded your score will be based on 2015-2019. It's possible to cheat and get a perfect score.. but don't do that. \n- In Stage 2 you will be graded on the outcomes of the yet to be played 2020 tournament.\n- `ID` is in the format SSSS_XXXX_YYYY, where SSSS is the four digit season number, XXXX is the four-digit TeamID of the lower-ID team, and YYYY is the four-digit TeamID of the higher-ID team. Read more here: https://www.kaggle.com/c/march-madness-analytics-2020/data"},{"metadata":{"trusted":true},"cell_type":"code","source":"Mss = pd.read_csv(f'{MENS_DIR}/MSampleSubmissionStage1_2020.csv')\nWss = pd.read_csv(f'{WOMENS_DIR}/WSampleSubmissionStage1_2020.csv')\nMss.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Team Data\n**MTeams & WTeams**\n\nTeam name and Team ID, first and last D1 Season. Sorting by the `FirstD1Season` column we can see some of the newest teams in D1 basketball. Welcome to D1 Merrimack! Cool mascot.\n![](https://media0.giphy.com/media/Q5G8oHPpDGLb0aaayD/giphy.gif)"},{"metadata":{},"cell_type":"markdown","source":"# Womens teams"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Womens' data does not contain years joined :(\nWTeams = pd.read_csv(f'{WOMENS_DIR}/WDataFiles_Stage1/WTeams.csv')\nWTeams.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(WTeams) # number of teams in total","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Seasons Data\n## WSeasons\nThese files identify the different seasons included in the historical data, along with certain season-level properties.\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"WSeasons = pd.read_csv(f'{WOMENS_DIR}/WDataFiles_Stage1/WSeasons.csv')\nWSeasons.head()\n\n# Day Zero : first day of the season\n# Regions = to identify the four regions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WSeasons","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Tourney Seed Data\n\n## WNCAATourneySeeds for the NCAA Tournament : March Madness\n\nThis file identifies the seeds for all teams in each NCAA® tournament, for all seasons of historical data."},{"metadata":{"trusted":true},"cell_type":"code","source":"WNCAATourneySeeds = pd.read_csv(f'{WOMENS_DIR}/WDataFiles_Stage1/WNCAATourneySeeds.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WNCAATourneySeeds.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# lets get the seeds for 2019\n# teams selected for the March Madness\nmarch_2019 = WNCAATourneySeeds[WNCAATourneySeeds['Season'] == 2019]\nmarch_2019","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# let's join this with the teams data to see some of the past matchups\n\nteams = WNCAATourneySeeds.merge(WTeams, validate='many_to_one')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"teams","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(teams['TeamID'].unique()) # teams selected for the NCAA","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"count = teams.groupby('TeamName').count() # to see old and pretty young teams\ncount = count.sort_values('TeamID', ascending = False)\nold_teams = count[count['Season']>10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (40,39))\nplt.barh(count.index[:30], count['TeamID'][:30])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n"},{"metadata":{},"cell_type":"markdown","source":"# Regular Season Results\n## WRegularSeasonCompactResults\n\nThese files identify the game-by-game NCAA® tournament results for all seasons of historical data."},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularSeasonCompactResults = pd.read_csv(f'{WOMENS_DIR}/WDataFiles_Stage1/WRegularSeasonCompactResults.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# We have the team the won, lost and the score.\nWRegularSeasonCompactResults.head(5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can join our regular season results on the team names to more clearly identify the games."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Lets Add the winning and losing team names to the results\n\nWRegularSeasonCompactResults = \\\n    WRegularSeasonCompactResults \\\n    .merge(WTeams[['TeamName', 'TeamID']],\n           left_on='WTeamID',\n           right_on='TeamID',\n           validate='many_to_one') \\\n    .drop('TeamID', axis=1) \\\n    .rename(columns={'TeamName': 'WTeamName'}) \\\n    .merge(WTeams[['TeamName', 'TeamID']],\n           left_on='LTeamID',\n           right_on='TeamID') \\\n    .drop('TeamID', axis=1) \\\n    .rename(columns={'TeamName': 'LTeamName'})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularSeasonCompactResults","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results_post_2015 = WRegularSeasonCompactResults[WRegularSeasonCompactResults['Season']>2014]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"victories = WRegularSeasonCompactResults.groupby(['Season', 'WTeamName']).count()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"victories =victories.reset_index()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Visualize number of wins per team Since 2015"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in [2015,2016,2017,2018,2019]: \n    plt.style.use('fivethirtyeight')\n    data =  victories[victories['Season']==i] \n    data = data.sort_values('DayNum', ascending = False)\n    plt.figure(figsize = (15,12))\n    a = 'Season '+str(i)\n    plt.title(a)\n    plt.barh(data['WTeamName'][:20], data['DayNum'][:20])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularSeasonCompactResults.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# score difference \nWRegularSeasonCompactResults['Score_Diff'] = WRegularSeasonCompactResults['WScore'] - WRegularSeasonCompactResults['LScore']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results_2009 = WRegularSeasonCompactResults[WRegularSeasonCompactResults['Season']>2009]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Most Winning teams in general"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.style.use('fivethirtyeight')\nWRegularSeasonCompactResults['counter'] = 1\nWRegularSeasonCompactResults.groupby('WTeamName')['counter'] \\\n    .count() \\\n    .sort_values() \\\n    .tail(20) \\\n    .plot(kind='barh',\n          title='Most Winning (Regular Season) Womens Teams',\n          figsize=(15, 8),\n          xlim=(400, 680),\n          color=mypal[0])\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# after 2009\n\nplt.style.use('fivethirtyeight')\nresults_2009['counter'] = 1\nresults_2009.groupby('WTeamName')['counter'] \\\n    .count() \\\n    .sort_values() \\\n    .tail(20) \\\n    .plot(kind='barh',\n          title='Most Winning (Regular Season) Teams after 2009',\n          figsize=(15, 8),\n          xlim=(10, 350),\n          color=mypal[1])\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"teams_2019 = WRegularSeasonCompactResults[WRegularSeasonCompactResults['Season']==2019]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(teams_2019['WTeamID'].unique())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Results NCAA Tournament "},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults = pd.read_csv(f'{WOMENS_DIR}/WDataFiles_Stage1/WNCAATourneyCompactResults.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults = \\\n    WRegularTourneyCompactResults \\\n    .merge(WTeams[['TeamName', 'TeamID']],\n           left_on='WTeamID',\n           right_on='TeamID',\n           validate='many_to_one') \\\n    .drop('TeamID', axis=1) \\\n    .rename(columns={'TeamName': 'WTeamName'}) \\\n    .merge(WTeams[['TeamName', 'TeamID']],\n           left_on='LTeamID',\n           right_on='TeamID') \\\n    .drop('TeamID', axis=1) \\\n    .rename(columns={'TeamName': 'LTeamName'})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults['Score_Diff'] = WRegularTourneyCompactResults['WScore'] - WRegularTourneyCompactResults['LScore']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WNCAATourneySeeds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults = \\\n    WRegularTourneyCompactResults \\\n    .merge(WNCAATourneySeeds[['Seed', 'TeamID', 'Season']],\n           left_on=['WTeamID', 'Season'],\n           right_on=['TeamID','Season'],\n           validate='many_to_one') \\\n    .drop('TeamID', axis=1) \\\n    .rename(columns={'Seed': 'WSeed'}) \\\n    .merge(WNCAATourneySeeds[['Seed', 'TeamID', 'Season']],\n           left_on=['LTeamID', 'Season'],\n           right_on=['TeamID','Season'],\n           validate='many_to_one') \\\n    .drop('TeamID', axis=1) \\\n    .rename(columns={'Seed': 'LSeed'})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults = WRegularTourneyCompactResults.sort_values(['Season', 'DayNum'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> It could be interesting to check the seeds of every team and the \"unexpected\" results (Cinderella) "},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults= WRegularTourneyCompactResults.reset_index()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults['index']=WRegularTourneyCompactResults.index","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Add Rounds to Tourney Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults['Round'] = 0 \n#WRegularTourneyCompactResults = WRegularTourneyCompactResults.reset_index()\nfor i in WRegularTourneyCompactResults.index: \n    \n    if WRegularTourneyCompactResults['Season'][i]<2003 :\n        #print(WRegularTourneyCompactResults['Season'][i])\n        #print(WRegularTourneyCompactResults['DayNum'][i])\n        if WRegularTourneyCompactResults['DayNum'][i] == 137 :\n            WRegularTourneyCompactResults['Round'][i]= 1 \n        elif WRegularTourneyCompactResults['DayNum'][i] == 138: \n            WRegularTourneyCompactResults['Round'][i]= 1 \n            \n        elif WRegularTourneyCompactResults['DayNum'][i] == 139 :\n            WRegularTourneyCompactResults['Round'][i]= 2 \n        elif WRegularTourneyCompactResults['DayNum'] [i] == 140 :\n            WRegularTourneyCompactResults['Round'][i]= 2 \n            \n        elif WRegularTourneyCompactResults['DayNum'][i] ==145 :\n            WRegularTourneyCompactResults['Round'][i]= 3 \n        elif WRegularTourneyCompactResults['DayNum'][i] ==147 :\n            WRegularTourneyCompactResults['Round'][i]= 4 \n        elif WRegularTourneyCompactResults['DayNum'][i] ==151: \n            WRegularTourneyCompactResults['Round'][i]= 5\n        else: #WRegularTourneyCompactResults['DayNum'][i]==153:\n            WRegularTourneyCompactResults['Round'][i]= 6\n                \n\n    else :   \n        WRegularTourneyCompactResults['Round'][i] = 0 \n        if WRegularTourneyCompactResults['Season'][i]<2015 : \n            if WRegularTourneyCompactResults['DayNum'][i] ==138 :\n                WRegularTourneyCompactResults['Round'][i]= 1 \n            elif WRegularTourneyCompactResults['DayNum'][i] ==139: \n                WRegularTourneyCompactResults['Round'][i]= 1\n            elif WRegularTourneyCompactResults['DayNum'][i] == 140 :\n                WRegularTourneyCompactResults['Round'][i]= 2\n            elif WRegularTourneyCompactResults['DayNum'][i] ==141:\n                WRegularTourneyCompactResults['Round'][i]= 2 \n            elif WRegularTourneyCompactResults['DayNum'][i] ==145 :\n                WRegularTourneyCompactResults['Round'][i]= 3 \n            elif WRegularTourneyCompactResults['DayNum'][i] ==146:\n                WRegularTourneyCompactResults['Round'][i]= 3 \n            elif WRegularTourneyCompactResults['DayNum'][i] ==147:\n                WRegularTourneyCompactResults['Round'][i]= 4\n            elif WRegularTourneyCompactResults['DayNum'][i] ==148:\n                WRegularTourneyCompactResults['Round'][i]= 4 \n            elif WRegularTourneyCompactResults['DayNum'][i] ==153: \n                WRegularTourneyCompactResults['Round'][i]= 5\n            else: #WRegularTourneyCompactResults['DayNum'][i]==155:\n                WRegularTourneyCompactResults['Round'][i]= 6\n    \n        else :  \n            if WRegularTourneyCompactResults['Season'][i]<2017 : \n\n                if WRegularTourneyCompactResults['DayNum'][i] ==137:\n                    WRegularTourneyCompactResults['Round'][i]= 1\n                elif WRegularTourneyCompactResults['DayNum'][i] ==138:\n                    WRegularTourneyCompactResults['Round'][i]= 1 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==139 or WRegularTourneyCompactResults['DayNum'][i] ==140:\n                    WRegularTourneyCompactResults['Round'][i]= 2 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==144 or WRegularTourneyCompactResults['DayNum'][i] ==145:\n                    WRegularTourneyCompactResults['Round'][i]= 3 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==146 or WRegularTourneyCompactResults['DayNum'][i] ==147:\n                    WRegularTourneyCompactResults['Round'][i]= 4 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==153: \n                    WRegularTourneyCompactResults['Round'][i]= 5\n                else: # WRegularTourneyCompactResults['DayNum'][i]==155:\n                    WRegularTourneyCompactResults['Round'][i]= 6\n\n            else : \n                if WRegularTourneyCompactResults['DayNum'][i] ==137 or WRegularTourneyCompactResults['DayNum'][i] ==138:\n                    WRegularTourneyCompactResults['Round'][i]= 1 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==139 or WRegularTourneyCompactResults['DayNum'][i] ==140:\n                    WRegularTourneyCompactResults['Round'][i]= 2 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==144 or WRegularTourneyCompactResults['DayNum'][i] ==145:\n                    WRegularTourneyCompactResults['Round'][i]= 3 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==146 or WRegularTourneyCompactResults['DayNum'][i] ==147:\n                    WRegularTourneyCompactResults['Round'][i]= 4 \n                elif WRegularTourneyCompactResults['DayNum'][i] ==151: \n                    WRegularTourneyCompactResults['Round'][i]= 5\n                else: # WRegularTourneyCompactResults['DayNum'][i] ==153:\n                    WRegularTourneyCompactResults['Round'][i]= 6  \n            ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Add Regions to Results"},{"metadata":{"trusted":true},"cell_type":"code","source":"\nWRegularTourneyCompactResults['Region']=''\nfor i in WRegularTourneyCompactResults.index:\n    if WRegularTourneyCompactResults['LSeed'][i][0] == WRegularTourneyCompactResults['WSeed'][i][0]: \n        WRegularTourneyCompactResults['Region'][i]=WRegularTourneyCompactResults['LSeed'][i][0]\n    else : \n        WRegularTourneyCompactResults['Region'][i]=WRegularTourneyCompactResults['WSeed'][i][0] + WRegularTourneyCompactResults['LSeed'][i][0]\n        \n        ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Add Seeds to results"},{"metadata":{"trusted":true},"cell_type":"code","source":"WRegularTourneyCompactResults['Seeds']=''\nfor i in WRegularTourneyCompactResults.index: \n    WRegularTourneyCompactResults['Seeds'][i] = str(WRegularTourneyCompactResults['WSeed'][i][1:]) + '-' + str(int(WRegularTourneyCompactResults['LSeed'][i][1:]))\n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Cinderellas (surprises) for the tournament"},{"metadata":{"trusted":true},"cell_type":"code","source":"cinderella= pd.DataFrame()\nsame_seed = pd.DataFrame()\npredicted =pd.DataFrame()\n\nfor i in WRegularTourneyCompactResults.index: \n    if int(WRegularTourneyCompactResults['WSeed'][i][1:])>int(WRegularTourneyCompactResults['LSeed'][i][1:]):\n        #print((WRegularTourneyCompactResults['WSeed'][i][1:], WRegularTourneyCompactResults['LSeed'][i][1:]))\n        cinderella = pd.concat([cinderella, pd.DataFrame(WRegularTourneyCompactResults[WRegularTourneyCompactResults['index']==i])])\n    elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==int(WRegularTourneyCompactResults['LSeed'][i][1:]):\n        same_seed = pd.concat([same_seed, pd.DataFrame(WRegularTourneyCompactResults[WRegularTourneyCompactResults['index']==i])])\n    \n    else : \n        predicted = pd.concat([predicted, pd.DataFrame(WRegularTourneyCompactResults[WRegularTourneyCompactResults['index']==i])])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# surprises \ncinderella= cinderella.reset_index()\n\n# same seed games \nsame_seed =same_seed.reset_index()\n\n# predicted wins with seeds \npredicted =predicted.reset_index()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Look at resutls according to rounds"},{"metadata":{"trusted":true},"cell_type":"code","source":"round_6 = WRegularTourneyCompactResults[WRegularTourneyCompactResults['Round']==6]\nround_1 = WRegularTourneyCompactResults[WRegularTourneyCompactResults['Round']==1]\nround_5 = WRegularTourneyCompactResults[WRegularTourneyCompactResults['Round']==5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Surprises at Round 1 \nplt.figure(figsize =(30,30))\ntest = round_1.groupby('Seeds').count()\ntest = test.sort_values('Season')\nplt.bar(test.index, test['Season'])\nplt.title('Surprises according to seeds')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Surprised in Semis (Round 5)\n\nplt.figure(figsize =(30,30))\ntest = round_5.groupby('Seeds').count()\ntest = test.sort_values('Season')\nplt.bar(test.index, test['Season'])\nplt.title('Surprises according to seeds')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Surprises in Final (round 6)\n\nplt.figure(figsize =(30,30))\ntest = round_6.groupby('Seeds').count()\ntest = test.sort_values('Season')\nplt.bar(test.index, test['Season'])\nplt.title('Surprises according to seeds')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Same Seed Games Proportion"},{"metadata":{"trusted":true},"cell_type":"code","source":"(len(same_seed)/len(WRegularTourneyCompactResults))*100","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Same seeds games represent only 2 % of the total games\n(Only one in 2019 = the final)"},{"metadata":{"trusted":true},"cell_type":"markdown","source":"## Results in 2019"},{"metadata":{"trusted":true},"cell_type":"code","source":"cinderella_2019 = cinderella[cinderella['Season']==2019]\nmarch_2019 = WRegularTourneyCompactResults[WRegularTourneyCompactResults['Season']==2019]\nmarch_2019 = march_2019.sort_values('DayNum')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Surprises Proportions since 1998"},{"metadata":{"trusted":true},"cell_type":"code","source":"(len(cinderella)/len(WRegularTourneyCompactResults))*100","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"21.5 % of surprises over the years"},{"metadata":{},"cell_type":"markdown","source":"### Surprises Proportions in 2019"},{"metadata":{"trusted":true},"cell_type":"code","source":"# in 2019\nlen(cinderella_2019)/len(march_2019)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> by using the seeds you would have got 83% accuracy in 2019 : so it's going to be the baseline to improve the model"},{"metadata":{},"cell_type":"markdown","source":"# Little and Big Cinderellas\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# get the ones with more than 1 seed difference \n# for ex match between W01 and W02 wont count \n\nbig_cinderella = pd.DataFrame()\nlittle_cinderella = pd.DataFrame()\nfor i in cinderella.index: \n    if int(cinderella['WSeed'][i][1:]) - int(cinderella['LSeed'][i][1:])>1 :\n        big_cinderella = pd.concat([big_cinderella, pd.DataFrame(cinderella[WRegularTourneyCompactResults['index']==i])])\n    else : \n        little_cinderella = pd.concat([little_cinderella, pd.DataFrame(cinderella[WRegularTourneyCompactResults['index']==i])])\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Big Cinderellas ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"(len(big_cinderella)/len(WRegularTourneyCompactResults))*100","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"13% of games are big surprises "},{"metadata":{"trusted":true},"cell_type":"code","source":"big_cinderella.groupby('Seeds').count()['Season'].sort_values().plot(kind = 'barh',\n          title='Seeds for big cinderellas',\n          figsize=(15, 8),\n          color=mypal[0])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Little Cinderellas"},{"metadata":{"trusted":true},"cell_type":"code","source":"(len(little_cinderella)/len(WRegularTourneyCompactResults))*100","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"8.6% = little surprises (1 seed difference) "},{"metadata":{"trusted":true},"cell_type":"code","source":"little_cinderella.groupby('Seeds').count()['Season'].sort_values().plot(kind = 'barh',\n          title='Seeds for Little cinderellas',\n          figsize=(15, 8),\n          color=mypal[0])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Cinderellas Over the Years"},{"metadata":{"trusted":true},"cell_type":"code","source":"# number of surprises over the years\nplt.style.use('fivethirtyeight')\ntest = cinderella.groupby('Season').count()\nplt.bar(test.index, test['index'])\nplt.title('Cinderellas over the years')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### BIG CINDERELLAS "},{"metadata":{"trusted":true},"cell_type":"code","source":"# number of big surprises over the years\nplt.style.use('fivethirtyeight')\ntest = big_cinderella.groupby('Season').count()\nplt.bar(test.index, big_cinderella.groupby('Season').count()['index'])\nplt.title('Big Cinderellas over the years')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Cinderellas according to ROUNDS"},{"metadata":{"trusted":true},"cell_type":"code","source":"# predict surprises according to rounds\n\ntest = cinderella.groupby('Round').count()\nplt.bar(test.index, test['Season'])\nplt.title('Surprises over the years according to rounds')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# in 2019 \n\ntest = cinderella_2019.groupby('Round').count()\nplt.bar(test.index, test['Season'])\nplt.title('Surprises in each round in season 2019')\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### SURPRISES ACCORDING TO SEED REGIONS : W,Y,X Z"},{"metadata":{"trusted":true},"cell_type":"code","source":"test = cinderella.groupby('Region').count()\nplt.bar(test.index, test['Season'])\nplt.title('Surprises IN REGIONS')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### SURPRISES ACCORDING TO SEED REGIONS EACH YEAR : "},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in cinderella['Season'].unique():\n    cind =cinderella[cinderella['Season']==i ]\n    test = cind.groupby('Region').count()\n    plt.figure()\n    plt.bar(test.index, test['Season'])\n    plt.title(i)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# code to get surprises per year per region per round\n\n'''for i in cinderella['Season'].unique()[20:]:\n    cind =cinderella[cinderella['Season']==i ]\n    \n    for j in cind['Region'].unique():\n        cind2 = cind[cind['Region']==j]\n        test = cind2.groupby('Round').count()\n        \n        plt.figure(figsize =(20,20))\n        plt.bar(test.index, test['Season'])\n        hello = str(i)+' in region ' + str(j)\n        plt.title(hello)'''","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* ## Surprises according to seeds combinations for all cinderellas"},{"metadata":{"trusted":true},"cell_type":"code","source":"cinderella.groupby('Seeds').count()['Season'].sort_values().plot(kind = 'barh',\n          title='Seeds for All cinderellas',\n          figsize=(15, 8),\n          color=mypal[0])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Seeds per Season for cinderellas"},{"metadata":{"trusted":true},"cell_type":"code","source":"# what seeds are involved mostly \nfor i in cinderella['Season'].unique():\n    cind.groupby('Seeds').count()['Season'].sort_values().plot(kind = 'barh',\n              title='Seeds for All cinderellas in '+str(i) ,\n              figsize=(15, 8),\n              color=mypal[0])\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Big Cinderellas per Season per Region "},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in big_cinderella['Season'].unique():\n    cind =big_cinderella[big_cinderella['Season']==i ]\n    cind.groupby('Region').count()['Season'].sort_values().plot(kind = 'barh',\n              title='Big Cinderellas in Season ' +str(i) ,\n              figsize=(15, 8),\n              color=mypal[0])\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Seeds Surprises after 2009"},{"metadata":{"trusted":true},"cell_type":"code","source":"\ncinderella_post_2010 = cinderella[cinderella['Season']>2009]\nplt.figure(figsize =(30,30))\ntest = cinderella_post_2010.groupby('Seeds').count()\ntest = test.sort_values('Season')\nplt.bar(test.index, test['Season'])\nplt.title('Surprises according to seeds')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# to get the round of each seed combination\ntryt = cinderella[cinderella['Seeds']=='07-2']\ntryt","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- 05-4 Round 2\n- 06-3 Round 2\n- 11-3 Round 2\n- 02-1 Round 4 \n- 07 - 2 Round 2 \n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"big_cinderella_2019 = big_cinderella[big_cinderella['Season']==2019]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"big_cinderella_2019","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":""},{"metadata":{},"cell_type":"markdown","source":"### Proportions of little and big cinderellas"},{"metadata":{"trusted":true},"cell_type":"code","source":"(len(big_cinderella)/len(WRegularTourneyCompactResults))*100","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"(len(little_cinderella)/len(WRegularTourneyCompactResults))*100","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"what is gonna improve the score accuracy considerably is to detect little and big cinderellas \nlike the matches between seeds really close "},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"markdown","source":"\n        \n         \n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# find the round for each game but NOT WORKING VERSIONA\n\n'''\nWRegularTourneyCompactResults['Round']= 0\nfor i in WRegularTourneyCompactResults.index :\n    for k in range(len(L)):     \n        if int(WRegularTourneyCompactResults['WSeed'][i][1:])==L[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M[k]:\n            WRegularTourneyCompactResults['Round'][i]= 1                                                                      \n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L[k]:\n            WRegularTourneyCompactResults['Round'][i]= 1                                                                         \n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==L[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M_2[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2                                                                           \n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M_2[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==L_2[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L_2[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==L[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L_2[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==L_2[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M_2[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M_2[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M[k]:\n            WRegularTourneyCompactResults['Round'][i]= 2\n            \n\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==L[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L[k-4]:\n            WRegularTourneyCompactResults['Round'][i]= 3\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==L[k-4] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L[k]:\n            WRegularTourneyCompactResults['Round'][i]= 3\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M[k-4]:\n            WRegularTourneyCompactResults['Round'][i]= 3\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M[k-4] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M[k]:\n            WRegularTourneyCompactResults['Round'][i]= 3\n            \n\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==L[k] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== M[k-4]:\n            WRegularTourneyCompactResults['Round'][i]= 3\n        elif int(WRegularTourneyCompactResults['WSeed'][i][1:])==M[k-4] and int(WRegularTourneyCompactResults['LSeed'][i][1:])== L[k]:\n            WRegularTourneyCompactResults['Round'][i]= 3\n\n'''\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#2017 season through 2020 season:\n#Round 1 = days 137/138 (Fri/Sat)\n#Round 2 = days 139/140 (Sun/Mon)\n#Round 3 = days 144/145 (Sweet Sixteen, Fri/Sat)\n#Round 4 = days 146/147 (Elite Eight, Sun/Mon)\n#National Seminfinal = day 151 (Fri)\n#National Final = day 153 (Sun)\n\n#2015 season and 2016 season:\n#Round 1 = days 137/138 (Fri/Sat)\n#Round 2 = days 139/140 (Sun/Mon)\n#Round 3 = days 144/145 (Sweet Sixteen, Fri/Sat)\n#Round 4 = days 146/147 (Elite Eight, Sun/Mon)\n#National Seminfinal = day 153 (Sun)\n#National Final = day 155 (Tue)\n\n#2003 season through 2014 season:\n#Round 1 = days 138/139 (Sat/Sun)\n#Round 2 = days 140/141 (Mon/Tue)\n#Round 3 = days 145/146 (Sweet Sixteen, Sat/Sun)\n#Round 4 = days 147/148 (Elite Eight, Mon/Tue)\n#National Seminfinal = day 153 (Sun)\n#National Final = day 155 (Tue)\n\n#1998 season through 2002 season:\n#Round 1 = days 137/138 (Fri/Sat)\n#Round 2 = days 139/140 (Sun/Mon)\n#Round 3 = day 145 only (Sweet Sixteen, Sat)\n#Round 4 = day 147 only (Elite Eight, Mon)\n#National Seminfinal = day 151 (Fri)\n#National Final = day 153 (Sun)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Day #133 is Selection Monday (for the women's tournament).\n\n137 = First Round in 2019\nFirst round SEEDS: \n- 16 - 1\n- 15 - 2\n- 14 - 3\n- 13 - 4\n- 12 - 5 \n- 11 - 6\n- 10 - 7\n- 9 - 8"},{"metadata":{},"cell_type":"markdown","source":"# STATS PLAYERS\n> "},{"metadata":{},"cell_type":"markdown","source":"### PLAYERS NAMES AND ID"},{"metadata":{"trusted":true},"cell_type":"code","source":"WPlayers = pd.read_csv(f'{WOMENS_DIR}/WPlayers.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WPlayers","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Event Data SINCE 2015 FOR EACH GAME\n\nEach MEvents & WEvents file lists the play-by-play event logs for more than 99.5% of games from that season.\nEach event is assigned to either a team or a single one of the team's players.\nThus if a basket is made by one player and an assist is credited to a second player,\nthat would show up as two separate records. The players are listed by PlayerID within the xPlayers.csv file.\n\nWomens Event Files:\n- WEvents2015.csv, WEvents2016.csv, WEvents2017.csv, WEvents2018.csv, WEvents2019.csv\n\nWe can read in all files and combine into one huge dataframe, one for womens and one for mens."},{"metadata":{"trusted":true},"cell_type":"code","source":"womens_events = []\nfor year in [2015, 2016, 2017, 2018, 2019]:\n    womens_events.append(pd.read_csv(f'{WOMENS_DIR}/WEvents{year}.csv'))\nWEvents = pd.concat(womens_events)\nprint(WEvents.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WEvents.head()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"del womens_events\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### MERGE PLAYERS AND EVENTS "},{"metadata":{"trusted":true},"cell_type":"code","source":"# Merge Player name onto events\n\nWEvents = WEvents.merge(WPlayers,\n              how='left',\n              left_on='EventPlayerID',\n              right_on='PlayerID')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WEvents","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Event Types\nplt.style.use('fivethirtyeight')\nWEvents['counter'] = 1\nWEvents.groupby('EventType')['counter'] \\\n    .sum() \\\n    .sort_values(ascending=False) \\\n    .plot(kind='bar',\n          figsize=(15, 5),\n         color=mypal[3],\n         title='Event Type Frequency (Womens)')\nplt.xticks(rotation=0)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"It could be interesting to check what players have better stats the average "},{"metadata":{},"cell_type":"markdown","source":"CRITERIA FOR BEST STATS: \n- made2 \n- made3\n- steal \n- block \n- reb \n- assist\n\nNEGATIVE CRITERIA : \n- miss2 \n- miss3 \n\nINTERESTING = RADIO MADE / MISS + MADE (reussite) "},{"metadata":{},"cell_type":"markdown","source":"### Get the games in the season against teams with cinderellas "},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"games = pd.DataFrame()\nfor i in cinderella.index:\n    for j in WRegularSeasonCompactResults.index: \n        if cinderella['Season'][i] == WRegularSeasonCompactResults['Season'][j]: \n            if cinderella['WTeamID'][i]==WRegularSeasonCompactResults['WTeamID'][i] and cinderella['LTeamID'][i]==WRegularSeasonCompactResults['LTeamID'][i] :\n                games = pd.concat([games, pd.DataFrame(WRegularTourneyCompactResults[WRegularTourneyCompactResults['index']==i])])\n\n"},{"metadata":{},"cell_type":"markdown","source":"# Area of Event\nWe are told that the `Area` feature describes the 13 \"areas\" of the court, as follows: 1=under basket; 2=in the paint; 3=inside right wing; 4=inside right; 5=inside center; 6=inside left; 7=inside left wing; 8=outside right wing; 9=outside right; 10=outside center; 11=outside left; 12=outside left wing; 13=backcourt.\n\nWe can map these values to their names."},{"metadata":{"trusted":true},"cell_type":"code","source":"area_mapping = {0: np.nan,\n                1: 'under basket',\n                2: 'in the paint',\n                3: 'inside right wing',\n                4: 'inside right',\n                5: 'inside center',\n                6: 'inside left',\n                7: 'inside left wing',\n                8: 'outside right wing',\n                9: 'outside right',\n                10: 'outside center',\n                11: 'outside left',\n                12: 'outside left wing',\n                13: 'backcourt'}\n\nWEvents['Area_Name'] = WEvents['Area'].map(area_mapping)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WEvents.groupby('Area_Name')['counter'].sum() \\\n    .sort_values() \\\n    .plot(kind='barh',\n          figsize=(15, 8),\n          title='Frequency of Event Area')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(15, 8))\nfor i, d in WEvents.loc[~WEvents['Area_Name'].isna()].groupby('Area_Name'):\n    d.plot(x='X', y='Y', style='.', label=i, ax=ax, title='Visualizing Event Areas')\n    ax.legend()\nplt.legend(bbox_to_anchor=(1.04,1), loc=\"upper left\")\nax.set_xticks([])\nax.set_yticks([])\nax.set_xlabel('')\nax.set_xlim(0, 100)\nax.set_ylim(0, 100)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting X, Y Data\nThis is some of the most exciting data provided, but after looking there are some things to consider.\n- X, Y points are not available for all games- so this is not a complete sample\n- The X/Y position is provided for fouls, turnovers, and field-goal attempts (either 2-point or 3-point). No X/Y data for other events."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Normalize X, Y positions for court dimentions\n# Court is 50 feet wide and 94 feet end to end.\n\nWEvents['X_'] = (WEvents['X'] * (94/100))\nWEvents['Y_'] = (WEvents['Y'] * (50/100))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# NCAA Court Plot Function"},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_ncaa_full_court(ax=None, three_line='mens', court_color='#dfbb85',\n                           lw=3, lines_color='black', lines_alpha=0.5,\n                           paint_fill='blue', paint_alpha=0.4):\n    \"\"\"\n    Creates NCAA Basketball\n    Dimensions are in feet (Court is 97x50 ft)\n    Created by: Rob Mulla / https://github.com/RobMulla\n\n    * Note that this function uses \"feet\" as the unit of measure.\n    * NCAA Data is provided on a x range: 0, 100 and y-range 0 to 100\n    * To plot X/Y positions first convert to feet like this:\n    ```\n    Events['X_'] = (Events['X'] * (94/100))\n    Events['Y_'] = (Events['Y'] * (50/100))\n    ```\n\n    three_line: 'mens', 'womens' or 'both' defines 3 point line plotted\n    court_color : (hex) Color of the court\n    lw : line width\n    lines_color : Color of the lines\n    paint_fill : Color inside the paint\n    paint_alpha : transparency of the \"paint\"\n    \"\"\"\n    if ax is None:\n        ax = plt.gca()\n\n    # Create Pathes for Court Lines\n    center_circle = Circle((94/2, 50/2), 6,\n                           linewidth=lw, color=lines_color, lw=lw,\n                           fill=False, alpha=lines_alpha)\n#     inside_circle = Circle((94/2, 50/2), 2,\n#                            linewidth=lw, color=lines_color, lw=lw,\n#                            fill=False, alpha=lines_alpha)\n\n    hoop_left = Circle((5.25, 50/2), 1.5 / 2,\n                       linewidth=lw, color=lines_color, lw=lw,\n                       fill=False, alpha=lines_alpha)\n    hoop_right = Circle((94-5.25, 50/2), 1.5 / 2,\n                        linewidth=lw, color=lines_color, lw=lw,\n                        fill=False, alpha=lines_alpha)\n\n    # Paint - 18 Feet 10 inches which converts to 18.833333 feet - gross!\n    left_paint = Rectangle((0, (50/2)-6), 18.833333, 12,\n                           fill=paint_fill, alpha=paint_alpha,\n                           lw=lw, edgecolor=None)\n    right_paint = Rectangle((94-18.83333, (50/2)-6), 18.833333,\n                            12, fill=paint_fill, alpha=paint_alpha,\n                            lw=lw, edgecolor=None)\n    \n    left_paint_boarder = Rectangle((0, (50/2)-6), 18.833333, 12,\n                           fill=False, alpha=lines_alpha,\n                           lw=lw, edgecolor=lines_color)\n    right_paint_boarder = Rectangle((94-18.83333, (50/2)-6), 18.833333,\n                            12, fill=False, alpha=lines_alpha,\n                            lw=lw, edgecolor=lines_color)\n\n    left_arc = Arc((18.833333, 50/2), 12, 12, theta1=-\n                   90, theta2=90, color=lines_color, lw=lw,\n                   alpha=lines_alpha)\n    right_arc = Arc((94-18.833333, 50/2), 12, 12, theta1=90,\n                    theta2=-90, color=lines_color, lw=lw,\n                    alpha=lines_alpha)\n    \n    leftblock1 = Rectangle((7, (50/2)-6-0.666), 1, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    leftblock2 = Rectangle((7, (50/2)+6), 1, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    ax.add_patch(leftblock1)\n    ax.add_patch(leftblock2)\n    \n    left_l1 = Rectangle((11, (50/2)-6-0.666), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    left_l2 = Rectangle((14, (50/2)-6-0.666), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    left_l3 = Rectangle((17, (50/2)-6-0.666), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    ax.add_patch(left_l1)\n    ax.add_patch(left_l2)\n    ax.add_patch(left_l3)\n    left_l4 = Rectangle((11, (50/2)+6), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    left_l5 = Rectangle((14, (50/2)+6), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    left_l6 = Rectangle((17, (50/2)+6), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    ax.add_patch(left_l4)\n    ax.add_patch(left_l5)\n    ax.add_patch(left_l6)\n    \n    rightblock1 = Rectangle((94-7-1, (50/2)-6-0.666), 1, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    rightblock2 = Rectangle((94-7-1, (50/2)+6), 1, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    ax.add_patch(rightblock1)\n    ax.add_patch(rightblock2)\n\n    right_l1 = Rectangle((94-11, (50/2)-6-0.666), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    right_l2 = Rectangle((94-14, (50/2)-6-0.666), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    right_l3 = Rectangle((94-17, (50/2)-6-0.666), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    ax.add_patch(right_l1)\n    ax.add_patch(right_l2)\n    ax.add_patch(right_l3)\n    right_l4 = Rectangle((94-11, (50/2)+6), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    right_l5 = Rectangle((94-14, (50/2)+6), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    right_l6 = Rectangle((94-17, (50/2)+6), 0.166, 0.666,\n                           fill=True, alpha=lines_alpha,\n                           lw=0, edgecolor=lines_color,\n                           facecolor=lines_color)\n    ax.add_patch(right_l4)\n    ax.add_patch(right_l5)\n    ax.add_patch(right_l6)\n    \n    # 3 Point Line\n    if (three_line == 'mens') | (three_line == 'both'):\n        # 22' 1.75\" distance to center of hoop\n        three_pt_left = Arc((6.25, 50/2), 44.291, 44.291, theta1=-78,\n                            theta2=78, color=lines_color, lw=lw,\n                            alpha=lines_alpha)\n        three_pt_right = Arc((94-6.25, 50/2), 44.291, 44.291,\n                             theta1=180-78, theta2=180+78,\n                             color=lines_color, lw=lw, alpha=lines_alpha)\n\n        # 4.25 feet max to sideline for mens\n        ax.plot((0, 11.25), (3.34, 3.34),\n                color=lines_color, lw=lw, alpha=lines_alpha)\n        ax.plot((0, 11.25), (50-3.34, 50-3.34),\n                color=lines_color, lw=lw, alpha=lines_alpha)\n        ax.plot((94-11.25, 94), (3.34, 3.34),\n                color=lines_color, lw=lw, alpha=lines_alpha)\n        ax.plot((94-11.25, 94), (50-3.34, 50-3.34),\n                color=lines_color, lw=lw, alpha=lines_alpha)\n        ax.add_patch(three_pt_left)\n        ax.add_patch(three_pt_right)\n\n    if (three_line == 'womens') | (three_line == 'both'):\n        # womens 3\n        three_pt_left_w = Arc((6.25, 50/2), 20.75 * 2, 20.75 * 2, theta1=-85,\n                              theta2=85, color=lines_color, lw=lw, alpha=lines_alpha)\n        three_pt_right_w = Arc((94-6.25, 50/2), 20.75 * 2, 20.75 * 2,\n                               theta1=180-85, theta2=180+85,\n                               color=lines_color, lw=lw, alpha=lines_alpha)\n\n        # 4.25 inches max to sideline for mens\n        ax.plot((0, 8.3), (4.25, 4.25), color=lines_color,\n                lw=lw, alpha=lines_alpha)\n        ax.plot((0, 8.3), (50-4.25, 50-4.25),\n                color=lines_color, lw=lw, alpha=lines_alpha)\n        ax.plot((94-8.3, 94), (4.25, 4.25),\n                color=lines_color, lw=lw, alpha=lines_alpha)\n        ax.plot((94-8.3, 94), (50-4.25, 50-4.25),\n                color=lines_color, lw=lw, alpha=lines_alpha)\n\n        ax.add_patch(three_pt_left_w)\n        ax.add_patch(three_pt_right_w)\n\n    # Add Patches\n    ax.add_patch(left_paint)\n    ax.add_patch(left_paint_boarder)\n    ax.add_patch(right_paint)\n    ax.add_patch(right_paint_boarder)\n    ax.add_patch(center_circle)\n#     ax.add_patch(inside_circle)\n    ax.add_patch(hoop_left)\n    ax.add_patch(hoop_right)\n    ax.add_patch(left_arc)\n    ax.add_patch(right_arc)\n\n    # Restricted Area Marker\n    restricted_left = Arc((6.25, 50/2), 8, 8, theta1=-90,\n                        theta2=90, color=lines_color, lw=lw,\n                        alpha=lines_alpha)\n    restricted_right = Arc((94-6.25, 50/2), 8, 8,\n                         theta1=180-90, theta2=180+90,\n                         color=lines_color, lw=lw, alpha=lines_alpha)\n    ax.add_patch(restricted_left)\n    ax.add_patch(restricted_right)\n    \n    # Backboards\n    ax.plot((4, 4), ((50/2) - 3, (50/2) + 3),\n            color=lines_color, lw=lw*1.5, alpha=lines_alpha)\n    ax.plot((94-4, 94-4), ((50/2) - 3, (50/2) + 3),\n            color=lines_color, lw=lw*1.5, alpha=lines_alpha)\n    ax.plot((4, 4.6), (50/2, 50/2), color=lines_color,\n            lw=lw, alpha=lines_alpha)\n    ax.plot((94-4, 94-4.6), (50/2, 50/2),\n            color=lines_color, lw=lw, alpha=lines_alpha)\n\n    # Half Court Line\n    ax.axvline(94/2, color=lines_color, lw=lw, alpha=lines_alpha)\n\n    # Boarder\n    boarder = Rectangle((0.3,0.3), 94-0.6, 50-0.6, fill=False, lw=3, color='black', alpha=lines_alpha)\n    ax.add_patch(boarder)\n    \n    # Plot Limit\n    ax.set_xlim(0, 94)\n    ax.set_ylim(0, 50)\n    ax.set_facecolor(court_color)\n    ax.set_xticks([])\n    ax.set_yticks([])\n    ax.set_xlabel('')\n    return ax\n\n\nfig, ax = plt.subplots(figsize=(15, 8.5))\ncreate_ncaa_full_court(ax, three_line='both', paint_alpha=0.4)\nplt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(15, 7.8))\nms = 10\nax = create_ncaa_full_court(ax, paint_alpha=0.1)\nWEvents.query('EventType == \"turnover\"') \\\n    .plot(x='X_', y='Y_', style='X',\n          title='Turnover Locations (Mens)',\n          c='red',\n          alpha=0.3,\n         figsize=(15, 9),\n         label='Steals',\n         ms=ms,\n         ax=ax)\nax.set_xlabel('')\nax.get_legend().remove()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"COURT_COLOR = '#dfbb85'\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 4))\n# Where are 3 pointers made from? (This is really cool)\nWEvents.query('EventType == \"made3\"') \\\n    .plot(x='X_', y='Y_', style='.',\n          color='blue',\n          title='3 Pointers Made (Womens)',\n          alpha=0.01, ax=ax1)\nax1 = create_ncaa_full_court(ax1, lw=0.5, three_line='womens', paint_alpha=0.1)\nax1.set_facecolor(COURT_COLOR)\nWEvents.query('EventType == \"miss3\"') \\\n    .plot(x='X_', y='Y_', style='.',\n          title='3 Pointers Missed (Womens)',\n          color='red',\n          alpha=0.01, ax=ax2)\nax2.set_facecolor(COURT_COLOR)\nax2 = create_ncaa_full_court(ax2, lw=0.5, three_line='womens', paint_alpha=0.1)\nax1.get_legend().remove()\nax2.get_legend().remove()\nax1.set_xticks([])\nax1.set_yticks([])\nax2.set_xticks([])\nax2.set_yticks([])\nax1.set_xlabel('')\nax2.set_xlabel('')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"COURT_COLOR = '#dfbb85'\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 4))\n# Where are 3 pointers made from? (This is really cool)\nWEvents.query('EventType == \"made2\"') \\\n    .plot(x='X_', y='Y_', style='.',\n          color='blue',\n          title='2 Pointers Made (Womens)',\n          alpha=0.01, ax=ax1)\nax1.set_facecolor(COURT_COLOR)\nax1 = create_ncaa_full_court(ax1, lw=0.5, three_line='womens', paint_alpha=0.1)\nWEvents.query('EventType == \"miss2\"') \\\n    .plot(x='X_', y='Y_', style='.',\n          title='2 Pointers Missed (Womens)',\n          color='red',\n          alpha=0.01, ax=ax2)\nax2.set_facecolor(COURT_COLOR)\nax2 = create_ncaa_full_court(ax2, lw=0.5, three_line='womens', paint_alpha=0.1)\nax1.get_legend().remove()\nax2.get_legend().remove()\nax1.set_xticks([])\nax1.set_yticks([])\nax2.set_xticks([])\nax2.set_yticks([])\nax1.set_xlabel('')\nax2.set_xlabel('')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## PlayerIDs\nThere is an issue when trying to read in lines where the player name has a comma. We can use `error_bad_lines` to get past this, but ideally the data would be cleaned to remove the comma or a different delimiter would be used."},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"WPlayers = pd.read_csv(f'{WOMENS_DIR}/WPlayers.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"WPlayers.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"# Plotting Specific Players' Made/Missed Shots\nNow that we have player names in the event data, lets single out specific players. Starting with one of the most exciting players of the last decade.\n\n![](https://thenypost.files.wordpress.com/2018/11/zion-williamson-duke-freshman-scouting-comparables.jpg?quality=80&strip=all&w=618&h=410&crop=1)"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Next lets look at Katie Lou Samuelson. She is known to be a 3-point shooter. As such, we can see her shots mostly come from outside the 3-point line.\n\n![](https://imagesvc.timeincapp.com/v3/fan/image?url=https://highposthoops.com/wp-content/uploads/getty-images/2018/10/951142340.jpeg?&w=618&h=410&crop=1)"},{"metadata":{"trusted":true},"cell_type":"code","source":"ms = 10 # Marker Size\nFirstName = 'Katie Lou'\nLastName = 'Samuelson'\nfig, ax = plt.subplots(figsize=(15, 8))\nax = create_ncaa_full_court(ax, three_line='womens')\nWEvents.query('FirstName == @FirstName and LastName == @LastName and EventType == \"made2\"') \\\n    .plot(x='X_', y='Y_', style='o',\n          title='Shots (Katie Lou Samuelson)',\n          alpha=0.5,\n         figsize=(15, 8),\n         label='Made 2',\n         ms=ms,\n         ax=ax)\nplt.legend()\nWEvents.query('FirstName == @FirstName and LastName == @LastName and EventType == \"miss2\"') \\\n    .plot(x='X_', y='Y_', style='X',\n          alpha=0.5, ax=ax,\n         label='Missed 2',\n         ms=ms)\nplt.legend()\nWEvents.query('FirstName == @FirstName and LastName == @LastName and EventType == \"made3\"') \\\n    .plot(x='X_', y='Y_', style='o',\n          c='brown',\n          alpha=0.5,\n         figsize=(15, 8),\n         label='Made 3', ax=ax,\n         ms=ms)\nplt.legend()\nWEvents.query('FirstName == @FirstName and LastName == @LastName and EventType == \"miss3\"') \\\n    .plot(x='X_', y='Y_', style='X',\n          c='green',\n          alpha=0.5, ax=ax,\n         label='Missed 3',\n         ms=ms)\nax.set_xlabel('')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Shot Heatmap\nWe can plot a heatmap of where shots occur on the court. Interesting observation when comparing the mens to womens game is that many of the shots for mens come from directly under the hoop, while the hot spots for women shots come more frequently from the left and right of the hoop."},{"metadata":{"trusted":true},"cell_type":"code","source":"N_bins = 100\nshot_events = WEvents.loc[WEvents['EventType'].isin(['miss3','made3','miss2','made2']) & (WEvents['X_'] != 0)]\nfig, ax = plt.subplots(figsize=(15, 7))\nax = create_ncaa_full_court(ax,\n                            paint_alpha=0.0,\n                            three_line='mens',\n                            court_color='black',\n                            lines_color='white')\n_ = plt.hist2d(shot_events['X_'].values + np.random.normal(0, 0.1, shot_events['X_'].shape), # Add Jitter to values for plotting\n           shot_events['Y_'].values + np.random.normal(0, 0.1, shot_events['Y_'].shape),\n           bins=N_bins, norm=mpl.colors.LogNorm(),\n               cmap='plasma')\n\n# Plot a colorbar with label.\ncb = plt.colorbar()\ncb.set_label('Number of shots')\n\nax.set_title('Shot Heatmap (Mens)')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"N_bins = 100\nshot_events = WEvents.loc[WEvents['EventType'].isin(['miss3','made3','miss2','made2']) & (WEvents['X_'] != 0)]\nfig, ax = plt.subplots(figsize=(15, 7))\nax = create_ncaa_full_court(ax, three_line='womens', paint_alpha=0.0,\n                            court_color='black',\n                            lines_color='white')\n_ = plt.hist2d(shot_events['X_'].values + np.random.normal(0, 0.2, shot_events['X_'].shape),\n           shot_events['Y_'].values + np.random.normal(0, 0.2, shot_events['Y_'].shape),\n           bins=N_bins, norm=mpl.colors.LogNorm(),\n               cmap='plasma')\n\n# Plot a colorbar with label.\ncb = plt.colorbar()\ncb.set_label('Number of shots')\n\nax.set_title('Shot Heatmap (Womens)')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MEvents['PointsScored'] =  0\nMEvents.loc[MEvents['EventType'] == 'made2', 'PointsScored'] = 2\nMEvents.loc[MEvents['EventType'] == 'made3', 'PointsScored'] = 3\nMEvents.loc[MEvents['EventType'] == 'missed2', 'PointsScored'] = 0\nMEvents.loc[MEvents['EventType'] == 'missed3', 'PointsScored'] = 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# # Average Points Scored per xy coord\n# avg_pnt_xy = MEvents.loc[MEvents['EventType'].isin(['miss3','made3','miss2','made2']) & (MEvents['X_'] != 0)] \\\n#     .groupby(['X_','Y_'])['PointsScored'].mean().reset_index()\n\n# # .plot(x='X_',y='Y_', style='.')\n# fig, ax = plt.subplots(figsize=(15, 8))\n# ax = sns.scatterplot(data=avg_pnt_xy, x='X_', y='Y_', hue='PointsScored', cmap='coolwarm')\n# ax = create_ncaa_full_court(ax)\n# plt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# avg_made_xy.sort_values('Made')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# avg_made_xy['Made'] / avg_made_xy['Missed']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# MEvents['Made'] = False\n# MEvents['Made'] = False\n# MEvents.loc[MEvents['EventType'] == 'made2', 'Made'] = True\n# MEvents.loc[MEvents['EventType'] == 'made3', 'Made'] = True\n# MEvents.loc[MEvents['EventType'] == 'missed2', 'Made'] = False\n# MEvents.loc[MEvents['EventType'] == 'missed3', 'Made'] = False\n# MEvents.loc[MEvents['EventType'] == 'made2', 'Missed'] = False\n# MEvents.loc[MEvents['EventType'] == 'made3', 'Missed'] = False\n# MEvents.loc[MEvents['EventType'] == 'missed2', 'Missed'] = True\n# MEvents.loc[MEvents['EventType'] == 'missed3', 'Missed'] = True\n\n# # Average Pct Made per xy coord\n# avg_made_xy = MEvents.loc[MEvents['EventType'].isin(['miss3','made3','miss2','made2']) & (MEvents['X_'] != 0)] \\\n#     .groupby(['X_','Y_'])['Made','Missed'].sum().reset_index()\n\n# # .plot(x='X_',y='Y_', style='.')\n# fig, ax = plt.subplots(figsize=(15, 8))\n# cmap = sns.cubehelix_palette(as_cmap=True)\n# ax = sns.scatterplot(data=avg_made_xy, x='X_', y='Y_', size='Made', cmap='plasma')\n# ax = create_ncaa_full_court(ax, paint_alpha=0)\n# ax.set_title('Number of Shots Made')\n# plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# TODO\n- Half Court Plot\n- Normalize X,Y data to half court"},{"metadata":{},"cell_type":"markdown","source":"# Reference\n1. Court Lines code inspired by code made for plotting the NBA court. http://savvastjortjoglou.com/nba-shot-sharts.html\n2. Official NCAA Basketball Court Dimensions:"},{"metadata":{},"cell_type":"markdown","source":"![](https://og4sg2f1jmu2x9xay48pj5z1-wpengine.netdna-ssl.com/wp-content/uploads/2019/06/NCAA-Mens-and-Womens-Basketball-Court-Diagram-3-point-line-extended-2019.png)"}],"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":4,"nbformat_minor":4}