{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-11-02T11:16:53.302437Z","iopub.execute_input":"2021-11-02T11:16:53.303014Z","iopub.status.idle":"2021-11-02T11:16:53.315913Z","shell.execute_reply.started":"2021-11-02T11:16:53.302960Z","shell.execute_reply":"2021-11-02T11:16:53.314949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In this notebook I am looking at one flying ball. I selected a play that is a deep kickback and I look at the speed and acceleration of the flying ball. \nNormally, after the kick, the acceleration of the ball should be constant and equal to the gravitational acceleration, if the acceleration from the tracking data is given by an accelerometer attached to the ball. The speed in the plane of the field should be constant. Weirdly, this is not what we see in the data. ","metadata":{}},{"cell_type":"code","source":"# Read in data files\nBASE_DIR = '../input/nfl-big-data-bowl-2022'\nplayers = pd.read_csv(f'{BASE_DIR}/players.csv')\nPFFScouting = pd.read_csv(f'{BASE_DIR}/PFFScoutingData.csv')\ntracking2019 = pd.read_csv(f'{BASE_DIR}/tracking2019.csv')\ntracking2020 = pd.read_csv(f'{BASE_DIR}/tracking2020.csv')\ntracking2018 = pd.read_csv(f'{BASE_DIR}/tracking2018.csv')\ngames = pd.read_csv(f'{BASE_DIR}/games.csv')\nplays = pd.read_csv(f'{BASE_DIR}/plays.csv')","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:16:53.317716Z","iopub.execute_input":"2021-11-02T11:16:53.318537Z","iopub.status.idle":"2021-11-02T11:18:45.423784Z","shell.execute_reply.started":"2021-11-02T11:16:53.318502Z","shell.execute_reply":"2021-11-02T11:18:45.422992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pylab as plt","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:45.425543Z","iopub.execute_input":"2021-11-02T11:18:45.426119Z","iopub.status.idle":"2021-11-02T11:18:45.431253Z","shell.execute_reply.started":"2021-11-02T11:18:45.426068Z","shell.execute_reply":"2021-11-02T11:18:45.430265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Here we already find a play with a deep kick from J. Elliott. We are just going to look at this play in the tracking data. ","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"plays.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:45.432935Z","iopub.execute_input":"2021-11-02T11:18:45.433482Z","iopub.status.idle":"2021-11-02T11:18:45.468327Z","shell.execute_reply.started":"2021-11-02T11:18:45.433432Z","shell.execute_reply":"2021-11-02T11:18:45.467281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The hang time is 3.85s","metadata":{}},{"cell_type":"code","source":"PFFScouting.query('gameId == 2018090600 & playId == 37' )['hangTime']","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:45.471706Z","iopub.execute_input":"2021-11-02T11:18:45.472166Z","iopub.status.idle":"2021-11-02T11:18:45.488471Z","shell.execute_reply.started":"2021-11-02T11:18:45.472134Z","shell.execute_reply":"2021-11-02T11:18:45.487652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"tr_ball = tracking2018.query('gameId == 2018090600 & playId == 37 & team == \"football\"').reset_index(drop = True)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:45.489878Z","iopub.execute_input":"2021-11-02T11:18:45.490645Z","iopub.status.idle":"2021-11-02T11:18:46.003348Z","shell.execute_reply.started":"2021-11-02T11:18:45.490610Z","shell.execute_reply":"2021-11-02T11:18:46.002425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set(tr_ball['event'].values)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.004525Z","iopub.execute_input":"2021-11-02T11:18:46.004822Z","iopub.status.idle":"2021-11-02T11:18:46.011421Z","shell.execute_reply.started":"2021-11-02T11:18:46.004788Z","shell.execute_reply":"2021-11-02T11:18:46.010759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tr_ball.query('event == \"kickoff\" or event == \"touchback\"')","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.012762Z","iopub.execute_input":"2021-11-02T11:18:46.013328Z","iopub.status.idle":"2021-11-02T11:18:46.048642Z","shell.execute_reply.started":"2021-11-02T11:18:46.013288Z","shell.execute_reply":"2021-11-02T11:18:46.047596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Here I make a column called gtime (good time) where the time is expressed in seconds from teh kickoff","metadata":{}},{"cell_type":"code","source":"\ntr_ball['gtime'] = tr_ball['time'].str.split(\":\").str[-1].astype('float32')\nT0 = tr_ball.query('event == \"kickoff\"')['gtime'].reset_index(drop = True)[0] \ntr_ball['gtime'] = tr_ball['gtime'] - T0","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.050472Z","iopub.execute_input":"2021-11-02T11:18:46.051076Z","iopub.status.idle":"2021-11-02T11:18:46.065009Z","shell.execute_reply.started":"2021-11-02T11:18:46.051025Z","shell.execute_reply":"2021-11-02T11:18:46.064006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# here I add a column with the calculated speed in the x direction\ntr_ball['sx'] = tr_ball['s'] \nfor i in range(1,len(tr_ball)):\n    tr_ball.at[i,'sx'] = (tr_ball.at[i,'x'] - tr_ball.at[i-1,'x'])/(tr_ball.at[i,'gtime'] - tr_ball.at[i-1,'gtime'])","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.066079Z","iopub.execute_input":"2021-11-02T11:18:46.066694Z","iopub.status.idle":"2021-11-02T11:18:46.082170Z","shell.execute_reply.started":"2021-11-02T11:18:46.066658Z","shell.execute_reply":"2021-11-02T11:18:46.081110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# here I add a column with the calculated speed in the y direction\ntr_ball['sy'] = tr_ball['s'] \nfor i in range(1,len(tr_ball)):\n    tr_ball.at[i,'sy'] = (tr_ball.at[i,'y'] - tr_ball.at[i-1,'y'])/(tr_ball.at[i,'gtime'] - tr_ball.at[i-1,'gtime'])","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.083769Z","iopub.execute_input":"2021-11-02T11:18:46.084914Z","iopub.status.idle":"2021-11-02T11:18:46.097744Z","shell.execute_reply.started":"2021-11-02T11:18:46.084866Z","shell.execute_reply":"2021-11-02T11:18:46.096640Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ready for plotting, let's just turn all these into numpy arrays\n#acceleration\np_a = tr_ball[['gtime', 'a']].to_numpy()\n#speed\np_s = tr_ball[['gtime', 's']].to_numpy()\n#calculated speed along x\np_sx = tr_ball[['gtime', 'sx']].to_numpy()\n#calculated speed along y\np_sy = tr_ball[['gtime', 'sy']].to_numpy()","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.099322Z","iopub.execute_input":"2021-11-02T11:18:46.100498Z","iopub.status.idle":"2021-11-02T11:18:46.112938Z","shell.execute_reply.started":"2021-11-02T11:18:46.100442Z","shell.execute_reply":"2021-11-02T11:18:46.111879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we plot s and s_x. s is the speed as read from the tracking data, s_x is the speed along x as calculated from the tracking data. \ns_x should really be a constant until the moment the ball touches the ground or another player. It is not. Why is s_x changing while the ball flies? According to the laws of kinematis as long as the ball is in the air, the acceleration in the x-y plane should be zero, therefore the speeds along x and y should be constant.\nThe speed s from the trackind data seems to follow quite closely the speed calculated from the x displacement vs time. This indicates that the speed is not some three dimensional speed, but a speed in the x-y plane, as the one for the players.\n","metadata":{}},{"cell_type":"code","source":"# let's plot s and s_x\n\nplt.plot(p_s[:,0], p_s[:,1],'rs',  markersize = 4, label='speed')\nplt.plot(p_sx[:,0], p_sx[:,1],'gs', markersize = 4, label='speed_x')\nplt.legend(loc='upper right')","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.114217Z","iopub.execute_input":"2021-11-02T11:18:46.115047Z","iopub.status.idle":"2021-11-02T11:18:46.403308Z","shell.execute_reply.started":"2021-11-02T11:18:46.115001Z","shell.execute_reply":"2021-11-02T11:18:46.402636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's plot the acceleration vs time. Keep in mind that it should be constant while the ball flies, at g = 10.72 yards/(seconds squared), the gravitational acceleration, or acceleration of falling bodies.\nInstead of a constant acceleration, the values are all over the place, only around t=1s it seems to keep a constant value which is quite above 10.7 yards/(seconds squared). \nWhat happened at around 2 seconds? Why did the acceleration suddenly increase? The souting data indicates a hang time of 3.85s.","metadata":{}},{"cell_type":"code","source":"plt.plot(p_a[:,0], p_a[:,1],'bo', label='acceleration', markersize = 4 )\nplt.legend(loc='upper right')","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.405798Z","iopub.execute_input":"2021-11-02T11:18:46.406218Z","iopub.status.idle":"2021-11-02T11:18:46.661811Z","shell.execute_reply.started":"2021-11-02T11:18:46.406166Z","shell.execute_reply":"2021-11-02T11:18:46.661151Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Here I plotted all three together, speed, calculated speed along x and acceleration. ","metadata":{}},{"cell_type":"code","source":"plt.plot(p_s[:,0], p_s[:,1],'rs',  markersize = 4, label='speed')\nplt.plot(p_sx[:,0], p_sx[:,1],'gs', markersize = 4, label='speed_x')\nplt.plot(p_a[:,0], p_a[:,1],'bo', label='acceleration', markersize = 4 )\nplt.legend(loc='upper right')\n","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:18:46.663162Z","iopub.execute_input":"2021-11-02T11:18:46.663573Z","iopub.status.idle":"2021-11-02T11:18:46.947966Z","shell.execute_reply.started":"2021-11-02T11:18:46.663540Z","shell.execute_reply":"2021-11-02T11:18:46.947117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Questions: \nWhy does the acceleration change while the ball is in the air? It should stay constant.\nWhy does the horizontal speed change while the ball is in the air? It should stay constant.\nAccording to the scouting data the ball was in the air up to 3.85s after the kick. \n","metadata":{}},{"cell_type":"markdown","source":"Let's do the same analysis for the 56 yards punt that follows","metadata":{}},{"cell_type":"code","source":"tr_ball_2 = tracking2018.query('gameId == 2018090600 & playId == 366 & team == \"football\"').reset_index(drop = True)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:37:06.922753Z","iopub.execute_input":"2021-11-02T11:37:06.923304Z","iopub.status.idle":"2021-11-02T11:37:07.528661Z","shell.execute_reply.started":"2021-11-02T11:37:06.923265Z","shell.execute_reply":"2021-11-02T11:37:07.527554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tr_ball.query('event == \"punt\"')['gtime'].reset_index(drop = True)","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:40:46.080537Z","iopub.execute_input":"2021-11-02T11:40:46.080884Z","iopub.status.idle":"2021-11-02T11:40:46.474732Z","shell.execute_reply.started":"2021-11-02T11:40:46.080808Z","shell.execute_reply":"2021-11-02T11:40:46.473631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tr_ball = tr_ball_2\ntr_ball['gtime'] = tr_ball['time'].str.split(\":\").str[-1].astype('float32')\nT0 = tr_ball.query('event == \"punt\"')['gtime'].reset_index(drop = True)[0] \ntr_ball['gtime'] = tr_ball['gtime'] - T0","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:40:55.527924Z","iopub.execute_input":"2021-11-02T11:40:55.528239Z","iopub.status.idle":"2021-11-02T11:40:55.541610Z","shell.execute_reply.started":"2021-11-02T11:40:55.528204Z","shell.execute_reply":"2021-11-02T11:40:55.540624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# here I add a column with the calculated speed in the x direction\ntr_ball['sx'] = tr_ball['s'] \nfor i in range(1,len(tr_ball)):\n    tr_ball.at[i,'sx'] = (tr_ball.at[i,'x'] - tr_ball.at[i-1,'x'])/(tr_ball.at[i,'gtime'] - tr_ball.at[i-1,'gtime'])\n    \n","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:40:57.645481Z","iopub.execute_input":"2021-11-02T11:40:57.645787Z","iopub.status.idle":"2021-11-02T11:40:57.658145Z","shell.execute_reply.started":"2021-11-02T11:40:57.645754Z","shell.execute_reply":"2021-11-02T11:40:57.657202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ready for plotting, let's just turn all these into numpy arrays\n#acceleration\np_a = tr_ball[['gtime', 'a']].to_numpy()\n#speed\np_s = tr_ball[['gtime', 's']].to_numpy()\n#calculated speed along x\np_sx = tr_ball[['gtime', 'sx']].to_numpy()\n","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:41:16.294741Z","iopub.execute_input":"2021-11-02T11:41:16.295053Z","iopub.status.idle":"2021-11-02T11:41:16.304082Z","shell.execute_reply.started":"2021-11-02T11:41:16.295017Z","shell.execute_reply":"2021-11-02T11:41:16.302813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# let's plot s and s_x\n\nplt.plot(p_s[:,0], p_s[:,1],'rs',  markersize = 4, label='speed')\nplt.plot(p_sx[:,0], p_sx[:,1],'gs', markersize = 4, label='speed_x')\nplt.legend(loc='upper right')","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:41:18.883811Z","iopub.execute_input":"2021-11-02T11:41:18.884124Z","iopub.status.idle":"2021-11-02T11:41:19.169902Z","shell.execute_reply.started":"2021-11-02T11:41:18.884091Z","shell.execute_reply":"2021-11-02T11:41:19.168844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(p_a[:,0], p_a[:,1],'bo', label='acceleration', markersize = 4 )\nplt.legend(loc='upper right')","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:41:33.181183Z","iopub.execute_input":"2021-11-02T11:41:33.181505Z","iopub.status.idle":"2021-11-02T11:41:33.456035Z","shell.execute_reply.started":"2021-11-02T11:41:33.181471Z","shell.execute_reply":"2021-11-02T11:41:33.455130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(p_s[:,0], p_s[:,1],'rs',  markersize = 4, label='speed')\nplt.plot(p_sx[:,0], p_sx[:,1],'gs', markersize = 4, label='speed_x')\nplt.plot(p_a[:,0], p_a[:,1],'bo', label='acceleration', markersize = 4 )\nplt.legend(loc='upper right')\n","metadata":{"execution":{"iopub.status.busy":"2021-11-02T11:41:46.013566Z","iopub.execute_input":"2021-11-02T11:41:46.014197Z","iopub.status.idle":"2021-11-02T11:41:46.330792Z","shell.execute_reply.started":"2021-11-02T11:41:46.014149Z","shell.execute_reply":"2021-11-02T11:41:46.329661Z"},"trusted":true},"execution_count":null,"outputs":[]}]}