{"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":"markdown","source":"###  1. Introduction\nIn the present day NFL play games, the role of specialTeams has assumed great importance. The productivity of the specialTeams bothers on the response time; i.e. how quickly the player makes an appropriate move. \n\nThe speed of the player which in the recent past is being recognised to be the 'bane' of the NFL play game is a very important phenomenon. The importance of speed takes greater prominence since, NFL play games are now more of 'running games' rather than 'passing games' in nature.\n\nThis presentation bothers on the relevance of speed of NFL specialTeams. The goal is to promote insights which were deduced from data analysis of NFL datasets that, would lead to the optimization of the speed of NFL players. \n\nSpecifically, insights drawn from the analysis of the NFL datasets led to: \n    - the presentation of the present state of NFL specialTeams speed\n    - development of a ML based model to clarify mitigating factors of the specialTeams speed phenomenon.\n    - development of a simple statistical analysis model - Ordinary Least Square (OLS) model.\n    - the presentation of a Graphical User Interface for the monitoring and management of this phenomenon.\n\nIt is hoped that, this work will contribute, in one way or the other, to the knowledge-base of the NFL.","metadata":{}},{"cell_type":"markdown","source":"###  2. Python Libraries and Modules\nInitiate appropriate libraries and modules to be used for data analysis","metadata":{}},{"cell_type":"code","source":"# load needed libraries and modules\nimport warnings\nwarnings.filterwarnings('ignore')\n\nimport numpy as np\nimport pandas as pd","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:15:43.591735Z","iopub.execute_input":"2022-01-06T03:15:43.592013Z","iopub.status.idle":"2022-01-06T03:15:43.596611Z","shell.execute_reply.started":"2022-01-06T03:15:43.591983Z","shell.execute_reply":"2022-01-06T03:15:43.596015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"###  3.  Read Data Files. Select Variables to Work on. Remove NaN Values. \n#### 3.1. Load the Datasets\nRead NFL datasets into memory to facilitate processing. Read the Plays and 2018, 2019 and 2020 NFL Tracking into memory.","metadata":{}},{"cell_type":"code","source":"# read the plays dataset.\nPlay = pd.read_csv('../input/nfl-big-data-bowl-2022/plays.csv') \n# select variables of interest fo the study\nPlay = Play[['gameId','playId','quarter','possessionTeam','specialTeamsPlayType','specialTeamsResult','playResult']]\n# remove all blank and Nan value rows\nnan_value = float(\"NaN\") #Convert NaN values to empty string.\nPlay. replace(\"\", nan_value, inplace=True)\nPlay. dropna(subset =[ 'gameId','quarter','possessionTeam','specialTeamsPlayType','specialTeamsResult','playResult'], inplace=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:15:43.59771Z","iopub.execute_input":"2022-01-06T03:15:43.598273Z","iopub.status.idle":"2022-01-06T03:15:43.744951Z","shell.execute_reply.started":"2022-01-06T03:15:43.598225Z","shell.execute_reply":"2022-01-06T03:15:43.743968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read the 2018tracking dataset.\nd2018 = pd.read_csv('../input/nfl-big-data-bowl-2022/tracking2018.csv') \n# select variables of interest fo the study\nd2018 = d2018[['gameId','playId','x','y','s','dis','dir','position']]\n# remove all blank and Nan value rows\nnan_value = float(\"NaN\") #Convert NaN values to empty string.\nd2018. dropna(subset = ['gameId','playId','x','y','s','dis','dir','position'], inplace=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:15:43.746708Z","iopub.execute_input":"2022-01-06T03:15:43.747466Z","iopub.status.idle":"2022-01-06T03:16:08.570685Z","shell.execute_reply.started":"2022-01-06T03:15:43.747422Z","shell.execute_reply":"2022-01-06T03:16:08.569568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read the 2019tracking dataset.\nd2019 = pd.read_csv('../input/nfl-big-data-bowl-2022/tracking2019.csv') \n# select variables of interest fo the study\nd2019 = d2019[['gameId','playId','x','y','s','dis','dir','position']]\n# remove all blank and Nan value rows\nnan_value = float(\"NaN\") #Convert NaN values to empty string.\nd2019. replace(\"\", nan_value, inplace=True)\nd2019. dropna(subset = ['gameId','playId','x','y','s','dis','dir','position'], inplace=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:16:08.572896Z","iopub.execute_input":"2022-01-06T03:16:08.573272Z","iopub.status.idle":"2022-01-06T03:16:31.958579Z","shell.execute_reply.started":"2022-01-06T03:16:08.573234Z","shell.execute_reply":"2022-01-06T03:16:31.957774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read the 2020tracking dataset.\nd2020 = pd.read_csv('../input/nfl-big-data-bowl-2022/tracking2020.csv') \n# select variables of interest fo the study\nd2020 = d2020[['gameId','playId','x','y','s','dis','dir','position']]\n# remove all blank and Nan value rows\nnan_value = float(\"NaN\") #Convert NaN values to empty string.\nd2020. replace(\"\", nan_value, inplace=True)\nd2020. dropna(subset = ['gameId','playId','x','y','s','dis','dir','position'], inplace=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:16:31.959771Z","iopub.execute_input":"2022-01-06T03:16:31.96013Z","iopub.status.idle":"2022-01-06T03:17:04.440144Z","shell.execute_reply.started":"2022-01-06T03:16:31.960091Z","shell.execute_reply":"2022-01-06T03:17:04.43927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"####  3.2. Merge Files.  Remove NaN Values. \nMerge the files as required to forge dataset, named NFLProject for convinience, to beused for the analsis and study.\nThe final merged of the original Plays and 2018, 2019 and 2020 NFL Tracking datasets is made up of 35171290 rows × 13 columns. ","metadata":{}},{"cell_type":"code","source":"# merge the 2018, 2019 and 2020 tracking datasets\nfiles = [d2018,d2019,d2020]\n# Create an empty dataframe, because Python would raise a NameError\n# saying that it doesn't recognize `list_stacked`.\nTrack = pd.DataFrame() \nfor file in files:\n    Track = pd.concat([Track, file])\n\n# remove all blank and Nan value rows\nnan_value = float(\"NaN\") #Convert NaN values to empty string.\nTrack. replace(\"\", nan_value, inplace=True)\nTrack. dropna(subset = ['gameId','playId','x','y','s','dis','dir','position'], inplace=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:17:04.441417Z","iopub.execute_input":"2022-01-06T03:17:04.441659Z","iopub.status.idle":"2022-01-06T03:17:16.757577Z","shell.execute_reply.started":"2022-01-06T03:17:04.44163Z","shell.execute_reply":"2022-01-06T03:17:16.756648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# merge plays and 3 tracking datasets\nNFLProject = pd.merge(Play, Track, on=[\"gameId\", \"playId\"])\n#NFLProject\n# 35171290 rows × 13 columns","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-01-06T03:17:16.758797Z","iopub.execute_input":"2022-01-06T03:17:16.759059Z","iopub.status.idle":"2022-01-06T03:17:26.031037Z","shell.execute_reply.started":"2022-01-06T03:17:16.759028Z","shell.execute_reply":"2022-01-06T03:17:26.030178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 4. Statistical Distribution of 'NFL specialTeamsPlayType' and  'specialTeamsResult' data\nAn exploratory data analysis (EDA) presentation of the merged dataset. This presentation is minimal in scope emphasising only the essential distributions. \n####  4.1. NFL  specialTeamsPlayType by specialTeamsResult  distribution\nA look at the distribution of NFL specialTeamsPlayType and specialTeamsResult. Presentation include a table, a plot and a characterisation of salient observations.\n\n - About 44.5% of Blocked Kick Attempt score results from Extra Point play while, the outstanding 55.5% are from Field Goal play.  \n - All (100%) of Blocked Punt, Downed and Fair Catch scores result from Punt play.  \n - About 57% of Kick Attempt Good score results from Extra Point play while, the outstanding 43% are from Field Goal play. \n - About 30% of Kick Attempt No Good score results from Extra Point play while, the outstanding 70% are from Field Goal play.  \n - 100% of Kick Team Recovery score results from Kickoff play.  \n - About 72% of Muffed score results from Punt play while, the outstanding 28% are from Kickoff play.  \n - About 70% of Non-Special Teams Result score come from Punt play while, 15% come from Extar Point play and the     outstanding 15% are from Field Goal play.  \n - About 95% of Out of Bounds score result from Punt play while, the remaining 5% are from Kickoff play.  \n - About 50% of Return score results from Punt play while, the outstanding 50% are from Kickoff play.  \n - Only about 10% of Touchback score results from Punt play while, the outstanding 90% are from Kickoff play.","metadata":{}},{"cell_type":"code","source":"# a plot of the crosstab\npd.crosstab(NFLProject.specialTeamsResult, NFLProject.specialTeamsPlayType, normalize='index').plot.bar(stacked=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:17:26.032287Z","iopub.execute_input":"2022-01-06T03:17:26.032508Z","iopub.status.idle":"2022-01-06T03:17:35.383679Z","shell.execute_reply.started":"2022-01-06T03:17:26.032481Z","shell.execute_reply":"2022-01-06T03:17:35.382838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"####  4.2. NFL specialTeamsResult given specialTeamsPlayType and quarter distribution\nA look at the distribution of NFL specialTeamsResult given specialTeamsPlayType and quarter. Presentation include a table, a heatmap plot and a characterisation of salient observations.\n\n  - Blocked Kick Attempt scores most likely result from Extra Point play in the 2nd quarter of game.\n  - Blocked Punt scores result from Punt play in all 4 quarters of game and more prominently in the 1st and 3rd quarters.\n  - Downed scores result from Punt play in all 4 quarters and quarter 5 of game. They are more prominent in the 2nd and 4th quarters.\n  - Fair catch scores result from Kickoff and Punt play in all 4 quarters and quarter 5 of game. They are more likely to occur in the 1st and 2nd quarters.\n  - Kick Attempt Good scores result from Extra Point and Field Goal play in all 4 quarters and quarter 5 of game. They are more likely to occur in the 2nd and 4th quarters.\n  - Kick Attempt No Good scores result from Extra Point and Field Goal play in all 4 quarters and quarter 5 of game. They are more likely to occur in the 2nd and 4th quarters.\n  - Kickoff Team Recovery scores result from Kickoff play in all 4 quarters of game. They are more likely to occur in the 4th quarters.\n  - Muffed scores result from Kickoff and Punt play in all 4 quarters and quarter 5 of game. They are more likely to occur in the 2nd and 3rd quarters.\n  - Non-Special Teams Result scores result from Extra Point , Field Goal and Puntplay in all 4 quarters of game. They are more likely to occur in the 2nd and 4th quarters.\n  - Out of Bounds scores result from Field Goal, Kickoff and Punt play in all 4 quarters and quarter 5 of game. They are more likely to occur in the 2nd and 4th quarters.\n  - Return scores result from Kickoff and Punt play in all 4 quarters and quarter 5 of game. They are more likely to occur in the 2nd and 3rd quarters.\n  - Touchback scores result from Kickoff and Punt play in all 4 quarters and quarter 5 of game. They are more likely to occur in the 3rd quarter.\n  \n  - The heatmap plot below shows an intensity of occurence pattern with a concentration range of between 0 and 1.","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\nsns.heatmap(pd.crosstab(NFLProject.specialTeamsResult, [NFLProject.specialTeamsPlayType, NFLProject.quarter],normalize='columns'),\n            cmap=\"YlGnBu\", annot=True, cbar=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:17:35.386025Z","iopub.execute_input":"2022-01-06T03:17:35.386784Z","iopub.status.idle":"2022-01-06T03:17:49.0649Z","shell.execute_reply.started":"2022-01-06T03:17:35.386737Z","shell.execute_reply":"2022-01-06T03:17:49.063972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### 4.3. Distribution of 'speed' data\nA dataset of 35171290 rows indicates that:","metadata":{}},{"cell_type":"code","source":"# derive the essential statistics of the 's' variable\nNFLProject['s'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:17:49.066067Z","iopub.execute_input":"2022-01-06T03:17:49.066314Z","iopub.status.idle":"2022-01-06T03:17:50.091652Z","shell.execute_reply.started":"2022-01-06T03:17:49.066284Z","shell.execute_reply":"2022-01-06T03:17:50.090691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- the maximum 'speed' of NFL players is 15.63 yds/sec which is 31.97mph\n- the average 'speed' of NFL players is 3.65 yds/sec which is 7.476 mph.\n- the median 'speed' of NFL players is 3.16 yds/sec which is 6.46 mph.\n\nFurthermore, general observation indicate that most sprints to the zone to score touchdowns is usually at about 10.57 yds/sec, ie. 21.64 mph. \n\nThe proposal is that, programmed and regular monitoring could very significantly improve on these levels.","metadata":{}},{"cell_type":"markdown","source":"###  5.  A Statistical  Model For Prediction of speed in NFL games\nA statistical model to further explore the NFL player speed. This model considers the relationships between the x, y, 'dis, 'dir', specialTeamsPlayType and s(speed) variables.\n####  5.1. Ordinary Least Squares (OLS) Model\nApply the following Ordinary Least Squares model:\n##              result = ols(formula=\"s ~ y + x + dis + dir + specialTeamsPlayType\", data = NFLProject).fit()\n\n\n\n####  5.2. interpretation of the Results of the OLS model\n\n- Adj. R-squared = 0.996 indicates that the fit of the model is very good. This is to say that assuming certain conditions are met, the R-squared value of 0.996 indicates a pretty good fit.\n- The Y-intercept suggests that, if T.Field Goal, T.Kickoff, T.Punt, y, x, dis and dir are zero, then the expected output (i.e. SPEED - the speed of team across all specialTeamsPlayTypes is given by the intercept coefficient of -0.0156.\n- The 'T.Field Goal' coefficient suggests that if everything else is held constant, a change of one unit in 'T.Field Goal' will result in an expected increase of the 'SPEED' by about 0.0002 units.\n- The 'T.Kickoff' coefficient suggests that if everything else is held constant, a change of one unit in 'T.Kickoff' will result in an expected increase of the 'SPEED' by about 0.0523 units.\n- The 'T.Punt' coefficient suggests that if everything else is held constant, a change of one unit in 'T.Punt' will result in an expected increase of the 'SPEED' by about 0.0338 units.\n- The 'y' coefficient suggests that if everything else is held constant, a change of one unit in 'y' will result in an expected decrease of the 'SPEED' by about 0.000003283 units.\n- The 'x' coefficient suggests that if everything else is held constant, a change of one unit in 'x' will result in an expected decrease of the 'SPEED' by about 0.0000004162 units.\n- The 'dis' coefficient suggests that if everything else is held constant, a change of one unit in 'dis' will result in an expected increase of the 'SPEED' by about 9.8978 units.\n- The 'dir' coefficient suggests that if everything else is held constant, a change of one unit in 'dir' will result in an expected increase of the 'SPEED' by about 0.000002328 units.\n- The std err reflects the level of accuracy of the coefficients. The lower it is, the higher is the level of accuracy. The p-value of less than 0.05 indicates that we are dealing with statistically significant distributions.\n- Confidence Interval represents with a likelihood of 95%, the range in which our coefficients are likely to fall.","metadata":{}},{"cell_type":"markdown","source":"#### 5.3. A Graphical User Interface (GUI)\n- A plausible Graphical User Interface (GUI) which is based on the findings of the OLS model in paragraph 5.2 above is presented here.\n- This GUI is an interactive tool suggested as an auxiliary speed monitoring device. Adaptation of the concepts of this tool can be of immense use for NFL Team Manager(s), specialTeamsManagers and administrators in general\n- The number of FieldGoals, Kickoffs and Punts stipulated in the GUI are based on the averages derived from processed data.","metadata":{}},{"cell_type":"code","source":"import ipywidgets as widgets\nfrom IPython.display import display, clear_output\nfrom ipywidgets import interact, interactive, fixed, interact_manual\n\n# Label widget for image\ninfoone = widgets.Label(value='GRAPHICAL USER INTERFACE: ',style={'description_width': 'initial'})\ninfotwo = widgets.Label(value='based on NFL Data Sets: ',style={'description_width': 'initial'})\ninfothree = widgets.Label (value= 'Games, Plays, 2018,  ',style={'description_width': 'initial'})\ninfofour = widgets.Label (value= '2019 and 2020 Tracking  ',style={'description_width': 'initial'})\n\n# Image Widget\nvbox_image_label=widgets.VBox([infoone,infotwo,infothree,infofour])\n\n# spacing\nlabel1 = widgets.Label(value='.......',style={'description_width':'initial'})\nvbox_space = widgets.VBox([label1],style={'description_width':'initial'})\n\n# label widget for sliders\nlabelA = widgets.Label(value='NFL specialTeamsPlayTypes SPEED MONITOR..               ',style={'description_width':'initial'})\nlabelB = widgets.Label(value=\"     1.Monitor Speed for specialTeamsPlayType(s);     \",style={'description_width':'initial'})\nlabelC = widgets.Label(value='     2.Self-explanatory labeling;                     ',style={'description_width':'initial'})\nlabelD = widgets.Label(value='     3-Choose from specialTeamsPlayType(s) sliders;   ',style={'description_width':'initial'})\nlabelE = widgets.Label(value='     HOW IT WORKS:        ',style={'description_width':'initial'})\nlabelF = widgets.Label(value='       Goal is to Monitor speed of NFL players        ',style={'description_width':'initial'})\nlabelG = widgets.Label(value='       For optimized specialTeamsPlayType result,        ',style={'description_width':'initial'})\n\nvbox_info=widgets.VBox([labelA, labelB, labelC, labelD, labelE, labelF, labelG])\n\ndef funcT(Intercept, T_FieldGoal, T_Kickoff, T_Punt, Xaxis, Yaxis, dis, dir ):\n    \n    display((-Intercept + 0.0002*T_FieldGoal + 0.0523*T_Kickoff + 0.0338*T_Punt + Xaxis - Yaxis + dis - dir ))\n\nw = interactive(funcT, Intercept = widgets.FloatSlider(min=0.0156, max=0.0156, value=0.0156, description=\"Intercept\",layout=widgets.Layout(width =\"200px\"),slider_color='red'),\n                       T_FieldGoal = widgets.IntSlider(min=0, max=3, value=0, step=1, description=\"#FieldGoal\",layout=widgets.Layout(width =\"200px\"),slider_color='blue'),\n                       T_Kickoff = widgets.IntSlider(min=0, max=10, value=0, step=1, description=\"#Kickoff\",layout=widgets.Layout(width =\"200px\"),slider_color='blue'),\n                       T_Punt = widgets.IntSlider(min=0, max=5, value=0, step=1, description=\"#Punt\",layout=widgets.Layout(width =\"200px\"),slider_color='blue'),\n                       Xaxis = widgets.FloatSlider(min=0.0000004162, max=0.0000004162, value=0.0000004162, description=\"xConstant\",layout=widgets.Layout(width =\"200px\"),slider_color='red'),\n                       Yaxis = widgets.FloatSlider(min=0.000003283, max=0.000003283, value=0.000003283, description=\"yConstant\",layout=widgets.Layout(width =\"200px\"),slider_color='red'),\n                       dis = widgets.FloatSlider(min=9.8978, max=9.8978, value=9.8978, description=\"disConstant\",layout=widgets.Layout(width =\"200px\"),slider_color='red'),\n                       dir = widgets.FloatSlider(min=0.000002328, max=0.000002328, value=0.000002328, description=\"dirConstant\",layout=widgets.Layout(width =\"200px\"),slider_color='red'),\n                       \n    )\n\nGUIpage = widgets.HBox([vbox_image_label,vbox_space, vbox_info,vbox_space, w])\ndisplay(GUIpage)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T03:17:50.093055Z","iopub.execute_input":"2022-01-06T03:17:50.093258Z","iopub.status.idle":"2022-01-06T03:17:50.309197Z","shell.execute_reply.started":"2022-01-06T03:17:50.093232Z","shell.execute_reply":"2022-01-06T03:17:50.308429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"###  6. Summary and Remarks\n\"The faster the ball moves,say from the long snapper to the punter for example, the quicker the punt gets the ball off into the air thereby reducing the number of turnovers for his team on 4th down\". This captures the essence of NFL play games.\n\nNFL datasets were analysed and some insights drawn from the analysis were discussed with a view and desire to participating in strenghtening the knowledge-base of the NFL.\n\nSusequently, a simple and plausible approach for how to improve on speed, of specialTeams in particular, was presented.\n\nThe concept and the suggested approach are firm and enduring. This is because it could be easily updated as more data become available. The concept bothers on close monitoring of 'speed' of players to promote and ensure improved performance and team victory rates.\n\nFurthermore, it is possible to search for more robust models which could greatly improve the veracity of the concept of this presentation.","metadata":{}}]}