{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom tqdm import tqdm\nfrom matplotlib import pyplot as plt\nimport seaborn as sns\nsns.set_style(\"white\")\nplt.style.use('seaborn')\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n#print(os.listdir(\"../input/NFL-Punt-Analytics-Competition\"))\n#print(os.listdir(\"../input/nflplaybyplay2009to2016\"))\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"df_play_by_play=pd.read_csv('../input/nflplaybyplay2009to2016/NFL Play by Play 2009-2018 (v5).csv',low_memory=False)\nprint('we imported the kaggle play by play Dataset')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3442cd5e9dc03bfdce0a61f1307e9dbbee371bcb"},"cell_type":"code","source":"df_play_by_play_dist=df_play_by_play[df_play_by_play['yardline_100']>-1]\ndf_play_by_play_dist=df_play_by_play_dist.reset_index()\ndrivesDistance=[]\ncurrentDrive=1\ndriveBegin=0\npuntDIsts=[]\n\nfor i in tqdm(range(len(df_play_by_play_dist)-1)):\n    if df_play_by_play_dist['play_type'][i]=='kickoff':\n        if i==0:\n            currentDrive=df_play_by_play_dist['drive'][i]\n            driveBegin=df_play_by_play_dist['yardline_100'][i+1]\n        else:\n            if df_play_by_play_dist['yardline_100'][i-1]>-1:\n                drivesDistance.append(driveBegin-df_play_by_play_dist['yardline_100'][i-1])\n            else:\n                drivesDistance.append(driveBegin-df_play_by_play_dist['yardline_100'][i-2])\n            currentDrive=df_play_by_play_dist['drive'][i]\n            driveBegin=df_play_by_play_dist['yardline_100'][i+1]\n    elif currentDrive==df_play_by_play_dist['drive'][i]:\n        pass\n    else:\n        if df_play_by_play['yardline_100'][i-1]>-1:\n            drivesDistance.append(driveBegin-df_play_by_play_dist['yardline_100'][i-1])\n        else:\n            drivesDistance.append(driveBegin-df_play_by_play_dist['yardline_100'][i-2])\n        currentDrive=df_play_by_play_dist['drive'][i]\n        driveBegin=df_play_by_play_dist['yardline_100'][i]\n\ndrivesDistance.append(driveBegin-df_play_by_play_dist['yardline_100'][i+1])\n\n\nfor i in tqdm(range(len(df_play_by_play_dist))):\n    if df_play_by_play_dist['play_type'][i]=='punt':\n        puntDIsts.append(df_play_by_play_dist['yardline_100'][i]-(100-df_play_by_play_dist['yardline_100'][i+1]))\n\n\n\nprint('On average, each drive makes a team go '+ str(int(np.mean(drivesDistance)))+' yards further' )\nprint('On average, each punt give the ball to the opposite team '+ str(int(np.mean(puntDIsts))) +' yards away')\nprint('So by punting (when you are less than 40 yards to the goal) you expect to get back the ball and a first down '+str(int(np.mean(puntDIsts)-np.mean(drivesDistance)))+ ' yards further' )\nprint('Punting is very advantaging for an offense')\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bfc271b25b9355e07c9011d22e075658cbc29e13"},"cell_type":"code","source":"df_play_by_play_fourth=df_play_by_play_dist[df_play_by_play_dist['down']==4]\ndf_play_by_play_fourth['5LineYard']=df_play_by_play_fourth['yardline_100'].apply(lambda x: int(x/5))\ndf_play_by_play_fourth=df_play_by_play_fourth.reset_index()\nnb_punt_dist=[0]*20\nnb_fieldgoal_dist=[0]*20\nnb_fourth_dist=[0]*20\nnb_pass_run_kneel_fourth_dist=[0]*20\nratio_punt_dist=[]\nratio_fieldgoal_dist=[]\nratio_fieldgoal_or_punt_dist=[]\nratio_punt_per_pass_run_kneel_play_dist=[]\ndist=[]\nfor i in tqdm(range(len(df_play_by_play_fourth))):\n    nb_fourth_dist[df_play_by_play_fourth['5LineYard'][i]]+=1\n    if df_play_by_play_fourth['play_type'][i]=='punt':\n        nb_punt_dist[df_play_by_play_fourth['5LineYard'][i]]+=1\n    elif df_play_by_play_fourth['play_type'][i]=='field_goal':\n        nb_fieldgoal_dist[df_play_by_play_fourth['5LineYard'][i]]+=1\n    elif df_play_by_play_fourth['play_type'][i]=='qb_kneel' or df_play_by_play_fourth['play_type'][i]=='run' or df_play_by_play_fourth['play_type'][i]=='pass':\n        nb_pass_run_kneel_fourth_dist[df_play_by_play_fourth['5LineYard'][i]]+=1\n\nfor i in range(20):\n    ratio_punt_per_pass_run_kneel_play_dist.append(nb_punt_dist[i]/(nb_punt_dist[i]+nb_pass_run_kneel_fourth_dist[i]))\n    ratio_punt_dist.append(nb_punt_dist[i]/nb_fourth_dist[i])\n    ratio_fieldgoal_dist.append(nb_fieldgoal_dist[i]/nb_fourth_dist[i])\n    ratio_fieldgoal_or_punt_dist.append((nb_fieldgoal_dist[i]+nb_punt_dist[i])/nb_fourth_dist[i])\n    dist.append(5*i)\n    \n#plt.plot(dist,ratio_punt_dist)\n#plt.plot(dist,ratio_fieldgoal_dist)\n#plt.plot(dist,ratio_fieldgoal_or_punt_dist)\n#plt.show()\nf=plt.figure()\nplt.plot(dist,ratio_punt_per_pass_run_kneel_play_dist)\nplt.show()\nf.savefig('ratio_punt_per_pass_run_kneel_play_dist.pdf',bbox_inches='tight')\n\ngroupByYardsToGo=df_play_by_play_fourth.groupby('ydstogo')\ndist_to_go=[]\nratio_punt_dist_to_go=[]\nratio_punt_or_fieldgoal_dist_to_go=[]\nratio_punt_per_pass_run_kneel_dist_to_go=[]\nnb_fourth_yard_to_go_punt_scrimmage=[]\nfor tupleDF in groupByYardsToGo:\n    if tupleDF[0]<=20:\n        df_tmp_perYardToGo=tupleDF[1]\n        dist_to_go.append(tupleDF[0])\n        ratio_punt_per_pass_run_kneel_dist_to_go.append(len(df_tmp_perYardToGo[df_tmp_perYardToGo['play_type']=='punt'])/len(df_tmp_perYardToGo[(df_tmp_perYardToGo['play_type']=='punt')|(df_tmp_perYardToGo['play_type']=='pass')|(df_tmp_perYardToGo['play_type']=='qb_kneel')|(df_tmp_perYardToGo['play_type']=='run')]))\n        ratio_punt_or_fieldgoal_dist_to_go.append(len(df_tmp_perYardToGo[(df_tmp_perYardToGo['play_type']=='punt')|(df_tmp_perYardToGo['play_type']=='field_goal')])/len(df_tmp_perYardToGo))\n        ratio_punt_dist_to_go.append(len(df_tmp_perYardToGo[df_tmp_perYardToGo['play_type']=='punt'])/len(df_tmp_perYardToGo))\n        nb_fourth_yard_to_go_punt_scrimmage.append(len(df_tmp_perYardToGo[(df_tmp_perYardToGo['play_type']=='punt')|(df_tmp_perYardToGo['play_type']=='pass')|(df_tmp_perYardToGo['play_type']=='qb_kneel')|(df_tmp_perYardToGo['play_type']=='run')]))\n#plt.plot(dist_to_go,ratio_punt_dist_to_go)\n#plt.show()\n#plt.plot(dist_to_go,ratio_punt_or_fieldgoal_dist_to_go)\n#plt.show()\nf=plt.figure()\nplt.plot(dist_to_go,ratio_punt_per_pass_run_kneel_dist_to_go)\nplt.show()\nf.savefig('ratio_punt_per_pass_run_kneel_dist_to_go.pdf',bbox_inches='tight')\n\nprint('we can see that the ratio of punting  by fourth is depending a lot on the yardline because beneath 40 yards, fieldgoald is prefered to punting')\nprint('we only want to study punt, so we will only watch the proportion of punt among punt and scrimmages as in graph 2')\nprint('we can see that punting is majoritary choosed over scrimmage in fourth downs')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cd56c08c3ca8c3020a516d95fdffcecddc645dbe"},"cell_type":"code","source":"df_play_pass_run_kneel=df_play_by_play[(df_play_by_play['down']>0)&(df_play_by_play['yardline_100']>0)&(df_play_by_play['yards_gained']>-100)&((df_play_by_play['play_type']=='run')|(df_play_by_play['play_type']=='pass')|(df_play_by_play['play_type']=='qb_kneel')|(df_play_by_play['play_type']=='qb_spike'))]\ndf_play_pass_run_kneel=df_play_pass_run_kneel.reset_index()\nplays_yards_gained=df_play_pass_run_kneel['yards_gained']\ndic_proba_yard_gained={}\nfor i in range(len(plays_yards_gained)):\n    try:\n        dic_proba_yard_gained[plays_yards_gained[i]]+=1\n    except:\n        dic_proba_yard_gained[plays_yards_gained[i]]=1\nfor val in dic_proba_yard_gained:\n    dic_proba_yard_gained[val]=dic_proba_yard_gained[val]/len(plays_yards_gained)\n    \ndic_proba_drive_yard_gained={}\nfor i in range(len(drivesDistance)):\n    try:\n        dic_proba_drive_yard_gained[drivesDistance[i]]+=1\n    except:\n        dic_proba_drive_yard_gained[drivesDistance[i]]=1\nfor val in dic_proba_drive_yard_gained:\n    dic_proba_drive_yard_gained[val]=dic_proba_drive_yard_gained[val]/len(drivesDistance)\n\ndic_proba_drive_more_than_yard_gained={}\nfor val1 in dic_proba_drive_yard_gained:\n    dic_proba_drive_more_than_yard_gained[val1]=dic_proba_drive_yard_gained[val1]\n    for val2 in dic_proba_drive_yard_gained:\n        if val2>val1:\n            dic_proba_drive_more_than_yard_gained[val1]+=dic_proba_drive_yard_gained[val2]\n\nesperance_yards_to_go=[]\nfor i in range(1,21):\n    res=0\n    for val in dic_proba_yard_gained:\n        if val>=i:\n            res+=dic_proba_yard_gained[val]*val\n        else:\n            res+=dic_proba_yard_gained[val]*(val-27)\n    esperance_yards_to_go.append(res)\n    \nf=plt.figure()\nplt.plot(dist_to_go,esperance_yards_to_go)\nplt.show()\nf.savefig('esperance_yards_to_go.pdf',bbox_inches='tight')\n\ndf_play_pass_run_kneel['yards_gained'].hist(bins=100)\nprint('we can see that the expected return on going for a fourth is negative, it is indeed very risky compared to punting')\n\nprint('to reduce the proportion of punting over scrimmage during fourth, we want to power up the scrimmage, we propose that if a turnover of downs occur, we give the ball to the defensive team some yards away')\nprint('punt being extremely efficient, we want to make scrimmage less risky but we do not want neither that a failed fourth become more advantaging than a punt')\nprint('we want to find the best value to give back the ball, easy to do practicaly (a multiple of ten yards), that does not make punt irrelevant and still punishes a failed fourth')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"56ee4e2d17712c89c3234f97e725e008fa1d112d"},"cell_type":"code","source":"for distanceBallGiven in [0,10,20,30]:\n    esperance_yards_to_go=[]\n    for i in range(1,21):\n        res=0\n        for val in dic_proba_yard_gained:\n            if val>=i:\n                res+=dic_proba_yard_gained[val]*val\n            else:\n                for val2 in dic_proba_drive_yard_gained:\n                    res+=dic_proba_yard_gained[val]*dic_proba_drive_yard_gained[val2]*(val-val2+distanceBallGiven)\n        esperance_yards_to_go.append(res)\n    f=plt.figure()\n    plt.plot(dist_to_go,esperance_yards_to_go)\n    plt.show()\n    f.savefig('esperance_yards_to_go'+str(distanceBallGiven)+'.pdf',bbox_inches='tight')\nprint('we can see here that we can improve the expected value of going for the fourth to positive values until 20 yards without making it more advantagous to fail the fourth')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8d07653aab4c0f2e0b56c39e4367ebb9af27a820"},"cell_type":"code","source":"print('no we want to measure the impact on the proportion of scrimmage of this rule')\nmean_dist_punt=np.mean(puntDIsts)\nproba_better_scrimmage_than_punt=[]\nfor i in range(1,21):\n    res=0\n    for val in dic_proba_yard_gained:\n        if val>=i:\n            for val2 in dic_proba_drive_yard_gained:\n                if mean_dist_punt-val2<=val:\n                    res+=dic_proba_yard_gained[val]*dic_proba_drive_yard_gained[val2]\n\n    proba_better_scrimmage_than_punt.append(1-res)\n#proba_better_scrimmage_than_punt[0]=ratio_punt_per_pass_run_kneel_dist_to_go[0]\nprint('probability of having better result with punt than scrimmage (we ignore 4th and one which is already favorised a lot by coaches)')\nf=plt.figure()\nplt.plot(dist_to_go[1:],ratio_punt_per_pass_run_kneel_dist_to_go[1:])\nplt.plot(dist_to_go[1:],proba_better_scrimmage_than_punt[1:])\nplt.show()\nf.savefig('proba_better_scrimmage_than_punt_and_ratio_punt_per_pass_run_kneel_dist_to_go.pdf',bbox_inches='tight')\n\nprint(np.mean(proba_better_scrimmage_than_punt))\nprint(np.mean(ratio_punt_per_pass_run_kneel_dist_to_go))\nprint('we can see that the two courbs are very similar, so the coachs are naturally following probability laws when they choose wether to go for the fourth or to punt')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dc79ddef8f3b770465b167649e83e5ee273c1cb1"},"cell_type":"code","source":"proba_better_scrimmage_than_punt_with_20_yard=[]\nfor i in tqdm(range(1,21)):\n    res=0\n    for val in dic_proba_yard_gained:\n        if val>=i:\n            for val2 in dic_proba_drive_yard_gained:\n                if mean_dist_punt-val2<=val:\n                    res+=dic_proba_yard_gained[val]*dic_proba_drive_yard_gained[val2]\n        else:\n            for val2 in dic_proba_drive_yard_gained:\n                for val3 in dic_proba_drive_yard_gained:\n                    if mean_dist_punt-val2<=val+20-val3:\n                        res+=dic_proba_yard_gained[val]*dic_proba_drive_yard_gained[val2]*dic_proba_drive_yard_gained[val3]\n    proba_better_scrimmage_than_punt_with_20_yard.append(1-res)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e1775c4d07d64becf7c8868124560fcef049948a"},"cell_type":"code","source":"np.mean(proba_better_scrimmage_than_punt_with_20_yard)\nf=plt.figure()\nplt.plot(dist_to_go[1:],proba_better_scrimmage_than_punt_with_20_yard[1:])\nplt.show()\nf.savefig('proba_better_scrimmage_than_punt_with_20_yard.pdf',bbox_inches='tight')\n\nprint('this would be the new probability of punt being better than scrimmage (and so what the coach would do)')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4fe5438be244bfed6d41fd051a9333eb39b35906"},"cell_type":"code","source":"actual_rate=0\nnew_rate=0\nall_fourth_punt_scrimmage=np.sum(nb_fourth_yard_to_go_punt_scrimmage)\n\nfor i in range(20):\n    actual_rate+=ratio_punt_per_pass_run_kneel_dist_to_go[i]*nb_fourth_yard_to_go_punt_scrimmage[i]\n    new_rate+=proba_better_scrimmage_than_punt_with_20_yard[i]*nb_fourth_yard_to_go_punt_scrimmage[i]\nactual_rate=actual_rate/all_fourth_punt_scrimmage\nnew_rate=new_rate/all_fourth_punt_scrimmage\nprint(actual_rate,new_rate)\n\nprint('By doing so, this rule should reduce the proportion of punt in fourth down from 83% to 64% ')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}