{"cells":[{"metadata":{"_uuid":"2e4fc0823a276147732d54b6592bc543fcb05b54"},"cell_type":"markdown","source":"# Overview\nHere we use some of the code from the starter kernel from [Chris Crawford](https://www.kaggle.com/crawford/nfl-punt-analytics-starter-kernel) and the great clean-up and feather code from [Alessandro Kosciansky](https://www.kaggle.com/akosciansky/how-to-import-large-csv-files-and-save-efficiently) to start annd process the data"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport os\nimport pandas as pd\nimport numpy as np\nimport glob\nfrom plotly import offline\nimport feather\nimport plotly.graph_objs as go\nimport matplotlib.pyplot as plt\nfrom matplotlib.patches import Rectangle\nfrom matplotlib.collections import PatchCollection\nfootball_field = lambda : Rectangle(xy=(10, 0), \n                                    width=100, \n                                    height=53.3, \n                                    color='g',\n                                   alpha=0.10)\nplt.style.use('ggplot')\npd.set_option('max.columns', None)\noffline.init_notebook_mode()\nfeather_dir = '../input/convert-to-feather-for-use-in-other-kernels/'\nnfl_dir = '../input/NFL-Punt-Analytics-Competition/'","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6ea20b6275cac99e92805a3d065668745557fb5a"},"cell_type":"markdown","source":"# Load in the games\nWe use the preprocessed file based on this [kernel](https://www.kaggle.com/akosciansky/how-to-import-large-csv-files-and-save-efficiently) which loads, cleans, and uses appropriate types for all of the CSV data to make it a lot easier to load the entire table into memory."},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# Load in a sample \nall_games_df = pd.read_feather(\n    os.path.join(feather_dir, 'ngs.feather')\n)\nall_games_df.sample(5)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"79b1613191a6082109f17dbbed0bbaaceb45d091"},"cell_type":"markdown","source":"## Show some example plays\nHere we show the paths the movement of every player for a number of randomly selected plays"},{"metadata":{"trusted":true,"_uuid":"9b2a75dd619927abd937113ee7effbead8a28bf5","_kg_hide-input":false,"_kg_hide-output":false},"cell_type":"code","source":"fig, m_axs = plt.subplots(8, 8, figsize=(20, 20))\nfor (play_id, play_rows), c_ax in zip(all_games_df.groupby('PlayID'), \n                      m_axs.flatten()):\n    c_ax.add_patch(football_field())\n    for player_id, player_rows in play_rows.groupby('GSISID'):\n        player_rows = player_rows.sort_values('Time')\n        c_ax.plot(player_rows['x'], player_rows['y'], \n                  label=player_id)\n    c_ax.set_title(play_id)\n    c_ax.set_aspect(1)\n    c_ax.set_xlim(0, 120)\n    c_ax.set_ylim(-10, 63)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"77356e8766f461738594155a0096d5897dddc1a2"},"cell_type":"markdown","source":"## Match concussion plays\nHere we have information on the concussion plays that occured. We can safely ass"},{"metadata":{"_kg_hide-output":false,"trusted":true,"_uuid":"8c389d81f41501fb4ced60750b1743449a0987d4"},"cell_type":"code","source":"match_cols = ['Season_Year', 'GameKey', 'PlayID']\nvideo_review_df = pd.read_csv(os.path.join(nfl_dir, \n                                           'video_review.csv'))\nvideo_review_df.dropna(subset=['GSISID'], inplace=True)\nvideo_review_df['GSISID'] = video_review_df['GSISID'].map(int)\n\nfor c_col in match_cols:\n    # match types to make merges later quicker\n    video_review_df[c_col] = video_review_df[c_col].astype(all_games_df[c_col].dtype)\nvideo_review_df.head(5)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"1edcfb174b05de9859a8eb3f839642be2b35c51c"},"cell_type":"markdown","source":"## Create a dictionary of concussion plays\nHere we make a little dictionary of all of the player/play/games to mark each individual player as concussion or not\n\n#### TODO expand to both players involved"},{"metadata":{"trusted":true,"_uuid":"5a54c0b80bd5c3d7d3ece4d28cb3559c7f4c5eb5"},"cell_type":"code","source":"def player_scene_key(in_df):\n    return in_df.apply(lambda x: (x['Season_Year'],\n                                x['GameKey'],\n                                x['PlayID'],\n                                x['GSISID']\n                               ), 1)\nconc_keys = player_scene_key(video_review_df).values\nconc_dict = dict(\n    zip(conc_keys, \n        video_review_df['Player_Activity_Derived'].values)\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cb6f450d0de8c11cafb24d4c3d1ceae3271ff996"},"cell_type":"markdown","source":"# Show Examples for each type\nHere we grab example plays for each type of concussion to see if we immediately notice any differences"},{"metadata":{"trusted":true,"_uuid":"039a8bbf95f791b3f306a0a94a0279c405fc304d"},"cell_type":"code","source":"sample_plays = 5\nfig, m_axs = plt.subplots(4, sample_plays, figsize=(20, 20))\n\nfor (conc_type, conc_rows), n_axs in zip(\n    video_review_df.groupby('Player_Activity_Derived'),\n    m_axs\n):\n    sel_plays = conc_rows.sample(sample_plays)\n    \n    for (play_id, c_play_row), c_ax in zip(\n        sel_plays.groupby('PlayID'), \n        n_axs):\n        play_rows = pd.merge(c_play_row[match_cols], \n                             all_games_df)\n        c_ax.add_patch(football_field())\n        for player_id, player_rows in play_rows.groupby('GSISID'):\n            player_rows = player_rows.sort_values('Time')\n            if player_id in c_play_row['GSISID'].values:\n                c_ax.plot(player_rows['x'], player_rows['y'], \n                          'r.-', label='Primary')\n            elif player_id in c_play_row['Primary_Partner_GSISID'].values:\n                c_ax.plot(player_rows['x'], player_rows['y'], \n                          'b.-', label='Partner')\n            else:\n                c_ax.plot(player_rows['x'], player_rows['y'], \n                          alpha=0.5, label='_nolegend_')\n                \n        c_ax.set_title(play_id)\n        c_ax.set_aspect(1)\n        c_ax.set_xlim(0, 120)\n        c_ax.set_ylim(-5, 68)\n        c_ax.legend()\n    n_axs[0].set_title('{0}-#{1} plays'.format(conc_type, conc_rows.shape[0]))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"01154c904316cacebe576d0e804e86305ef607c0"},"cell_type":"markdown","source":"# Study Play in Detail\nWe can use more detailed plots to try and see what exactly was happening at each timestep"},{"metadata":{"trusted":true,"_uuid":"c33f486604dc8fb6adfe16f5ba39c2e3ffefd8fa"},"cell_type":"code","source":"fig, c_ax = plt.subplots(1, 1, figsize=(20, 10))\nq_rows = play_rows.copy()\ndis_scalar = 1/10.0\nq_rows['u'] = -1*q_rows['dis']/dis_scalar*np.sin(q_rows['o']*2*np.pi/360)\nq_rows['v'] = q_rows['dis']/dis_scalar*np.cos(q_rows['o']*2*np.pi/360)\nc_ax.add_patch(football_field())\nfor player_id, player_rows in q_rows.groupby('GSISID'):\n    player_rows = player_rows.sort_values('Time')\n    if player_id in c_play_row['GSISID'].values:\n        c_ax.quiver(player_rows['x'], player_rows['y'],\n                    player_rows['u'], player_rows['v'],\n                    units='x', label='Primary')\n    else:\n        c_ax.plot(player_rows['x'], player_rows['y'], \n                  alpha=0.5, label='_nolegend_')\nc_ax.set_title(play_id)\nc_ax.set_aspect(1)\nc_ax.set_xlim(0, 120)\nc_ax.set_ylim(-10, 63)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"520fa99c5685fe2eac1434177f5a318b725a3b6f"},"cell_type":"markdown","source":"# Show an interactive movie"},{"metadata":{"trusted":true,"_uuid":"09e6e711af82479aba6f6c370a2602465a34fc2e"},"cell_type":"code","source":"from matplotlib import animation, rc\nrc('animation', html='jshtml', embed_limit=100)\nfig, c_ax = plt.subplots(1, 1, figsize=(20, 10))\nc_ax.add_patch(football_field())\nc_ax.set_aspect(1)\nc_ax.set_xlim(0, 120)\nc_ax.set_ylim(-10, 63)\nq_rows['clock'] = (q_rows['Time']-q_rows['Time'].min()).dt.total_seconds()\n\nstep_count = 30\nstep_length = 10*1000/(step_count)\ntime_steps = np.linspace(q_rows['clock'].min(),\n                       q_rows['clock'].max(),\n                       step_count+1)\ndef update_frame(i):\n    n_rows = q_rows[q_rows['clock']<=time_steps[i+1]]\n    n_rows = n_rows[n_rows['clock']>time_steps[i]]\n        \n    for player_id, player_rows in n_rows.groupby('GSISID'):\n        player_rows = player_rows.sort_values('Time')\n        if player_id in c_play_row['GSISID'].values:\n            c_ax.quiver(player_rows['x'], player_rows['y'],\n                        player_rows['u'], player_rows['v'],\n                        units='x', label='Primary')\n        else:\n            c_ax.plot(player_rows['x'], player_rows['y'], \n                      alpha=0.5, label='_nolegend_')\nani = animation.FuncAnimation(fig, \n                              update_frame, \n                              range(step_count), \n                              interval=step_length)\nani","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e6a50f182dbec83a6634a990bc0efbc22826c4c0"},"cell_type":"markdown","source":"## Next steps\nWe have very few examples of concussions from a single week (that is probably a good thing for football, but makes our analysis harder). So we will need to process more weeks to get a better idea what separates normal plays from concussion plays"},{"metadata":{"trusted":true,"_uuid":"ee3c65e562f1e7054b43e54131d01dffe097ded2"},"cell_type":"code","source":"","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}