{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport re\nimport glob\nimport datetime","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"36fe0813a3caa783497a462778ae20c1440d9af4"},"cell_type":"markdown","source":"# Analyzing Occurence of Concussions"},{"metadata":{"_uuid":"7067baf0d6257d3fe9e7c318082890dce5f04b64"},"cell_type":"markdown","source":"Before being able to propose modifcations to the rules, I needed to first analyze the occurence of concussions on punt returns.\n\n* How many punt plays in the last 2 seasons resulted in concussions?\n* What activity lead to the concussions?\n* Where during the play did the concussions occur?  Before or After the kick? Before or after the punt is caught?\n* Any other characteristics of the play affect the liklihood of a concussion."},{"metadata":{"_uuid":"bb8ef672693d50f6b0a02720284d7031613ca010"},"cell_type":"markdown","source":"### Load Injury Data"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"df_injury = pd.read_csv('../input/video_review.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2fd570a830603e7869c238b0c986d2d3c750bdb6"},"cell_type":"code","source":"print('Total Concussions:', len(df_injury))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cad09b1983d9afb13cd1014ba12883cc9e256fd6"},"cell_type":"code","source":"df_injury['Player_Activity_Derived'].value_counts().plot(kind=\"bar\", title = 'Player Activity That Causes Concussions')\ndf_injury['Player_Activity_Derived'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8401588a866f30f115438d7be6cc85886f78082b"},"cell_type":"markdown","source":"### Load Play Specific Data "},{"metadata":{"trusted":true,"_uuid":"90080d2003a7ba2e036ebd2d49b078250b3bda6f"},"cell_type":"code","source":"df_play = pd.read_csv('../input/play_information.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cfaa644d8e0a0b999119606d305e8bd2f40e48f2"},"cell_type":"code","source":"# Identify Punt Plays that resulted in fair catch\ndf_play['FairCatch'] = 0\ndf_play.loc[df_play['PlayDescription'].str.contains('fair catch', case = False),'FairCatch'] = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6954fcddd5074d20065b8e5e938fa0a0d0ae63d2"},"cell_type":"code","source":"# Identify Punt Plays that had a penalty\ndf_play['is_penalty'] = 0\ndf_play.loc[df_play['PlayDescription'].str.contains('penalty', case = False),'is_penalty'] = 1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"73b20e4fb0cf3f2fb68ced14cb8de7d39dbbe34f"},"cell_type":"markdown","source":"#### Identify the Punt/Return Type\nUse the Play Description field to determine the type of play.  Options are:\n* Return - The punt returner caught and returned the ball.\n* Fair Catch - Returned called a fair catch. No Return.\n* Downed - The ball was downed by the kicking team.  No Return.\n* Touchback - The ball goes into the opposing team's endzone.  No Return.\n* Out of Bounds - The ball is punted out of bounds.  No Return.\n* Block - The punt is blocked behind the LOS by the return team\n* No Punt - Play that does not result in an actual punt.  Either a fake or dropped snap. \n* Penalty - Penalty before the snap or on the return team that nullfies the play.  No official play."},{"metadata":{"trusted":true,"_uuid":"2f74c554cb4e99ae7b7863d79249f2fc5803d5d4"},"cell_type":"code","source":"df_play['punt_play_type'] = 'return'\ndf_play.loc[df_play['PlayDescription'].str.contains('fair catch', case = False),'punt_play_type'] = 'fair_catch'\ndf_play.loc[df_play['PlayDescription'].str.contains('downed', case = False),'punt_play_type'] = 'downed'\ndf_play.loc[df_play['PlayDescription'].str.contains('touchback', case = False),'punt_play_type'] = 'touchback'\ndf_play.loc[df_play['PlayDescription'].str.contains('out of bounds\\.', case = False),'punt_play_type'] = 'out_of_bounds'\ndf_play.loc[~df_play['PlayDescription'].str.contains('punts', case = False),'punt_play_type'] = 'no punt'\ndf_play.loc[df_play['PlayDescription'].str.contains('blocked', case = False),'punt_play_type'] = 'block'\ndf_play.loc[df_play['PlayDescription'].str.contains('\\(punt formation\\) penalty', case = False),'punt_play_type'] = 'pre-snap penalty'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"03271b3a800326ed1f4e2cd7354c9a7ce69ca2ea"},"cell_type":"code","source":"df_concussion_plays = df_injury.merge(df_play, how = 'inner', on = ['GameKey','PlayID'])\ndf_concussion_plays['punt_play_type'].value_counts().plot(kind=\"bar\", title = 'Punt Play Type for Concussions')\ndf_concussion_plays['punt_play_type'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d2c4791e628986293f449c3dbb0f07cfcd77873b"},"cell_type":"markdown","source":"#### Takeaways\n1. The majority of concussions are resulting on plays that have a return.  Where do injuries occur? Particular Position?\n2. There is still a chance of concussions on plays that do not have a return.\n3. After further investigation, the play with no punt is actually a fake punt.  This play is truly a running play so should not be included in the analysis\n\n**What is it about return plays that lead to conussions?**"},{"metadata":{"_uuid":"3ed9584fdade175e0612f94c0e3d03199ab8bf59"},"cell_type":"markdown","source":"### Does Position lead to more penalties? - Add Role Data"},{"metadata":{"trusted":true,"_uuid":"8c5aa64e4b88295463504e53077ecea13ada9612"},"cell_type":"code","source":"df_player_role = pd.read_csv('../input/play_player_role_data.csv')\ndf_concussion_plays = df_concussion_plays.merge(df_player_role, on = ['GameKey','PlayID','GSISID'], how = 'left')\n\n#Remove the no_snap play\ndf_concussion_plays = df_concussion_plays[df_concussion_plays['punt_play_type'] != 'no punt']\n\ndf_concussion_plays['Role'].value_counts().plot(kind=\"bar\", title = 'Position of Concussed Player')\ndf_concussion_plays['Role'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7eca3e5d7e4439a1315ed31973fc1cf9b9b095eb"},"cell_type":"markdown","source":"#### Takeaways\n* The punt returner is the most likely to be injured, which was somewhat expected as this is the ball carrier. \n* Majority of positions are impacted"},{"metadata":{"_uuid":"7a3e21dabe2d38cdcbe5dbca2f764afd66a2f3b3"},"cell_type":"markdown","source":"### What is happening on the plays with injuries? - Add Player Tracking Data\nTo first answer this question, I watched the video clips.  What I realized is that the majority of the concussions were occuring after the ball was caught.  A player was injured on the tackle or a downfield block during the return. \n\nOther injuries occurred during blocking at the line of LOS or before the punt was caught on downfield blocking.  \n\nWhile these three categories existed, I wanted to confirm this with the tracking data."},{"metadata":{"trusted":true,"_uuid":"8ea329f61c4c654765a6402d6e00c2d927a1f8cd"},"cell_type":"code","source":"df_ngs = pd.concat([pd.read_csv(f) for f in glob.glob('../input/NGS*.csv')],ignore_index=True)\n\n# Limit to just plays with injuries\ndf_ngs_injuries = df_ngs.merge(df_injury[['GameKey','PlayID']], how = 'inner', on = ['GameKey','PlayID'])\n\ndf_concussion_plays['Primary_Partner_GSISID'] = pd.to_numeric(df_concussion_plays['Primary_Partner_GSISID'].str.replace('Unclear',''))\ndf_injury_location = df_concussion_plays.merge(df_ngs_injuries, how = 'left', on = ['GameKey','PlayID','GSISID'])\ndf_injury_location = df_injury_location.merge(df_ngs_injuries, how = 'left', left_on = ['GameKey','PlayID','Time','Primary_Partner_GSISID'],right_on = ['GameKey','PlayID','Time','GSISID'],  suffixes = ['_injured','_partner'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"239b91384e1ee193eeca3deed76f5b5fd5d3b444"},"cell_type":"code","source":"df_injury_location['y_separation'] = (df_injury_location['y_partner'] - df_injury_location['y_injured']).abs()\ndf_injury_location['x_separation'] = (df_injury_location['x_partner'] - df_injury_location['x_injured']).abs()\ndf_injury_location['separation'] = np.sqrt(df_injury_location['y_separation']**2 + df_injury_location['x_separation']**2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"43795d3cc29dc0d6d2c685e7c2d1003654d562c9"},"cell_type":"code","source":"df_concussion = df_injury_location.sort_values('separation').drop_duplicates(['GameKey','PlayID'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0ebed6da94c37361a9ce2b317bad6606045c9274"},"cell_type":"code","source":"df_punt_received = df_ngs[(df_ngs['Event'].isin(['punt_received','kick_received','fair_catch','punt_downed']))][['PlayID','GameKey','Time']].drop_duplicates()\ndf_punt_received.columns = ['PlayID','GameKey','punt_caught_time']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8bde7b8c19437468ee4bc0ee499f94906420a81e"},"cell_type":"code","source":"df_punt_time = df_ngs[(df_ngs['Event'] == 'punt')][['PlayID','GameKey','Time']].drop_duplicates()\ndf_punt_time.columns = ['PlayID','GameKey','ball_kicked_time']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"078d2928e7adeedbb141f04de578c8f6c9aa79bd"},"cell_type":"code","source":"df_snap = df_ngs[(df_ngs['Event'] == 'ball_snap')][['PlayID','GameKey','Time']].drop_duplicates()\ndf_snap = df_snap.merge(df_player_role[df_player_role['Role'] == 'PLS'], how = 'inner', on = ['PlayID','GameKey'])\ndf_snap = df_snap[['PlayID','GameKey','Time','GSISID']]\ndf_snap.columns = ['PlayID','GameKey','snap_time','GSISID']\ndf_snap = df_snap.merge(df_ngs[df_ngs['Event'] == 'ball_snap'], how = 'inner', on = ['PlayID','GameKey','GSISID'])\ndf_snap = df_snap[['PlayID','GameKey','Time','x']]\ndf_snap.columns = ['PlayID','GameKey','snap_time','x_LOS']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3e11792777924110b717b90396dbd38c9fcbc62f"},"cell_type":"code","source":"df_concussion = df_concussion.merge(df_punt_received, how = 'left', on = ['GameKey','PlayID'], suffixes = ['_injury','_punt_received'])\ndf_concussion = df_concussion.merge(df_punt_time, how = 'left', on = ['GameKey','PlayID'], suffixes = ['_injury','_ball_kicked'])\ndf_concussion = df_concussion.merge(df_snap, how = 'left', on = ['GameKey','PlayID'], suffixes = ['_injury','_ball_snapped'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cdf97aea08ec83a269a2b74d98c296b3892a8f6d"},"cell_type":"code","source":"df_concussion['Time_to_injury'] = pd.to_datetime(df_concussion['Time']) - pd.to_datetime(df_concussion['snap_time'])\ndf_concussion['Time_to_punt'] = pd.to_datetime(df_concussion['ball_kicked_time']) - pd.to_datetime(df_concussion['snap_time'])\ndf_concussion['Time_to_punt_caught'] = pd.to_datetime(df_concussion['punt_caught_time']) - pd.to_datetime(df_concussion['snap_time'])\ndf_concussion['delta_from_LOS'] = (df_concussion['x_injured'] - df_concussion['x_LOS']).abs()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e491f86a8964f2ce947cf542e5a328afb08e86fd"},"cell_type":"code","source":"df_concussion = df_concussion[~df_concussion['Primary_Partner_GSISID'].isnull()]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f6b0ae761292ddf639363f96d380caed8cb88b0d"},"cell_type":"code","source":"df_concussion['Injury_Event_Type'] = 'NA'\ndf_concussion.loc[df_concussion['Time'] >= df_concussion['punt_caught_time'],'Injury_Event_Type'] = 'Blocking on return'\ndf_concussion.loc[df_concussion['Time'] < df_concussion['punt_caught_time'],'Injury_Event_Type'] = 'Blocking before return'\ndf_concussion.loc[df_concussion['Player_Activity_Derived'].isin(['Tackling','Tackled']),'Injury_Event_Type'] = 'Tackle'\ndf_concussion['Injury_Event_Type'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"eace923c054541d3514cc282ef6881690fc80374"},"cell_type":"code","source":"colors = {'Tackle':'magenta', 'Blocking on return':'blue', 'Blocking before return':'cyan','NA':'red'}\nlabels = {'Tackle':'Tackle', 'Blocking on return':'Blocking on return', 'Blocking before return':'Blocking before return','NA':'NA'}\n\n# create data \ny = df_concussion['delta_from_LOS']\nx = df_concussion['Time_to_injury'].dt.total_seconds()\n \n# plot\nfor g in df_concussion['Injury_Event_Type'].unique():\n    ix = df_concussion['Injury_Event_Type'] == g\n    plt.scatter(x[ix], y[ix], c = colors[g], label = g)\n#plt.scatter(x,y, c = df_concussion['Injury_Event_Type'].apply(lambda x: colors[x]))\nplt.gcf().autofmt_xdate()\nplt.axvline(x=df_concussion['Time_to_punt_caught'].mean().total_seconds(), color='k', linestyle='--', label = 'avg. time to punt')\nplt.axvline(x=df_concussion['Time_to_punt'].mean().total_seconds(), color='r', linestyle='--', label = 'avg. time to receive punt')\nplt.legend(bbox_to_anchor=(1.1, 1.05))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a544b5ec60d17924f2d1742fea0e02702561bd00"},"cell_type":"markdown","source":"## What if the punt was eliminated?"},{"metadata":{"trusted":true,"_uuid":"0f7224df606778dde0df97afd106036abf2e2b6c"},"cell_type":"code","source":"all_punt_atts = []\nfor x in df_play.index:\n\n    turnover = 0\n    strings = ['return','fair_catch','downed','out_of_bounds','touchback']\n\n    if any(s in df_play['punt_play_type'][x] for s in strings):\n        \n        # Code for touchback\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* touchback.',play).groups()\n\n            #print(punt_data)\n\n            return_yard = 20\n\n            return_length = 0\n            punt_dist = np.nan\n            \n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n           # print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n\n        except:\n            pass\n        \n        # Code for return\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*|-|\\d), .* to (\\w*) (\\d*) for (\\d*|-\\d*) yard.*',play).groups()\n\n            #print(punt_data)\n\n            if punt_data[3] == team:\n                return_yard = int(punt_data[4]) + 50\n            else:\n                return_yard = int(punt_data[4])\n\n            return_length = int(punt_data[5])\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n           # print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n\n        except:\n            pass  \n        \n        # Code for out of bounds\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* out of bounds.',play).groups()\n\n           # print(punt_data)\n\n            if punt_data[1] == team:\n                return_yard = int(punt_data[2]) + 50\n            else:\n                return_yard = int(punt_data[2])\n\n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n           # print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n\n        except:\n            pass \n        \n        # Code for fair catch\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* fair catch .*',play).groups()\n\n           # print(punt_data)\n\n            if punt_data[1] == team:\n                return_yard = int(punt_data[2]) + 50\n            else:\n                return_yard = int(punt_data[2])\n\n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n           # print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n            \n        except:\n            pass\n\n        # Code for muff\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            #print(play)\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* muffs catch, recovered by (\\w*)-.* at .* to (\\w*) (\\d*) for .*',play).groups()\n\n            #print(punt_data)\n\n            if punt_data[0] == team:\n                turnover = True\n                return_yard = np.nan\n                return_length = np.nan\n            else:\n                turnover = False\n                return_length = np.nan\n                if punt_data[1] == team:\n                    return_yard = np.nan\n                    return_length = np.nan\n\n            #return_length = 0\n            #punt_dist = punt_data[0]\n\n            #print(punt_dist, return_yard, return_length)\n            \n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": np.nan,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 1,\n                    \"turnover\": turnover\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n        except:\n            pass  \n        \n        # Code for return no gain\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* to (\\w*) (\\d*) for no gain .*',play).groups()\n\n            #print(punt_data)\n\n            if punt_data[3] == team:\n                return_yard = int(punt_data[4]) + 50\n            else:\n                return_yard = int(punt_data[4])\n\n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n\n        except:\n            pass  \n        \n        # Downed Punt\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* downed .*',play).groups()\n\n           # print(punt_data)\n\n            if punt_data[1] == team:\n                return_yard = 50\n            else:\n                return_yard = 0\n\n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n        except:\n            pass  \n        \n        # return to 50\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* to 50 for (\\d*) yard.*',play).groups()\n\n           # print(punt_data)\n\n            return_yard = 50\n            \n            return_length = punt_data[3]\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n\n        except:\n            pass\n        \n        # Code for return\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* at (\\w*) (\\d*) for (\\d*|-\\d*) yard.*',play).groups()\n\n            #print(punt_data)\n\n            if punt_data[3] == team:\n                return_yard = int(punt_data[4]) + 50\n            else:\n                return_yard = int(punt_data[4])\n\n            return_length = int(punt_data[5])\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n           # print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n            \n            continue\n\n        except:\n            pass\n        \n        # Code for return\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* at (\\w*) (\\d*) for no gain.*',play).groups()\n\n            #print(punt_data)\n\n            if punt_data[3] == team:\n                return_yard = int(punt_data[4]) + 50\n            else:\n                return_yard = int(punt_data[4])\n\n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n           # print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n            \n            continue\n        except:\n            pass \n        \n        # ob 50\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* at 50 for (\\d*) yard.*',play).groups()\n\n           # print(punt_data)\n\n            return_yard = 50\n            \n            return_length = punt_data[3]\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n            \n        except:\n            pass            \n        # touchdown\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* for (\\d*) yard.*',play).groups()\n\n           # print(punt_data)\n\n            return_yard = 100\n            \n            return_length = punt_data[3]\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n\n            continue\n            \n        except:\n            pass \n        \n        # ob 50\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to 50, .* for (\\d*) yard.*',play).groups()\n\n           # print(punt_data)\n\n            return_yard = 50 + int(punt_data[1])\n            \n            return_length = punt_data[1]\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n            \n            continue\n\n        except:\n            pass \n        \n        # ob 50\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to 50, .* for no gain .*',play).groups()\n\n           # print(punt_data)\n\n            return_yard = 50 \n            \n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts) \n            \n            continue\n        except:\n            pass \n        \n        # ob 50\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to 50, .* fair catch.*',play).groups()\n\n           # print(punt_data)\n\n            return_yard = 50 \n            \n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)  \n            \n            continue\n            \n        except:\n            pass \n        \n        # ob 50\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*), .* muffs .* recovered by (\\w*)-.* at (\\w*) (\\d*).*',play).groups()\n\n            if punt_data[3] == team:\n                turnover = True\n                return_yard = np.nan\n                return_length = np.nan\n            else:\n                turnover = False\n                return_length = 0\n                return_yard = punt_data[5]\n            \n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 1,\n                    \"turnover\": turnover\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n            \n            continue \n            \n        except:\n            pass \n        \n        # ob 50\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to (\\w*) (\\d*) .* muffs .* recovers at (\\w*) (\\d*).*',play).groups()\n           \n            turnover = False\n            return_yard = punt_data[4]\n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 1,\n                    \"turnover\": turnover\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n        except:\n            pass\n\n        try:\n            play = df_play['PlayDescription'][x].lower()\n            team = df_play['Poss_Team'][x].lower()\n            punt_data = re.search('.* punts (\\d*) yards to 50, .*',play).groups()\n\n           # print(punt_data)\n\n            return_yard = 50 \n            \n            return_length = 0\n            punt_dist = punt_data[0]\n\n            punt_atts = {\n                    \"index\":x,\n                    \"punt_distance\": punt_dist,\n                    \"return_yard\": return_yard,\n                    \"return_length\": return_length,\n                    \"muff\": 0\n                }\n            \n            #print(punt_atts)\n            \n            all_punt_atts.append(punt_atts)\n            \n            continue\n\n        except:\n            \n            pass","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"97e2bd52de4fedee54262af3d0ccb7cb85068fe6"},"cell_type":"code","source":"df_punt_atts = pd.DataFrame(all_punt_atts)\ndf_punt_atts['return_length'] = df_punt_atts['return_length'].fillna(0).astype(int)\nprint('Average Return Length:', df_punt_atts['return_length'].mean())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"17a85f0876194aea9d6b34441a58385d437c1bb9"},"cell_type":"code","source":"df_punt_atts['return_length'] = df_punt_atts['return_length'].fillna(0).astype(int)\nprint('Average Return on returns only:', df_punt_atts['return_length'].mean())","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}