{"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\nimport plotly.express as px\nfrom plotly.offline import plot, iplot, init_notebook_mode\ninit_notebook_mode(connected=True)\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","_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:32.880771Z","iopub.execute_input":"2021-12-14T21:45:32.881450Z","iopub.status.idle":"2021-12-14T21:45:32.894518Z","shell.execute_reply.started":"2021-12-14T21:45:32.881414Z","shell.execute_reply":"2021-12-14T21:45:32.893610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# What is a good kickoff?","metadata":{}},{"cell_type":"markdown","source":"![2007 Hawaii Bowl - Boise State University vs East Carolina University - Second Half Kickoff](https://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/2007_Hawaii_Bowl_-_Boise_State_University_vs_East_Carolina_University_-_Second_Half_Kickoff.jpg/800px-2007_Hawaii_Bowl_-_Boise_State_University_vs_East_Carolina_University_-_Second_Half_Kickoff.jpg)\n\n2007 Hawaii Bowl - Boise State University vs East Carolina University - Second Half Kickoff\n\nby **Mark Ramelb**","metadata":{}},{"cell_type":"markdown","source":"This notebook is to analyze data on **kickoff** plays, in order to provide insights on the strategy.\n\nIf kickoff is a new term to you, NFL has provided a [definition](https://operations.nfl.com/learn-the-game/nfl-basics/terms-glossary/)\n\n> A kick that puts the ball in play at the start of each half, at the start of overtime, after each Try, and after a successful field goal.\n\nOther than that, I personally find this Youtube [video](https://www.youtube.com/watch?v=9HwNDNeDpFw) is quite helpful as a brief intro.\n\nFrom the data source in this competition, we can see four types of special team plays - \n\n* Kickoffs\n* Punt\n* Extra point\n* Field goal\n\nThe type having the highest number is Kickoffs, which shows its importance in special team performance.\n","metadata":{}},{"cell_type":"markdown","source":"# Kickoff is the most common play type for the special team","metadata":{}},{"cell_type":"code","source":"# fetch play data\nplay_data = pd.read_csv(\"/kaggle/input/nfl-big-data-bowl-2022/plays.csv\")","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:32.895968Z","iopub.execute_input":"2021-12-14T21:45:32.896761Z","iopub.status.idle":"2021-12-14T21:45:33.057064Z","shell.execute_reply.started":"2021-12-14T21:45:32.896709Z","shell.execute_reply":"2021-12-14T21:45:33.056214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# how many Kickoffs were played from the data source?\nplay_data_aggr = play_data.groupby('specialTeamsPlayType').nunique().reset_index()[['specialTeamsPlayType','playId']]\nfig = px.bar(play_data_aggr, \n             x='specialTeamsPlayType', \n             y='playId',\n             labels={'specialTeamsPlayType':'Type of Special team plays',\n                   'playId':'Number of plays'}\n            )\nfig.update_layout(title_text='Number of special team plays per type<br><sup>Kickoff has the highest number of play in all four special team types</sup>')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.058266Z","iopub.execute_input":"2021-12-14T21:45:33.058477Z","iopub.status.idle":"2021-12-14T21:45:33.216626Z","shell.execute_reply.started":"2021-12-14T21:45:33.058451Z","shell.execute_reply":"2021-12-14T21:45:33.216000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Most usual starting positions for a kickoff","metadata":{}},{"cell_type":"markdown","source":"The starting position of the ball for a kickoff is usually at either the **35** line or the **65** line, depending on the team kicked off the ball is heading to the right or the left.","metadata":{}},{"cell_type":"code","source":"# select plays which are Kickoffs\nkickoff_play = play_data.loc[play_data[\"specialTeamsPlayType\"] == \"Kickoff\"]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.218436Z","iopub.execute_input":"2021-12-14T21:45:33.218808Z","iopub.status.idle":"2021-12-14T21:45:33.228022Z","shell.execute_reply.started":"2021-12-14T21:45:33.218762Z","shell.execute_reply":"2021-12-14T21:45:33.227364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# The start and the end of the x coorinator is the outside egde of the goal zone\n# so we need to minus the absoluteYardlineNumber by 10 if we want to get the exact number of the number line\nkickoff_play['absoluteYardlineNumber'] = kickoff_play['absoluteYardlineNumber'] - 10 \nabsoluteYardlineNumber_aggr = kickoff_play.groupby(['absoluteYardlineNumber']).nunique().reset_index()[['absoluteYardlineNumber','playId']]","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.229151Z","iopub.execute_input":"2021-12-14T21:45:33.229521Z","iopub.status.idle":"2021-12-14T21:45:33.281353Z","shell.execute_reply.started":"2021-12-14T21:45:33.229468Z","shell.execute_reply":"2021-12-14T21:45:33.280259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.bar(absoluteYardlineNumber_aggr, \n             x='absoluteYardlineNumber', \n             y='playId',\n             labels={'absoluteYardlineNumber':'Location of ball downfield',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per Location of ball downfield')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.283115Z","iopub.execute_input":"2021-12-14T21:45:33.283439Z","iopub.status.idle":"2021-12-14T21:45:33.353428Z","shell.execute_reply.started":"2021-12-14T21:45:33.283394Z","shell.execute_reply":"2021-12-14T21:45:33.352547Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Among the 3,454 Kickoffs, **Touchback** and **Return** are two of the most common results, followed by Out of bounds, Muffed, Kick Team Recovery, Fair catch and Downed.","metadata":{}},{"cell_type":"code","source":"# nr of specialTeamsResult of kickoff\nkickoff_play_result = kickoff_play.groupby(['specialTeamsResult']).nunique().reset_index()[['specialTeamsResult','playId']]\n\nfig = px.bar(kickoff_play_result, \n             x='specialTeamsResult', \n             y='playId',\n             labels={'specialTeamsResult':'Result of kickoffs',\n                   'playId':'Number of plays'}\n            )\nfig.update_layout(title_text='Number of plays per kickoff result')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.354774Z","iopub.execute_input":"2021-12-14T21:45:33.355045Z","iopub.status.idle":"2021-12-14T21:45:33.464902Z","shell.execute_reply.started":"2021-12-14T21:45:33.354991Z","shell.execute_reply":"2021-12-14T21:45:33.463918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"game_data = pd.read_csv(\"/kaggle/input/nfl-big-data-bowl-2022/games.csv\")","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.466487Z","iopub.execute_input":"2021-12-14T21:45:33.466789Z","iopub.status.idle":"2021-12-14T21:45:33.480753Z","shell.execute_reply.started":"2021-12-14T21:45:33.466750Z","shell.execute_reply":"2021-12-14T21:45:33.479996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Touchback tends to become more popular for special plays over the years since 2018\nThe reason is it became more easier to occur since 2018, the time NFL approved a new rule that if a ball gets to the end zone and touches the ground, it’s an automatic touchback. There’s no need for a player to pick it up and kneel, or even catch a ball if it’s headed for the end zone and they don’t intend to return it. This is a small time saver, but the goal is to blow a play dead earlier so that unnecessary collisions don’t happen. Under the previous rules, a player could take their time gathering a ball and kneeling while the coverage team and return team blockers still careened toward each other for no reason. [source](https://www.sbnation.com/2018/5/22/17369774/nfl-kickoff-rule-change-explained)\n","metadata":{}},{"cell_type":"code","source":"game_play_data = pd.merge(\n    kickoff_play,\n    game_data,\n    how=\"inner\",\n    left_on=[\"gameId\"],\n    right_on=[\"gameId\"],\n    sort=True,\n    suffixes=(\"_x\", \"_y\"),\n    copy=True,\n    indicator=False,\n    validate=None,\n)\n\ngame_play_data_type = game_play_data[['gameId','playId','season','specialTeamsResult']]\n\ngame_play_data_type['unique_id'] = game_play_data['gameId'].astype(str) + game_play_data['playId'].astype(str)\ngame_play_data_type_aggr = game_play_data_type.groupby(['season','specialTeamsResult']).count().reset_index()\n\n\ngame_play_data_type_aggr['year_sum'] = game_play_data_type_aggr['unique_id'].groupby(game_play_data_type_aggr['season']).transform('sum')\ngame_play_data_type_aggr['Percentage_of_total_plays'] = round(game_play_data_type_aggr['unique_id'] * 100/ game_play_data_type_aggr['year_sum'],1)\ntouchback_share = game_play_data_type_aggr.loc[game_play_data_type_aggr['specialTeamsResult'] == 'Touchback']\ntouchback_share['season'] = touchback_share['season'].astype(str)\n\nfig = px.line(touchback_share, x=\"season\", y=\"Percentage_of_total_plays\", title='Percentage of touchback is played by the special team during the season')\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.482564Z","iopub.execute_input":"2021-12-14T21:45:33.482921Z","iopub.status.idle":"2021-12-14T21:45:33.620915Z","shell.execute_reply.started":"2021-12-14T21:45:33.482872Z","shell.execute_reply":"2021-12-14T21:45:33.620300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Gained yards per kickoff outcome","metadata":{}},{"cell_type":"markdown","source":"Return and touchback are most two common outcomes of kickoff. The two have pretty close median in gained yards of the kickoff team, which is ~40 yards. Though the return has a much wider range of possible outcomes, from 65 to minus -35. It indicates that touchback is more safe but might be less uncertain, exciting than return.","metadata":{}},{"cell_type":"code","source":"kickoff_play['uniqueId'] = kickoff_play['gameId'].astype(str) + kickoff_play['playId'].astype(str)\nyards_gained_outcome = kickoff_play[['uniqueId','playResult','specialTeamsResult']]\nfig = px.box(yards_gained_outcome, \n             x=\"specialTeamsResult\", \n             y=\"playResult\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:45:33.623486Z","iopub.execute_input":"2021-12-14T21:45:33.623839Z","iopub.status.idle":"2021-12-14T21:45:33.788653Z","shell.execute_reply.started":"2021-12-14T21:45:33.623796Z","shell.execute_reply":"2021-12-14T21:45:33.787731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Does point and time left correlate with the kickoff outcome?","metadata":{"_kg_hide-input":true}},{"cell_type":"code","source":"\"\"\"\ngame_play_data_point_time = game_play_data[['gameId','playId','quarter','yardsToGo','specialTeamsResult',\n                'gameClock','preSnapHomeScore','preSnapVisitorScore','possessionTeam','homeTeamAbbr','visitorTeamAbbr']]\ngame_play_data_point_time['Score_diff'] = np.where(game_play_data_point_time['possessionTeam'] == game_play_data_point_time['homeTeamAbbr'], \n                                                            game_play_data_point_time['preSnapHomeScore'] - game_play_data_point_time['preSnapVisitorScore'], \n                                                            -(game_play_data_point_time['preSnapHomeScore'] - game_play_data_point_time['preSnapVisitorScore']))\n\ngame_play_data_point_time['uniqueId'] = game_play_data_point_time['gameId'].astype(str) + game_play_data_point_time['playId'].astype(str)\nfig = px.box(game_play_data_point_time, \n             x=\"specialTeamsResult\", \n             y=\"Score_diff\")\nfig.show()\n\"\"\"","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.789888Z","iopub.execute_input":"2021-12-14T21:45:33.790157Z","iopub.status.idle":"2021-12-14T21:45:33.798134Z","shell.execute_reply.started":"2021-12-14T21:45:33.790127Z","shell.execute_reply":"2021-12-14T21:45:33.796808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Taking 2020 tracking data as an example, I plotted the routes of ball per special team play type.","metadata":{}},{"cell_type":"code","source":"# tracking data\ntracking_2020 = pd.read_csv('/kaggle/input/nfl-big-data-bowl-2022/tracking2020.csv')\ntracking_2020['x'] = tracking_2020['x'] - 10","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:45:33.799477Z","iopub.execute_input":"2021-12-14T21:45:33.800247Z","iopub.status.idle":"2021-12-14T21:46:18.476835Z","shell.execute_reply.started":"2021-12-14T21:45:33.800213Z","shell.execute_reply":"2021-12-14T21:46:18.475112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_tracking_2020 = pd.merge(\n    kickoff_play,\n    tracking_2020,\n    how=\"inner\",\n    left_on=[\"gameId\",\"playId\"],\n    right_on=[\"gameId\",\"playId\"],\n    sort=True,\n    suffixes=(\"_x\", \"_y\"),\n    copy=True,\n    indicator=False,\n    validate=None,\n)\n\n# ball route per type\nkickoff_ball = kickoff_tracking_2020.loc[kickoff_tracking_2020['displayName'] == 'football']","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:18.481973Z","iopub.execute_input":"2021-12-14T21:46:18.483755Z","iopub.status.idle":"2021-12-14T21:46:42.973300Z","shell.execute_reply.started":"2021-12-14T21:46:18.483515Z","shell.execute_reply":"2021-12-14T21:46:42.972345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.scatter(kickoff_ball, \n                 x=\"x\", \n                 y=\"y\", \n                 facet_col=\"playDirection\", \n                 facet_row=\"specialTeamsResult\",\n                height=800, \n                 width=1200)\nfig.update_traces(marker={'size': 2,\n                         'opacity':0.5})\nfig.for_each_annotation(lambda a: a.update(text=a.text.split(\"=\")[-1]))\n\nfig.update_layout(\n    paper_bgcolor='rgba(0,0,0,0)',\n    plot_bgcolor='rgba(0,0,0,0)',\n    title_text='Ball route of kickoff per type')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:42.974797Z","iopub.execute_input":"2021-12-14T21:46:42.975045Z","iopub.status.idle":"2021-12-14T21:46:44.676309Z","shell.execute_reply.started":"2021-12-14T21:46:42.975004Z","shell.execute_reply":"2021-12-14T21:46:44.674277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's create a visualization to illustrate how players and ball are moving in the field.","metadata":{}},{"cell_type":"code","source":"# playId 39\n# gameId 2020091000\nplay_2020091000_39 = kickoff_tracking_2020.loc[(kickoff_tracking_2020['playId'] == 3509) & \n                                    (kickoff_tracking_2020['gameId'] == 2020091310)]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:44.677591Z","iopub.execute_input":"2021-12-14T21:46:44.677947Z","iopub.status.idle":"2021-12-14T21:46:44.697098Z","shell.execute_reply.started":"2021-12-14T21:46:44.677916Z","shell.execute_reply":"2021-12-14T21:46:44.696204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# draw a field board\nimport plotly.graph_objects as go\n\n#fig = go.Figure()\n\nfig = px.scatter(play_2020091000_39, \n           x=\"x\", \n           y=\"y\", \n           animation_frame=\"time\", \n           animation_group=\"nflId\",\n           color=\"team\",\n           hover_name=\"displayName\"           \n          )\n\"\"\"\nfig.add_shape(type=\"rect\",\n    x0=0, \n    y0=53.3, \n    x1=120, \n    y1=0,\n    line=dict(color=\"white\"),\n)\n\n\n\n\nx_start = 10\nwhile x_start <= 110:\n    fig.add_shape(type=\"line\",\n    x0=x_start, y0=0, x1=x_start, y1=53.3,\n    line=dict(color=\"white\",width=1))\n    fig.add_annotation(text=str(x_start),x=x_start, y=1, showarrow=False)\n    fig.add_annotation(text=str(x_start),x=x_start, y=52, showarrow=False)\n    x_start += 5\n\n\n# Set axes properties\nfig.update_xaxes(range=[0, 120], \n                 showgrid=False)\nfig.update_yaxes(range=[0, 53.3], showgrid = False)\n\nfig.update_shapes(dict(xref='x', \n                       yref='y'))\n\n\n\nfig.update_layout(xaxis_visible=False, xaxis_showticklabels=False)\nfig.update_layout(xaxis_visible=False, xaxis_showticklabels=False,\n                  yaxis_visible=False, yaxis_showticklabels=False,\n                 paper_bgcolor='rgba(0,0,0,0)',\n                  plot_bgcolor='green')\n\"\"\"\nfig.show()\n\n\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:44.698776Z","iopub.execute_input":"2021-12-14T21:46:44.699086Z","iopub.status.idle":"2021-12-14T21:46:45.850943Z","shell.execute_reply.started":"2021-12-14T21:46:44.699049Z","shell.execute_reply":"2021-12-14T21:46:45.850050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"TBA:\n\nWhat are the outcomes of each result?","metadata":{}},{"cell_type":"markdown","source":"# Returning yards could be a good metric","metadata":{}},{"cell_type":"markdown","source":"Once catching the ball, the Kickoff return team tries as much as possible to reach the end zone of the kickoff team. The return yards is calculated from the ball possession is changed. How many yards do they gain in general? The data is close to a normal distribution which has an average number ~20.\n\nAnother interesting thing is X% of the kickoffs return team gained no yards at all. Since the goal of the kickoff team is to limit the yards the opposing team gaining once they possess the ball, I'd firstly look at the returning yards as a metric to evaluate how good a kickoff is.","metadata":{}},{"cell_type":"code","source":"kickReturn_aggr = kickoff_play.groupby(['kickReturnYardage']).nunique().reset_index()[['kickReturnYardage',\n                                                                               'playId']]\n\nfig = px.bar(kickReturn_aggr, \n             x='kickReturnYardage', \n             y='playId',\n             labels={'kickReturnYardage':'Kick Return Yard age',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per Return Yard age')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:45.852427Z","iopub.execute_input":"2021-12-14T21:46:45.852770Z","iopub.status.idle":"2021-12-14T21:46:45.962211Z","shell.execute_reply.started":"2021-12-14T21:46:45.852709Z","shell.execute_reply":"2021-12-14T21:46:45.960839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"But one thing we need to keep in mind is if the ball to is kicked beyond the end zone of the opposing team, then a **touchback** will occur.\n\nIn such case, according to the current NFL rule, the kickoff team will gain no awards and the receiving team will start their round at 25 yard line from their side.\n\nAnd in our dataset, the kickReturnYardage value will be null if the play result is a touchback.","metadata":{}},{"cell_type":"code","source":"print(\"Not null values in kickReturnYardage data once a touchback result occured is: \" + \n      str(sum(kickoff_play.loc[kickoff_play['specialTeamsResult'] == 'Touchback']['kickReturnYardage'].notna())))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:45.963556Z","iopub.execute_input":"2021-12-14T21:46:45.963793Z","iopub.status.idle":"2021-12-14T21:46:45.974120Z","shell.execute_reply.started":"2021-12-14T21:46:45.963763Z","shell.execute_reply":"2021-12-14T21:46:45.973221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# A ball is often kicked ~75 yards in length...","metadata":{}},{"cell_type":"code","source":"kickLength_aggr = kickoff_play.groupby(['kickLength']).nunique().reset_index()[['kickLength',\n                                                                               'playId']]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:45.975853Z","iopub.execute_input":"2021-12-14T21:46:45.976202Z","iopub.status.idle":"2021-12-14T21:46:46.032901Z","shell.execute_reply.started":"2021-12-14T21:46:45.976166Z","shell.execute_reply":"2021-12-14T21:46:46.032108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Kick length** indicates the distance of a kicked ball in air.\nThe most common length is 75 yards, which has almost 3 times in terms of number of the second length - 70 yards. Another interesting finding is on the left side of the chart below, we can see a small but noticeable amount of kick lengths lie around 10 yards.","metadata":{}},{"cell_type":"code","source":"fig = px.bar(kickLength_aggr, \n             x='kickLength', \n             y='playId',\n             labels={'kickLength':'Kick length',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per kick length')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.034392Z","iopub.execute_input":"2021-12-14T21:46:46.034868Z","iopub.status.idle":"2021-12-14T21:46:46.110212Z","shell.execute_reply.started":"2021-12-14T21:46:46.034836Z","shell.execute_reply":"2021-12-14T21:46:46.109282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Is Kick length significantly correlated with the returning yards?","metadata":{}},{"cell_type":"markdown","source":"Yes. They are positively correlated.","metadata":{}},{"cell_type":"code","source":"correlation = kickoff_play[\"kickLength\"].corr(kickoff_play[\"kickReturnYardage\"])\nprint(\"The correlation between Kick length and Kick return is: \" + str(round(correlation,3)) + \".\")","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.112086Z","iopub.execute_input":"2021-12-14T21:46:46.112715Z","iopub.status.idle":"2021-12-14T21:46:46.120780Z","shell.execute_reply.started":"2021-12-14T21:46:46.112666Z","shell.execute_reply":"2021-12-14T21:46:46.119798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From the chart below, it turns out there is an **upward** trend indicating the relationship between how far the ball is kicked and how much the returning team could advance the ball towards the end zone.","metadata":{}},{"cell_type":"code","source":"import plotly.express as px\nfig = px.scatter(kickoff_play, \n                 x=\"kickLength\", \n                 y=\"kickReturnYardage\",\n                 trendline=\"ols\",\n                 labels=dict(kickLength=\"Kick length (yards)\", kickReturnYardage=\"Kick return (yards)\"),\n                 title=\"The correlation between Kick length and Kick return\"\n                )\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.122719Z","iopub.execute_input":"2021-12-14T21:46:46.123314Z","iopub.status.idle":"2021-12-14T21:46:46.250340Z","shell.execute_reply.started":"2021-12-14T21:46:46.123264Z","shell.execute_reply":"2021-12-14T21:46:46.249352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The hypothesis could be the further the ball is kicked, the longer distance/longer time it takes the kick team to tackle the returning team player who holds the ball.\n\nTherefore, the returning player could have much space and time to move forward.","metadata":{}},{"cell_type":"code","source":"# kicklength per team\nfig = px.box(kickoff_play, \n             x=\"possessionTeam\", \n             y=\"kickLength\")\nfig.show()\n\n","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:46:46.252262Z","iopub.execute_input":"2021-12-14T21:46:46.252574Z","iopub.status.idle":"2021-12-14T21:46:46.407088Z","shell.execute_reply.started":"2021-12-14T21:46:46.252528Z","shell.execute_reply":"2021-12-14T21:46:46.406173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Kickoff teams usually get 40 yards as the result of their kickoff","metadata":{}},{"cell_type":"markdown","source":"The reason is out of 3,454 plays, around 2,675 of them ended up as touchback, in which the ball will be placed at the 35/75 yard line from the opposing team. And it resulted in the most cases, Kickoff teams usually get 40 yards as result.","metadata":{}},{"cell_type":"code","source":"playResult_aggr = kickoff_play.groupby(['playResult']).nunique().reset_index()[['playResult',\n                                                                               'playId']]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.408373Z","iopub.execute_input":"2021-12-14T21:46:46.409067Z","iopub.status.idle":"2021-12-14T21:46:46.464850Z","shell.execute_reply.started":"2021-12-14T21:46:46.409018Z","shell.execute_reply":"2021-12-14T21:46:46.463632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.bar(playResult_aggr, \n             x='playResult', \n             y='playId',\n             labels={'playResult':'Play result',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per play result')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.466138Z","iopub.execute_input":"2021-12-14T21:46:46.466399Z","iopub.status.idle":"2021-12-14T21:46:46.537506Z","shell.execute_reply.started":"2021-12-14T21:46:46.466363Z","shell.execute_reply":"2021-12-14T21:46:46.536705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"Let's explore what the PFFScoutingData reveals to us.","metadata":{}},{"cell_type":"code","source":"pff = pd.read_csv(\"/kaggle/input/nfl-big-data-bowl-2022/PFFScoutingData.csv\")","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.539117Z","iopub.execute_input":"2021-12-14T21:46:46.539592Z","iopub.status.idle":"2021-12-14T21:46:46.638076Z","shell.execute_reply.started":"2021-12-14T21:46:46.539546Z","shell.execute_reply":"2021-12-14T21:46:46.637343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_pff = pd.merge(\n    kickoff_play,\n    pff,\n    how=\"inner\",\n    left_on=[\"gameId\",\"playId\"],\n    right_on=[\"gameId\",\"playId\"],\n    sort=True,\n    suffixes=(\"_x\", \"_y\"),\n    copy=True,\n    indicator=False,\n    validate=None,\n)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.639528Z","iopub.execute_input":"2021-12-14T21:46:46.639825Z","iopub.status.idle":"2021-12-14T21:46:46.680568Z","shell.execute_reply.started":"2021-12-14T21:46:46.639783Z","shell.execute_reply":"2021-12-14T21:46:46.679463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Possible values for kickoff plays:\n\n* D: Deep - your normal deep kick with decent hang time\n* F: Flat - different than a Squib in that it will have some hang time and no roll but has a lower trajectory and hang time than a Deep kick off\n* K: Free Kick - Kick after a safety\n* O: Obvious Onside - score and situation dictates the need to regain possession. Also the hands team is on for the returning team\n* P: Pooch kick - high for hangtime but not a lot of distance - usually targeting an upman\n* Q: Squib - low-line drive kick that bounces or rolls considerably, with virtually no hang time\n* S: Surprise Onside - accounting for score and situation an onsides kick that the returning team doesn’t expect. Hands teams probably aren't on the field\n* B: Deep Direct OOB - Kickoff that is aimed deep (regular kickoff) that goes OOB directly (doesn't bounce)","metadata":{}},{"cell_type":"code","source":"kickType_aggr = kickoff_pff.groupby(['kickType']).nunique().reset_index()[['kickType','playId']]\nfig = px.bar(kickType_aggr, \n             x='kickType', \n             y='playId',\n             labels={'kickType':'Kick type',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per Kick type')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:46.686104Z","iopub.execute_input":"2021-12-14T21:46:46.686359Z","iopub.status.idle":"2021-12-14T21:46:47.007111Z","shell.execute_reply.started":"2021-12-14T21:46:46.686330Z","shell.execute_reply":"2021-12-14T21:46:47.006308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# It usually takes ~4 seconds for the ball hanging in the air after a kickoff.","metadata":{}},{"cell_type":"code","source":"kickHangTime_aggr = kickoff_pff.groupby(['hangTime']).nunique().reset_index()[['hangTime','playId']]\nfig = px.bar(kickHangTime_aggr, \n             x='hangTime', \n             y='playId',\n             labels={'hangTime':'Hang time',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per hang time')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:47.008633Z","iopub.execute_input":"2021-12-14T21:46:47.009100Z","iopub.status.idle":"2021-12-14T21:46:47.156998Z","shell.execute_reply.started":"2021-12-14T21:46:47.009056Z","shell.execute_reply":"2021-12-14T21:46:47.156001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# In most kickoffs, the direction of the ball goes to the center, either intended or actual.","metadata":{}},{"cell_type":"code","source":"kickDirectionIntended= kickoff_pff.groupby(['kickDirectionIntended']).nunique().reset_index()[['kickDirectionIntended','playId']]\nfig = px.bar(kickDirectionIntended, \n             x='kickDirectionIntended', \n             y='playId',\n             labels={'kickDirectionIntended':'kick Direction Intended',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per kick Direction Intended')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:47.158881Z","iopub.execute_input":"2021-12-14T21:46:47.159209Z","iopub.status.idle":"2021-12-14T21:46:47.297380Z","shell.execute_reply.started":"2021-12-14T21:46:47.159163Z","shell.execute_reply":"2021-12-14T21:46:47.296455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickDirectionActual= kickoff_pff.groupby(['kickDirectionActual']).nunique().reset_index()[['kickDirectionActual','playId']]\nfig = px.bar(kickDirectionActual, \n             x='kickDirectionActual', \n             y='playId',\n             labels={'kickDirectionActual':'kick Direction Actual',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per kick Direction Actual')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:47.298702Z","iopub.execute_input":"2021-12-14T21:46:47.298927Z","iopub.status.idle":"2021-12-14T21:46:47.440191Z","shell.execute_reply.started":"2021-12-14T21:46:47.298899Z","shell.execute_reply":"2021-12-14T21:46:47.439315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_pff[['kickDirectionIntended','kickDirectionActual']]\n\nkickoff_pff_direction_actual = kickoff_pff.loc[kickoff_pff['kickDirectionIntended'] != kickoff_pff['kickDirectionActual']][['kickDirectionIntended','kickDirectionActual','playId']]\n\n\nkickoff_pff_direction_actual_aggr = kickoff_pff_direction_actual.groupby(['kickDirectionIntended','kickDirectionActual']).nunique().reset_index()\n\nkickoff_pff_direction_actual_aggr['IntendedActuall'] = kickoff_pff_direction_actual_aggr['kickDirectionIntended'] + kickoff_pff_direction_actual_aggr['kickDirectionActual']\n\nfig = px.bar(kickoff_pff_direction_actual_aggr, \n             x='IntendedActuall', \n             y='playId',\n             labels={'IntendedActuall':'kick Direction against Actual',\n                   'playId':'Number of kickoffs'}\n            )\nfig.update_layout(title_text='Number of kickoffs per kick Direction vs. Actual')\n\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:47.441629Z","iopub.execute_input":"2021-12-14T21:46:47.442232Z","iopub.status.idle":"2021-12-14T21:46:47.527807Z","shell.execute_reply.started":"2021-12-14T21:46:47.442172Z","shell.execute_reply":"2021-12-14T21:46:47.526764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Does long approach run results in a long kick length?","metadata":{}},{"cell_type":"code","source":"kickoff_tracking_2020['uniqueId'] = kickoff_tracking_2020['gameId'].astype(str) + kickoff_tracking_2020['playId'].astype(str)\n\nkickoff_tracking_distance_2020 = kickoff_tracking_2020[['gameId',\n                                                       'playId',\n                                                        'time',\n                                                       'kickerId',\n                                                       'kickLength',\n                                                       'x', \n                                                        'y', \n                                                        's', \n                                                        'a', \n                                                        'dis', \n                                                        'o', \n                                                        'dir',\n                                                        'event', \n                                                        'nflId', \n                                                        'displayName',\n                                                       'playDirection',\n                                                       'uniqueId']]\nkickoff_tracking_distance_2020 = kickoff_tracking_distance_2020.loc[(kickoff_tracking_distance_2020['displayName'] != 'football') \n                                                                    & (kickoff_tracking_distance_2020['kickerId'] == kickoff_tracking_distance_2020['nflId'])]\nkickoff_tracking_distance_2020 = kickoff_tracking_distance_2020[kickoff_tracking_distance_2020['kickLength'].notna()]\nkickoff_events = [\n                    'kickoff',\n                  'onside_kick',\n                  'autoevent_kickoff',\n                  'free_kick',\n                  'kickoff_play'\n                 ]\nkickoff_tracking_2020_kicks = kickoff_tracking_distance_2020.loc[kickoff_tracking_distance_2020['event'].isin(kickoff_events)]\nunique_id_kicks = kickoff_tracking_2020_kicks['uniqueId'].unique()\n\n# free_kick and kickoff_play have high correlations between distance of approach run and the length of a kickoff length\n# what is the difference between a free kick and ki","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:46:47.529771Z","iopub.execute_input":"2021-12-14T21:46:47.530128Z","iopub.status.idle":"2021-12-14T21:47:02.491426Z","shell.execute_reply.started":"2021-12-14T21:46:47.530083Z","shell.execute_reply":"2021-12-14T21:47:02.490405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_tracking_2020_kicks.groupby(['event']).count()","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:47:02.492580Z","iopub.execute_input":"2021-12-14T21:47:02.492796Z","iopub.status.idle":"2021-12-14T21:47:02.518732Z","shell.execute_reply.started":"2021-12-14T21:47:02.492770Z","shell.execute_reply":"2021-12-14T21:47:02.517823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_tracking_2020_kicks.groupby(['event']).count()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:47:02.520200Z","iopub.execute_input":"2021-12-14T21:47:02.520486Z","iopub.status.idle":"2021-12-14T21:47:02.544806Z","shell.execute_reply.started":"2021-12-14T21:47:02.520455Z","shell.execute_reply":"2021-12-14T21:47:02.544206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# shorter approach run but larger kick space\nkickoff_tracking_2020_kicks.groupby(['event']).sum()['dis'] / kickoff_tracking_2020_kicks.groupby(['event']).count()['uniqueId'] ","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:22:35.064076Z","iopub.execute_input":"2021-12-14T22:22:35.064398Z","iopub.status.idle":"2021-12-14T22:22:35.091103Z","shell.execute_reply.started":"2021-12-14T22:22:35.064363Z","shell.execute_reply":"2021-12-14T22:22:35.090244Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"distance_list = []\nkick_length_list = []\ndata_list = []\nfor uniqueId in unique_id_kicks:\n        \n        dataset = kickoff_tracking_distance_2020.loc[kickoff_tracking_distance_2020['uniqueId'] == uniqueId]\n        #kicker_ball_data = dataset.loc[(dataset['kickerId'] == dataset['nflId'])]\n        kickoff_time = dataset.loc[dataset['event'].isin(kickoff_events)]['time'].iloc[0]\n        kicker_ball_data_pre_kickoff = dataset.loc[dataset['time'] <= kickoff_time]\n        kicker_ball_data_pre_kickoff = kicker_ball_data_pre_kickoff.sort_values(by = 'time')\n        data_list.append(kicker_ball_data_pre_kickoff)\n        # we have dis!!\n        #kicker_ball_data_pre_kickoff['x2'] = kicker_ball_data_pre_kickoff['x'].shift(-1)\n        #kicker_ball_data_pre_kickoff['y2'] = kicker_ball_data_pre_kickoff['y'].shift(-1)\n        kick_length = kicker_ball_data_pre_kickoff['kickLength'].iloc[0]\n        #kicker_ball_data_pre_kickoff = kicker_ball_data_pre_kickoff.dropna()\n\n        #kicker_ball_data_pre_kickoff['distance_moving'] =((kicker_ball_data_pre_kickoff['x2'] - kicker_ball_data_pre_kickoff['x']) ** 2 + (kicker_ball_data_pre_kickoff['y2'] - kicker_ball_data_pre_kickoff['y']) ** 2) ** 0.5\n        approach_run_distance = kicker_ball_data_pre_kickoff['dis'].sum()\n        distance_list.append(approach_run_distance)\n        kick_length_list.append(kick_length)\n\n\nfrom scipy import stats\n\ncorrelation, p_value = stats.pearsonr(distance_list, kick_length_list)\n\n\nprint(correlation, p_value)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:47:02.545877Z","iopub.execute_input":"2021-12-14T21:47:02.546549Z","iopub.status.idle":"2021-12-14T21:48:37.933917Z","shell.execute_reply.started":"2021-12-14T21:47:02.546505Z","shell.execute_reply":"2021-12-14T21:48:37.932730Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.scatter(x=distance_list, y=kick_length_list, trendline=\"ols\")\nfig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:48:37.935563Z","iopub.execute_input":"2021-12-14T21:48:37.935992Z","iopub.status.idle":"2021-12-14T21:48:38.042318Z","shell.execute_reply.started":"2021-12-14T21:48:37.935944Z","shell.execute_reply":"2021-12-14T21:48:38.041308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# distance between the player and the ball when it is kicked","metadata":{}},{"cell_type":"code","source":"kickoff_tracking_kicked_distance_2020 = kickoff_tracking_2020.loc[(kickoff_tracking_2020['displayName'] == 'football') | (kickoff_tracking_2020['kickerId'] == kickoff_tracking_2020['nflId'])]","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:56:39.022560Z","iopub.execute_input":"2021-12-14T21:56:39.022978Z","iopub.status.idle":"2021-12-14T21:56:39.887224Z","shell.execute_reply.started":"2021-12-14T21:56:39.022947Z","shell.execute_reply":"2021-12-14T21:56:39.886546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_tracking_kicked_distance_2020['uniqueId'] = kickoff_tracking_kicked_distance_2020['gameId'].astype(str) + kickoff_tracking_kicked_distance_2020['playId'].astype(str)","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:56:40.531538Z","iopub.execute_input":"2021-12-14T21:56:40.531962Z","iopub.status.idle":"2021-12-14T21:56:41.704855Z","shell.execute_reply.started":"2021-12-14T21:56:40.531931Z","shell.execute_reply":"2021-12-14T21:56:41.703807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_tracking_kicked_distance_2020 = kickoff_tracking_kicked_distance_2020[['uniqueId','event','time','kickerId','displayName','x','y','kickLength']]\n\nkickoff_events = [\n                    'kickoff',\n                  'onside_kick',\n                  'autoevent_kickoff',\n                  'free_kick',\n                  'kickoff_play'\n                 ]","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:06:30.075195Z","iopub.execute_input":"2021-12-14T22:06:30.075764Z","iopub.status.idle":"2021-12-14T22:06:30.109683Z","shell.execute_reply.started":"2021-12-14T22:06:30.075718Z","shell.execute_reply":"2021-12-14T22:06:30.108743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_tracking_kicked_distance_event_2020 = kickoff_tracking_kicked_distance_2020.loc[kickoff_tracking_kicked_distance_2020['event'].isin(kickoff_events)]\n\nkickoff_tracking_kicked_distance_event_2020['x2'] = kickoff_tracking_kicked_distance_event_2020.groupby(['uniqueId'])['x'].shift(-1)\nkickoff_tracking_kicked_distance_event_2020['y2'] = kickoff_tracking_kicked_distance_event_2020.groupby(['uniqueId'])['y'].shift(-1)","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:06:30.111209Z","iopub.execute_input":"2021-12-14T22:06:30.111455Z","iopub.status.idle":"2021-12-14T22:06:30.148613Z","shell.execute_reply.started":"2021-12-14T22:06:30.111425Z","shell.execute_reply":"2021-12-14T22:06:30.147665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_tracking_kicked_distance_event_2020 = kickoff_tracking_kicked_distance_event_2020.dropna()\nkickoff_tracking_kicked_distance_event_2020['distance'] =((kickoff_tracking_kicked_distance_event_2020['x2'] - kickoff_tracking_kicked_distance_event_2020['x']) ** 2 + (kickoff_tracking_kicked_distance_event_2020['y2'] - kickoff_tracking_kicked_distance_event_2020['y']) ** 2) ** 0.5\nkickoff_tracking_kicked_distance_event_2020","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:06:30.149906Z","iopub.execute_input":"2021-12-14T22:06:30.150174Z","iopub.status.idle":"2021-12-14T22:06:30.190798Z","shell.execute_reply.started":"2021-12-14T22:06:30.150143Z","shell.execute_reply":"2021-12-14T22:06:30.190063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"correlation, p_value = stats.pearsonr(kickoff_tracking_kicked_distance_event_2020['distance'], \n                                      kickoff_tracking_kicked_distance_event_2020['kickLength'])\n\n\nprint(correlation, p_value)","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:06:30.192460Z","iopub.execute_input":"2021-12-14T22:06:30.192864Z","iopub.status.idle":"2021-12-14T22:06:30.199928Z","shell.execute_reply.started":"2021-12-14T22:06:30.192830Z","shell.execute_reply":"2021-12-14T22:06:30.198967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.scatter(x=kickoff_tracking_kicked_distance_event_2020['distance'], y=kickoff_tracking_kicked_distance_event_2020['kickLength'], trendline=\"ols\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:06:33.959199Z","iopub.execute_input":"2021-12-14T22:06:33.959507Z","iopub.status.idle":"2021-12-14T22:06:34.152922Z","shell.execute_reply.started":"2021-12-14T22:06:33.959476Z","shell.execute_reply":"2021-12-14T22:06:34.152272Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.box(kickoff_tracking_kicked_distance_event_2020, \n             x=\"event\", \n             y=\"distance\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:06:35.122874Z","iopub.execute_input":"2021-12-14T22:06:35.124035Z","iopub.status.idle":"2021-12-14T22:06:35.252630Z","shell.execute_reply.started":"2021-12-14T22:06:35.123968Z","shell.execute_reply":"2021-12-14T22:06:35.251937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_distance_ball = kickoff_tracking_kicked_distance_event_2020.loc[kickoff_tracking_kicked_distance_event_2020['event'].isin(['kickoff','autoevent_kickoff'])]\nonsidekick_distance_ball = kickoff_tracking_kicked_distance_event_2020.loc[kickoff_tracking_kicked_distance_event_2020['event'].isin(['onside_kick'])]","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:10:12.984843Z","iopub.execute_input":"2021-12-14T22:10:12.985401Z","iopub.status.idle":"2021-12-14T22:10:12.994126Z","shell.execute_reply.started":"2021-12-14T22:10:12.985333Z","shell.execute_reply":"2021-12-14T22:10:12.993343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"onsidekick_distance_ball['distance']","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:09:43.631591Z","iopub.execute_input":"2021-12-14T22:09:43.632252Z","iopub.status.idle":"2021-12-14T22:09:43.640100Z","shell.execute_reply.started":"2021-12-14T22:09:43.632210Z","shell.execute_reply":"2021-12-14T22:09:43.639436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"stats.ttest_ind(kickoff_distance_ball['distance'], onsidekick_distance_ball['distance'])","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:10:21.319949Z","iopub.execute_input":"2021-12-14T22:10:21.320260Z","iopub.status.idle":"2021-12-14T22:10:21.332616Z","shell.execute_reply.started":"2021-12-14T22:10:21.320226Z","shell.execute_reply":"2021-12-14T22:10:21.331616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickoff_distance_ball['distance'].mean()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:11:12.362763Z","iopub.execute_input":"2021-12-14T22:11:12.363579Z","iopub.status.idle":"2021-12-14T22:11:12.372127Z","shell.execute_reply.started":"2021-12-14T22:11:12.363527Z","shell.execute_reply":"2021-12-14T22:11:12.371353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"onsidekick_distance_ball['distance'].mean()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T22:11:20.939456Z","iopub.execute_input":"2021-12-14T22:11:20.940116Z","iopub.status.idle":"2021-12-14T22:11:20.947576Z","shell.execute_reply.started":"2021-12-14T22:11:20.940065Z","shell.execute_reply":"2021-12-14T22:11:20.946769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Onside kick has much smaller approach run than kickoffs, which results in a shorter kick length.  ","metadata":{}},{"cell_type":"code","source":"merged_dataset = pd.concat(data_list)\n\nevent_aggr = pd.DataFrame()\nevent_aggr[['uniqueId','dis']] = merged_dataset.groupby(['uniqueId']).sum().reset_index()[['uniqueId','dis']]\nevent_aggr['kickLength'] = merged_dataset.groupby(['uniqueId']).mean().reset_index()[['kickLength']]\nevent_aggr['event'] = merged_dataset.groupby(['uniqueId']).max().reset_index()[['event']]\nevent_aggr.groupby(['event']).count()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:48:38.482490Z","iopub.execute_input":"2021-12-14T21:48:38.482703Z","iopub.status.idle":"2021-12-14T21:48:40.951227Z","shell.execute_reply.started":"2021-12-14T21:48:38.482677Z","shell.execute_reply":"2021-12-14T21:48:40.950291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"event_aggr.groupby(['event']).median()","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:48:40.952635Z","iopub.execute_input":"2021-12-14T21:48:40.952891Z","iopub.status.idle":"2021-12-14T21:48:40.967621Z","shell.execute_reply.started":"2021-12-14T21:48:40.952852Z","shell.execute_reply":"2021-12-14T21:48:40.966908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 5 yardline should be a determining line\nevent_aggr.groupby(['event']).quantile(.9)","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:48:40.969120Z","iopub.execute_input":"2021-12-14T21:48:40.969592Z","iopub.status.idle":"2021-12-14T21:48:40.987438Z","shell.execute_reply.started":"2021-12-14T21:48:40.969557Z","shell.execute_reply":"2021-12-14T21:48:40.986482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Does the direction of a kicker's body tells us more of in which way the ball will fly to?","metadata":{}},{"cell_type":"code","source":"kickoff_tracking_2020_dir = kickoff_tracking_2020[['uniqueId','time', 'kickerId', 'o', 'dir','event', 'nflId','playDirection']]\n\n# PFF Scouting data\n# kickDirectionIntended\n# kickDirectionActual\n\npff['uniqueId'] = pff['gameId'].astype(str) + pff['playId'].astype(str)\n\npff_dir = pff[['uniqueId','kickDirectionIntended','kickDirectionActual']]\n\nkickoff_pff_dir = pd.merge(\n    kickoff_tracking_2020_dir,\n    pff_dir,\n    how=\"inner\",\n    left_on=[\"uniqueId\"],\n    right_on=[\"uniqueId\"],\n    sort=True,\n    suffixes=(\"_x\", \"_y\"),\n    copy=True,\n    indicator=False,\n    validate=None,\n)\n\nkickoff_pff_dir_kick_event = kickoff_pff_dir.loc[(kickoff_pff_dir['kickerId'] == kickoff_pff_dir['nflId']) &\n                   (kickoff_pff_dir['event'].isin(kickoff_events))]\n\n# right more if want right\nkickoff_pff_dir_kick_event.groupby(['playDirection',\n                                    'kickDirectionActual']).median().reset_index()[['playDirection',\n                                                                                   'kickDirectionActual',\n                                                                                   'o',\n                                                                                   'dir']]","metadata":{"execution":{"iopub.status.busy":"2021-12-14T21:48:40.988910Z","iopub.execute_input":"2021-12-14T21:48:40.989388Z","iopub.status.idle":"2021-12-14T21:48:44.883151Z","shell.execute_reply.started":"2021-12-14T21:48:40.989354Z","shell.execute_reply":"2021-12-14T21:48:44.882140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# why f","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:48:44.884324Z","iopub.execute_input":"2021-12-14T21:48:44.884553Z","iopub.status.idle":"2021-12-14T21:48:44.888258Z","shell.execute_reply.started":"2021-12-14T21:48:44.884523Z","shell.execute_reply":"2021-12-14T21:48:44.887345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# time\n# entity: player + ball\n# x\n# y\n# dir\n# o\n# acc\n# event - kick the ball, ball is catched, ball is out of bound/end, ball touches the ground","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:48:44.889832Z","iopub.execute_input":"2021-12-14T21:48:44.890414Z","iopub.status.idle":"2021-12-14T21:48:44.900934Z","shell.execute_reply.started":"2021-12-14T21:48:44.890365Z","shell.execute_reply":"2021-12-14T21:48:44.900290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# playId 39\n# gameId 2020091000\n\n\"\"\"\nplay_2020091000_39 = kickoff_tracking_2020.loc[(kickoff_tracking_2020['playId'] == 4182) & \n                                    (kickoff_tracking_2020['gameId'] == 2021010315)]\n\nplay_2020091000_39 = play_2020091000_39[['gameId',\n                   'playId',\n                   'kickerId',\n                    'nflId',\n                    'displayName',\n                    'event',                     \n                   'time',\n                   'x',\n                   'y',\n                   's',\n                   'a',\n                   'dis',\n                   'o',\n                   'dir',\n                   'playDirection']]\n\nplay_2020091000_39 = play_2020091000_39.loc[(play_2020091000_39['nflId'] == play_2020091000_39['kickerId']) | (play_2020091000_39['displayName'] == 'football')]\n\nkickoffTime = list(play_2020091000_39.loc[(play_2020091000_39['event'].isin(['kickoff','onside_kick'])) & (play_2020091000_39['displayName'] == 'football')][['time']].iloc[0])[0]\n\nplay_2020091000_39 = play_2020091000_39.loc[play_2020091000_39['time'] <= kickoffTime]\n\n\n\nplayer_2020091000_39 = play_2020091000_39.loc[play_2020091000_39['displayName'] != 'football']\nball_2020091000_39 = play_2020091000_39.loc[(play_2020091000_39['displayName'] == 'football') & (play_2020091000_39['time'] == kickoffTime)]\n\nfig = go.Figure()\n\n# Add traces\n\nfig.add_trace(go.Scatter(x=player_2020091000_39['x'], \n                         y=player_2020091000_39['y'],\n                    mode='lines+markers',\n                         text = player_2020091000_39['displayName']\n                        #marker=dict(size=player_2020091000_39['s'] * 20)\n                        ))\n\nfig.add_trace(go.Scatter(x=ball_2020091000_39['x'], \n                         y=ball_2020091000_39['y'],\n                    mode='markers',\n                    #name='lines+markers',\n                        text = ball_2020091000_39['displayName']))\n\n\n\nfig.show()\n\"\"\"","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-14T21:48:44.902525Z","iopub.execute_input":"2021-12-14T21:48:44.903050Z","iopub.status.idle":"2021-12-14T21:48:44.917284Z","shell.execute_reply.started":"2021-12-14T21:48:44.902988Z","shell.execute_reply":"2021-12-14T21:48:44.916611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}