{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":60305,"databundleVersionId":6654553,"sourceType":"competition"}],"dockerImageVersionId":30017,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<h1><center>NFL Big Data Bowl EDA </center></h1>","metadata":{}},{"cell_type":"markdown","source":"# NFL Player Performance Metrics\n\n## Offensive Metrics\n\n1. **Rushing Yards:**\n   - Total yards gained by a player while carrying the ball.\n\n2. **Receiving Yards:**\n   - Total yards gained by a player through receptions.\n\n3. **Touchdowns:**\n   - **Rushing Touchdowns:** The number of times a player scores a touchdown while carrying the ball.\n   - **Receiving Touchdowns:** The number of times a player scores a touchdown through receptions.\n\n4. **Passing Stats:**\n   - **Completion Percentage:** The percentage of completed passes by a quarterback.\n   - **Passing Yards:** Total yards gained by a quarterback through completed passes.\n\n## Defensive Metrics\n\n5. **Interceptions:**\n   - The number of times a quarterback throws an interception, indicating a turnover.\n\n6. **Tackles:**\n   - The total number of tackles made by a defensive player, indicating their involvement in stopping the opposing team's offense.\n\n7. **Sacks:**\n   - The number of times a defensive player tackles the quarterback behind the line of scrimmage.\n\n8. **Interceptions and Takeaways:**\n   - The number of times a defensive player intercepts the ball or forces a fumble, leading to a change in possession.\n\n## Special Teams Metrics\n\n9. **Punting and Kicking:**\n   - **Punting Average:** Average distance per punt for punters.\n   - **Field Goal Percentage:** The percentage of successful field goals made by kickers.\n\n## Team Performance Metrics\n\n10. **Time of Possession:**\n    - The amount of time a team holds the ball, indicating their control of the game.\n\n11. **Third-Down Conversion Rate:**\n    - The percentage of successful third-down plays, reflecting a team's ability to sustain drives.\n\n12. **Red Zone Efficiency:**\n    - The percentage of trips into the opponent's red zone resulting in touchdowns, indicating a team's effectiveness in scoring when close to the goal line.\n\n## Advanced Metrics\n\n13. **Player Efficiency Ratings:**\n    - Various advanced metrics that condense a player's overall performance into a single numerical value.\n\nRemember to consider these metrics in context and use a combination of statistics for a comprehensive analysis of a player's and team's performance.\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-12-26T11:36:45.320771Z","iopub.execute_input":"2023-12-26T11:36:45.321164Z","iopub.status.idle":"2023-12-26T11:36:46.172040Z","shell.execute_reply.started":"2023-12-26T11:36:45.321129Z","shell.execute_reply":"2023-12-26T11:36:46.171044Z"}}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt\n\nplt.style.use('fivethirtyeight')","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:42.039024Z","iopub.execute_input":"2024-01-07T05:17:42.039451Z","iopub.status.idle":"2024-01-07T05:17:43.120169Z","shell.execute_reply.started":"2024-01-07T05:17:42.039409Z","shell.execute_reply":"2024-01-07T05:17:43.118838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### **Game data:** The games.csv contains the teams playing in each game. The key variable is gameId.\n\n* **gameId:** Game identifier, unique (numeric)\n\n* **gameDate:** Game Date (time, mm/dd/yyyy)\n\n* **gameTimeEastern:** Start time of game (time, HH:MM:SS, EST)\n\n* **homeTeamAbbr:** Home team three-letter code (text)\n\n* **visitorTeamAbbr:** Visiting team three-letter code (text)\n\n* **week:** Week of game (numeric)","metadata":{}},{"cell_type":"code","source":"games = pd.read_csv('../input/nfl-big-data-bowl-2024/games.csv')\ngames","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.122740Z","iopub.execute_input":"2024-01-07T05:17:43.123159Z","iopub.status.idle":"2024-01-07T05:17:43.172178Z","shell.execute_reply.started":"2024-01-07T05:17:43.123121Z","shell.execute_reply":"2024-01-07T05:17:43.171198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles = pd.read_csv('../input/nfl-big-data-bowl-2024/tackles.csv')\ntackles","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.173556Z","iopub.execute_input":"2024-01-07T05:17:43.173922Z","iopub.status.idle":"2024-01-07T05:17:43.219027Z","shell.execute_reply.started":"2024-01-07T05:17:43.173885Z","shell.execute_reply":"2024-01-07T05:17:43.217922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Function for Downcast","metadata":{}},{"cell_type":"markdown","source":"Downcast is a great skill to compress data size which helps to save memory.","metadata":{}},{"cell_type":"code","source":"def downcast(df, verbose=True):\n    start_mem = df.memory_usage().sum() / 1024**2\n    for col in df.columns:\n        dtype_name = df[col].dtype.name\n        if dtype_name == 'object':\n            pass\n        elif dtype_name == 'bool':\n            df[col] = df[col].astype('int8')\n        elif dtype_name.startswith('int') or (df[col].round() == df[col]).all():\n            df[col] = pd.to_numeric(df[col], downcast='integer')\n        else:\n            df[col] = pd.to_numeric(df[col], downcast='float')\n    end_mem = df.memory_usage().sum() / 1024**2\n    if verbose:\n        print('{:.1f}% Compressed'.format(100 * (start_mem - end_mem) / start_mem))\n    \n    return df","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.220707Z","iopub.execute_input":"2024-01-07T05:17:43.221187Z","iopub.status.idle":"2024-01-07T05:17:43.235388Z","shell.execute_reply.started":"2024-01-07T05:17:43.221149Z","shell.execute_reply":"2024-01-07T05:17:43.233834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"games = downcast(games)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.241639Z","iopub.execute_input":"2024-01-07T05:17:43.242249Z","iopub.status.idle":"2024-01-07T05:17:43.262860Z","shell.execute_reply.started":"2024-01-07T05:17:43.242193Z","shell.execute_reply":"2024-01-07T05:17:43.261218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles = downcast(tackles)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.267668Z","iopub.execute_input":"2024-01-07T05:17:43.268331Z","iopub.status.idle":"2024-01-07T05:17:43.289499Z","shell.execute_reply.started":"2024-01-07T05:17:43.268266Z","shell.execute_reply":"2024-01-07T05:17:43.288220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Function for making feature summary ","metadata":{}},{"cell_type":"code","source":"def resumetable(df):\n    print(f'Shape : {df.shape}')\n    summary = pd.DataFrame(df.dtypes, columns=['Data Type'])\n    summary = summary.reset_index()\n    summary = summary.rename(columns={'index': 'Feature'})\n    summary['Num of null'] = df.isnull().sum().values\n    summary['Num of unique'] = df.nunique().values\n    summary['First value'] = df.loc[0].values\n    summary['Second value'] = df.loc[1].values\n    summary['Third value'] = df.loc[2].values\n    return summary\n\nresumetable(games)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.291384Z","iopub.execute_input":"2024-01-07T05:17:43.291880Z","iopub.status.idle":"2024-01-07T05:17:43.336213Z","shell.execute_reply.started":"2024-01-07T05:17:43.291829Z","shell.execute_reply":"2024-01-07T05:17:43.335030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resumetable(tackles)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.338027Z","iopub.execute_input":"2024-01-07T05:17:43.338501Z","iopub.status.idle":"2024-01-07T05:17:43.369300Z","shell.execute_reply.started":"2024-01-07T05:17:43.338454Z","shell.execute_reply":"2024-01-07T05:17:43.368178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Function for writing percent at the top of the bar graph","metadata":{}},{"cell_type":"code","source":"def write_percent(ax, total_size):\n    '''Traverse the figure object and display the ratio at the top of the bar graph.'''\n    for patch in ax.patches:\n        height = patch.get_height() # Figure height (number of data)\n        width = patch.get_width() # Figure width\n        left_coord = patch.get_x() # The x-axis position on the left edge of the figure\n        percent = height/total_size*100 # percent\n        \n        # Type text in the (x, y) coordinates\n        ax.text(x=left_coord + width/2.0, # x-axis position\n                y=height + total_size*0.001, # y-axis position\n                s=f'{percent:1.1f}%', # Text\n                ha='center') # in the middle","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.371137Z","iopub.execute_input":"2024-01-07T05:17:43.371623Z","iopub.status.idle":"2024-01-07T05:17:43.382084Z","shell.execute_reply.started":"2024-01-07T05:17:43.371572Z","shell.execute_reply":"2024-01-07T05:17:43.380170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Make derivative features (month, day, hour)","metadata":{}},{"cell_type":"code","source":"games['month'] = games['gameDate'].apply(lambda x: int(x.split('/')[0]))\ngames['day'] = games['gameDate'].apply(lambda x: int(x.split('/')[1]))\ngames['hour'] = games['gameTimeEastern'].apply(lambda x: int(x.split(':')[0]))","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.384091Z","iopub.execute_input":"2024-01-07T05:17:43.384502Z","iopub.status.idle":"2024-01-07T05:17:43.401550Z","shell.execute_reply.started":"2024-01-07T05:17:43.384463Z","shell.execute_reply":"2024-01-07T05:17:43.400402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Visualization","metadata":{}},{"cell_type":"code","source":"mpl.rc('font', size=15) # Set font size\nplt.figure(figsize=(7, 6)) # Set figure size\n\nax = sns.countplot(x='season', data=games)\nwrite_percent(ax, len(games)) \nax.set_title('Number of games for season');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.403294Z","iopub.execute_input":"2024-01-07T05:17:43.403656Z","iopub.status.idle":"2024-01-07T05:17:43.606459Z","shell.execute_reply.started":"2024-01-07T05:17:43.403607Z","shell.execute_reply":"2024-01-07T05:17:43.605457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### the number of games increase and decrease","metadata":{}},{"cell_type":"code","source":"mpl.rc('font', size=15)\nplt.figure(figsize=(8, 6))\n\nax = sns.countplot(x='month', data=games)\nwrite_percent(ax, len(games))\nax.set_title('Number of games for month');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.607960Z","iopub.execute_input":"2024-01-07T05:17:43.608321Z","iopub.status.idle":"2024-01-07T05:17:43.781595Z","shell.execute_reply.started":"2024-01-07T05:17:43.608288Z","shell.execute_reply":"2024-01-07T05:17:43.780142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=12) \nplt.figure(figsize=(15, 7))\n\nax = sns.countplot(x='day', data=games)\nwrite_percent(ax, len(games))\nax.set_title('Number of games for day');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:43.784140Z","iopub.execute_input":"2024-01-07T05:17:43.784730Z","iopub.status.idle":"2024-01-07T05:17:44.243886Z","shell.execute_reply.started":"2024-01-07T05:17:43.784626Z","shell.execute_reply":"2024-01-07T05:17:44.242591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=12) \nplt.figure(figsize=(15, 7))\n\nax = sns.countplot(x='gameTimeEastern', data=games)\nwrite_percent(ax, len(games))\nax.set_title('Number of games for gameTimeEastern');\nax.tick_params('x', labelrotation=30) # rotate 30 degree of x label","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:44.245966Z","iopub.execute_input":"2024-01-07T05:17:44.246465Z","iopub.status.idle":"2024-01-07T05:17:44.490375Z","shell.execute_reply.started":"2024-01-07T05:17:44.246407Z","shell.execute_reply":"2024-01-07T05:17:44.488726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=12) \nplt.figure(figsize=(15, 7))\n\nax = sns.countplot(x='hour', data=games)\nwrite_percent(ax, len(games))\nax.set_title('Number of games for hour');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:44.492026Z","iopub.execute_input":"2024-01-07T05:17:44.492390Z","iopub.status.idle":"2024-01-07T05:17:44.785652Z","shell.execute_reply.started":"2024-01-07T05:17:44.492356Z","shell.execute_reply":"2024-01-07T05:17:44.784018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=12) \nplt.figure(figsize=(15, 7))\n\nax = sns.countplot(x='week', data=games)\nwrite_percent(ax, len(games))\nax.set_title('Number of games for week');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:44.787292Z","iopub.execute_input":"2024-01-07T05:17:44.787712Z","iopub.status.idle":"2024-01-07T05:17:45.036526Z","shell.execute_reply.started":"2024-01-07T05:17:44.787673Z","shell.execute_reply":"2024-01-07T05:17:45.035474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h2 style='background:transparent; border:0; color:black'><center>2. Player Data<center><h2>","metadata":{}},{"cell_type":"markdown","source":"### **Player data:** The players.csv file contains player-level information from players that participated in any of the tracking data files. The key variable is nflId","metadata":{}},{"cell_type":"code","source":"players = pd.read_csv('../input/nfl-big-data-bowl-2024/players.csv')\nplayers","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.038327Z","iopub.execute_input":"2024-01-07T05:17:45.038713Z","iopub.status.idle":"2024-01-07T05:17:45.078884Z","shell.execute_reply.started":"2024-01-07T05:17:45.038675Z","shell.execute_reply":"2024-01-07T05:17:45.077679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players = downcast(players)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.080504Z","iopub.execute_input":"2024-01-07T05:17:45.080857Z","iopub.status.idle":"2024-01-07T05:17:45.093501Z","shell.execute_reply.started":"2024-01-07T05:17:45.080824Z","shell.execute_reply":"2024-01-07T05:17:45.092534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resumetable(players)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.094969Z","iopub.execute_input":"2024-01-07T05:17:45.095313Z","iopub.status.idle":"2024-01-07T05:17:45.133217Z","shell.execute_reply.started":"2024-01-07T05:17:45.095281Z","shell.execute_reply":"2024-01-07T05:17:45.131914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Convert all heights to feet","metadata":{}},{"cell_type":"code","source":"check = players['height'].str.split('-', expand=True)\n\ncheck.columns = ['first', 'second']\n\ncheck.loc[(check['second'].notnull()), 'first'] = check[check['second'].notnull()]['first'].astype(np.int16) * 12 + check[check['second'].notnull()]['second'].astype(np.int16)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.134912Z","iopub.execute_input":"2024-01-07T05:17:45.135406Z","iopub.status.idle":"2024-01-07T05:17:45.185980Z","shell.execute_reply.started":"2024-01-07T05:17:45.135366Z","shell.execute_reply":"2024-01-07T05:17:45.184542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players['height'] = check['first']\nplayers['height'] = players['height'].astype(np.float32)\nplayers['height'] /= 12\n\nplayers","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.188682Z","iopub.execute_input":"2024-01-07T05:17:45.189072Z","iopub.status.idle":"2024-01-07T05:17:45.217460Z","shell.execute_reply.started":"2024-01-07T05:17:45.189037Z","shell.execute_reply":"2024-01-07T05:17:45.215941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=15) \nplt.figure(figsize=(10, 6))\n\nax = sns.distplot(players['height'], bins=12)\nax.set_title('Height Distribution');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.219405Z","iopub.execute_input":"2024-01-07T05:17:45.219912Z","iopub.status.idle":"2024-01-07T05:17:45.468382Z","shell.execute_reply.started":"2024-01-07T05:17:45.219850Z","shell.execute_reply":"2024-01-07T05:17:45.466920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=15) \nplt.figure(figsize=(10, 6))\n\nax = sns.distplot(players['weight'])\nax.set_title('Weight Distribution');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.470175Z","iopub.execute_input":"2024-01-07T05:17:45.470745Z","iopub.status.idle":"2024-01-07T05:17:45.720175Z","shell.execute_reply.started":"2024-01-07T05:17:45.470637Z","shell.execute_reply":"2024-01-07T05:17:45.718898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"top_players_colleage = players['collegeName'].value_counts()[:20].reset_index()\ntop_players_colleage.columns = ['collageName', 'numberOfPlayers']","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.722112Z","iopub.execute_input":"2024-01-07T05:17:45.722605Z","iopub.status.idle":"2024-01-07T05:17:45.734104Z","shell.execute_reply.started":"2024-01-07T05:17:45.722557Z","shell.execute_reply":"2024-01-07T05:17:45.732704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=10) \nplt.figure(figsize=(15, 12))\n\nax = sns.barplot(x='numberOfPlayers', y='collageName', data=top_players_colleage)\nax.set_title('Number of players for collegeName');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:45.736864Z","iopub.execute_input":"2024-01-07T05:17:45.737465Z","iopub.status.idle":"2024-01-07T05:17:46.113492Z","shell.execute_reply.started":"2024-01-07T05:17:45.737397Z","shell.execute_reply":"2024-01-07T05:17:46.112170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Create birth year feature","metadata":{}},{"cell_type":"code","source":"players['birthYear'] = 0","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:46.115063Z","iopub.execute_input":"2024-01-07T05:17:46.115423Z","iopub.status.idle":"2024-01-07T05:17:46.122276Z","shell.execute_reply.started":"2024-01-07T05:17:46.115389Z","shell.execute_reply":"2024-01-07T05:17:46.121075Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There are NA values in birthDate so that we should drop them","metadata":{}},{"cell_type":"code","source":"players.dropna(subset=['birthDate'], inplace=True)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:46.124128Z","iopub.execute_input":"2024-01-07T05:17:46.125327Z","iopub.status.idle":"2024-01-07T05:17:46.138477Z","shell.execute_reply.started":"2024-01-07T05:17:46.125283Z","shell.execute_reply":"2024-01-07T05:17:46.136965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Extract birth year","metadata":{}},{"cell_type":"code","source":"for idx, row in players.iterrows():\n    if len(row['birthDate'].split('/')) == 3: # ex) 05/17/1994 \n        players.loc[idx, 'birthYear'] = row['birthDate'].split('/')[2]\n        \n    elif len(row['birthDate'].split('-')) == 3: # ex) 1995-05-05\n        players.loc[idx, 'birthYear'] = row['birthDate'].split('-')[0]","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:46.142905Z","iopub.execute_input":"2024-01-07T05:17:46.143387Z","iopub.status.idle":"2024-01-07T05:17:46.743901Z","shell.execute_reply.started":"2024-01-07T05:17:46.143348Z","shell.execute_reply":"2024-01-07T05:17:46.742145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=15) \nplt.figure(figsize=(10, 5))\n\nax = sns.distplot(players['birthYear'], bins=25)\nax.set_title('Players birth year Distribution');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:46.745871Z","iopub.execute_input":"2024-01-07T05:17:46.746241Z","iopub.status.idle":"2024-01-07T05:17:47.028118Z","shell.execute_reply.started":"2024-01-07T05:17:46.746207Z","shell.execute_reply":"2024-01-07T05:17:47.026302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Those born in 1995 are the most common","metadata":{}},{"cell_type":"code","source":"players['birthYear'].min(), players['birthYear'].max()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:47.030500Z","iopub.execute_input":"2024-01-07T05:17:47.030911Z","iopub.status.idle":"2024-01-07T05:17:47.040536Z","shell.execute_reply.started":"2024-01-07T05:17:47.030871Z","shell.execute_reply":"2024-01-07T05:17:47.039225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### The oldest player was born in 1977, and the youngest player was born in 1999","metadata":{}},{"cell_type":"markdown","source":"<a id=\"3\"></a>\n<h2 style='background:transparent; border:0; color:black'><center>3. Play Data<center><h2>","metadata":{}},{"cell_type":"code","source":"plays = pd.read_csv('../input/nfl-big-data-bowl-2024/plays.csv')\n\nplays","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:47.042456Z","iopub.execute_input":"2024-01-07T05:17:47.042934Z","iopub.status.idle":"2024-01-07T05:17:47.258512Z","shell.execute_reply.started":"2024-01-07T05:17:47.042896Z","shell.execute_reply":"2024-01-07T05:17:47.257433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plays = downcast(plays)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:47.260016Z","iopub.execute_input":"2024-01-07T05:17:47.260347Z","iopub.status.idle":"2024-01-07T05:17:47.305190Z","shell.execute_reply.started":"2024-01-07T05:17:47.260315Z","shell.execute_reply":"2024-01-07T05:17:47.303921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resumetable(plays)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:47.307042Z","iopub.execute_input":"2024-01-07T05:17:47.307744Z","iopub.status.idle":"2024-01-07T05:17:47.399917Z","shell.execute_reply.started":"2024-01-07T05:17:47.307648Z","shell.execute_reply":"2024-01-07T05:17:47.398743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### There are lots of null values in `returnerld`, `kickBlockerId`, `penaltyCodes`, `penaltyJerseyNumbers`, `penaltyYards`, `passResult`, `kickReturnYardage` features","metadata":{}},{"cell_type":"code","source":"mpl.rc('font', size=12) \nplt.figure(figsize=(12, 6))\n\nax = sns.countplot(x='quarter', data=plays)\nwrite_percent(ax, len(plays))\nax.set_title('Number of plays of every quarter');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:47.401761Z","iopub.execute_input":"2024-01-07T05:17:47.402109Z","iopub.status.idle":"2024-01-07T05:17:47.590450Z","shell.execute_reply.started":"2024-01-07T05:17:47.402077Z","shell.execute_reply":"2024-01-07T05:17:47.589207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=12) \nplt.figure(figsize=(12, 6))\n\nax = sns.countplot(x='down', data=plays)\nwrite_percent(ax, len(plays))\nax.set_title('Number of plays of every down');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:47.601850Z","iopub.execute_input":"2024-01-07T05:17:47.602258Z","iopub.status.idle":"2024-01-07T05:17:47.795497Z","shell.execute_reply.started":"2024-01-07T05:17:47.602224Z","shell.execute_reply":"2024-01-07T05:17:47.794020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=12) \nplt.figure(figsize=(12, 6))\n\nax = sns.countplot(x='yardsToGo', data=plays)\nax.set_title('Number of plays for every yards to go category');","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:47.797192Z","iopub.execute_input":"2024-01-07T05:17:47.797545Z","iopub.status.idle":"2024-01-07T05:17:48.200151Z","shell.execute_reply.started":"2024-01-07T05:17:47.797512Z","shell.execute_reply":"2024-01-07T05:17:48.198953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=15) \nplt.figure(figsize=(10, 5))\n\nax = sns.distplot(plays['playResult'], bins=25);\nax.set_title('playResult Distribution'); ","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:48.201644Z","iopub.execute_input":"2024-01-07T05:17:48.201992Z","iopub.status.idle":"2024-01-07T05:17:48.483860Z","shell.execute_reply.started":"2024-01-07T05:17:48.201960Z","shell.execute_reply":"2024-01-07T05:17:48.482885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"playResult: Net yards gained by the offense, including penalty yardage (numeric)","metadata":{}},{"cell_type":"code","source":"mpl.rc('font', size=15) \nplt.figure(figsize=(10, 5))\n\nax = sns.distplot(plays['preSnapHomeScore'], bins=12);\nax.set_title('preSnapHomeScore Distribution'); ","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:48.485368Z","iopub.execute_input":"2024-01-07T05:17:48.485761Z","iopub.status.idle":"2024-01-07T05:17:48.831601Z","shell.execute_reply.started":"2024-01-07T05:17:48.485724Z","shell.execute_reply":"2024-01-07T05:17:48.830618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size=15) \nplt.figure(figsize=(10, 5))\n\nax = sns.distplot(plays['preSnapVisitorScore'], bins=12);\nax.set_title('preSnapVisitorScore Distribution'); ","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:48.833627Z","iopub.execute_input":"2024-01-07T05:17:48.834117Z","iopub.status.idle":"2024-01-07T05:17:49.069486Z","shell.execute_reply.started":"2024-01-07T05:17:48.834069Z","shell.execute_reply":"2024-01-07T05:17:49.068286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"preSnapVisitorScore: Visiting team score prior to the play (numeric)","metadata":{}},{"cell_type":"markdown","source":"## Function to create football field\n","metadata":{}},{"cell_type":"markdown","source":"This function is taken from the post created by JARON_MICHAL. See the post [here](https://www.kaggle.com/jaronmichal/tracking-data-visualization)","metadata":{}},{"cell_type":"code","source":"import matplotlib.patches as patches\nfrom matplotlib.patches import Arc\nfrom matplotlib import pyplot as plt\nimport matplotlib.patches as mpatches\n\n# Change size of the figure\nplt.rcParams['figure.figsize'] = [12, 8]\ndef drawPitch(width, height, color=\"w\"):\n    fig = plt.figure()\n    ax = plt.axes(xlim=(-10, width + 30), ylim=(-15, height + 5))\n    plt.axis('off')\n\n    # Grass around pitch\n    rect = patches.Rectangle((-10, -5), width + 40, height + 10, linewidth=1, facecolor='#3f995b', capstyle='round')\n    ax.add_patch(rect)\n    ###################\n\n    # Pitch boundaries\n    rect = plt.Rectangle((0, 0), width + 20, height, ec=color, fc=\"None\", lw=2)\n    ax.add_patch(rect)\n    ###################\n\n    # vertical lines - every 5 yards\n    for i in range(21):\n        plt.plot([10 + 5 * i, 10 + 5 * i], [0, height], c=\"w\", lw=2)\n    ###################\n        \n    # distance markers - every 10 yards\n    for yards in range(10, width, 10):\n        yards_text = yards if yards <= width / 2 else width - yards\n        # top markers\n        plt.text(10 + yards - 2, height - 7.5, yards_text, size=15, c=\"w\", weight=\"bold\")\n        # botoom markers\n        plt.text(10 + yards - 2, 7.5, yards_text, size=15, c=\"w\", weight=\"bold\", rotation=180)\n    ###################\n\n    # yards markers - every yard\n    # bottom markers\n    for x in range(20):\n        for j in range(1, 5):\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [1, 3], color=\"w\", lw=2)\n\n    # top markers\n    for x in range(20):\n        for j in range(1, 5):\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [height - 1, height - 3], color=\"w\", lw=2)\n\n    # middle bottom markers\n    y = (height - 18.5) / 2\n    for x in range(20):\n        for j in range(1, 5):\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [y, y + 2], color=\"w\", lw=2)\n\n    # middle top markers\n    for x in range(20):\n        for j in range(1, 5):\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [height - y, height - y - 2], color=\"w\", lw=2)\n    ###################\n\n    # draw home end zone\n    plt.text(2.5, (height - 15) / 2, \"HOME\", size=30, c=\"w\", weight=\"bold\", rotation=90)\n    rect = plt.Rectangle((0, 0), 10, height, ec=color, fc=\"#0064dc\", lw=2)\n    ax.add_patch(rect)\n\n    # draw away end zone    \n    plt.text(111, (height - 15) / 2, \"AWAY\", size=30, c=\"w\", weight=\"bold\", rotation=-90)\n    rect = plt.Rectangle((width + 10, 0), 10, height, ec=color, fc=\"#c80014\", lw=2)\n    ax.add_patch(rect)\n    ###################\n    \n    # draw extra spot point\n    # left\n    y = (height - 3) / 2\n    plt.plot([10 + 2, 10 + 2], [y, y + 3], c=\"w\", lw=2)\n    \n    # right\n    plt.plot([width + 10 - 2, width + 10 - 2], [y, y + 3], c=\"w\", lw=2)\n    ###################\n    \n    # draw goalpost\n    goal_width = 6 # yards\n    y = (height - goal_width) / 2\n    # left\n    plt.plot([0, 0], [y, y + goal_width], \"-\", c=\"y\", lw=10, ms=20)\n    # right\n    plt.plot([width + 20, width + 20], [y, y + goal_width], \"-\", c=\"y\", lw=10, ms=20)\n    \n    return fig, ax","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-01-07T05:17:49.071386Z","iopub.execute_input":"2024-01-07T05:17:49.071879Z","iopub.status.idle":"2024-01-07T05:17:49.115972Z","shell.execute_reply.started":"2024-01-07T05:17:49.071840Z","shell.execute_reply":"2024-01-07T05:17:49.114515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":" fig, ax = drawPitch(100, 53.3)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:49.117591Z","iopub.execute_input":"2024-01-07T05:17:49.118127Z","iopub.status.idle":"2024-01-07T05:17:49.751093Z","shell.execute_reply.started":"2024-01-07T05:17:49.118076Z","shell.execute_reply":"2024-01-07T05:17:49.750202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Function to create animation","metadata":{}},{"cell_type":"code","source":"# games_ids = {}\n# games_tracking = tracking.groupby(by=[\"gameId\"])\n# for game, data in games_tracking:\n#     games_ids[game] = list(set(data.playId.tolist()))","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:49.752512Z","iopub.execute_input":"2024-01-07T05:17:49.752985Z","iopub.status.idle":"2024-01-07T05:17:49.757287Z","shell.execute_reply.started":"2024-01-07T05:17:49.752945Z","shell.execute_reply":"2024-01-07T05:17:49.756225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def extract_one_game(game_id, play_id, df):\n#     game = df[(df.gameId == game_id) & (df.playId == play_id)]\n#     home = {}\n#     away = {}\n#     balls = []\n    \n#     players = game.sort_values(['frameId'], ascending=True).groupby('nflId')\n#     for id, dx in players:\n#         jerseyNumber = int(dx.jerseyNumber.iloc[0])\n#         if dx.team.iloc[0] == \"home\":\n#             home[jerseyNumber] = list(zip(dx.x.tolist(), dx.y.tolist()))\n#         elif dx.team.iloc[0] == \"away\":\n#             away[jerseyNumber] = list(zip(dx.x.tolist(), dx.y.tolist()))\n\n\n#     ball_df = game.sort_values(['frameId'], ascending=True) \n#     ball_df = ball_df[ball_df.team == \"football\"]\n#     balls = list(zip(ball_df.x.tolist(), ball_df.y.tolist()))\n#     return home, away, balls","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-01-07T05:17:49.758802Z","iopub.execute_input":"2024-01-07T05:17:49.759433Z","iopub.status.idle":"2024-01-07T05:17:49.768568Z","shell.execute_reply.started":"2024-01-07T05:17:49.759376Z","shell.execute_reply":"2024-01-07T05:17:49.767586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from matplotlib import animation\n# from IPython.display import HTML\n# def animate_one_play(game_id, play_id, df):\n#     fig, ax = drawPitch(100, 53.3)\n    \n#     home, away, balls = extract_one_game(game_id, play_id, df)\n\n#     team_left, = ax.plot([], [], 'o', markersize=20, markerfacecolor=\"r\", markeredgewidth=2, markeredgecolor=\"white\", zorder=7)\n#     team_right, = ax.plot([], [], 'o', markersize=20, markerfacecolor=\"b\", markeredgewidth=2, markeredgecolor=\"white\", zorder=7)\n#     ball, = ax.plot([], [], 'o', markersize=10, markerfacecolor=\"black\", markeredgewidth=2, markeredgecolor=\"white\", zorder=7)\n#     drawings = [team_left, team_right, ball]\n\n#     def init():\n#         team_left.set_data([], [])\n#         team_right.set_data([], [])\n#         ball.set_data([], [])\n#         return drawings\n\n#     def draw_teams(i):\n#         X = []\n#         Y = []\n#         for k, v in home.items():\n#             x, y = v[i]\n#             X.append(x)\n#             Y.append(y)\n#         team_left.set_data(X, Y)\n        \n#         X = []\n#         Y = []\n#         for k, v in away.items():\n#             x, y = v[i]\n#             X.append(x)\n#             Y.append(y)\n#         team_right.set_data(X, Y)\n\n#     def animate(i):\n#         draw_teams(i)\n        \n#         x, y = balls[i]\n#         ball.set_data([x, y])\n#         return drawings\n    \n#     # !May take a while!\n#     anim = animation.FuncAnimation(fig, animate, init_func=init,\n#                                    frames=len(balls), interval=100, blit=True)\n\n#     return HTML(anim.to_html5_video())","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-01-07T05:17:49.770262Z","iopub.execute_input":"2024-01-07T05:17:49.770950Z","iopub.status.idle":"2024-01-07T05:17:49.780123Z","shell.execute_reply.started":"2024-01-07T05:17:49.770879Z","shell.execute_reply":"2024-01-07T05:17:49.779005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# animate_one_play(2018123000, 36, tracking)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:49.781852Z","iopub.execute_input":"2024-01-07T05:17:49.782276Z","iopub.status.idle":"2024-01-07T05:17:49.794089Z","shell.execute_reply.started":"2024-01-07T05:17:49.782223Z","shell.execute_reply":"2024-01-07T05:17:49.792990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# tracking data","metadata":{}},{"cell_type":"markdown","source":"# player tracking","metadata":{}},{"cell_type":"code","source":"tracking_data = pd.read_csv('../input/nfl-big-data-bowl-2024/tracking_week_1.csv')\ntracking = downcast(tracking_data)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:49.795445Z","iopub.execute_input":"2024-01-07T05:17:49.795800Z","iopub.status.idle":"2024-01-07T05:17:55.840599Z","shell.execute_reply.started":"2024-01-07T05:17:49.795753Z","shell.execute_reply":"2024-01-07T05:17:55.839358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport plotly.express as px\n\n\n\n# specific gameId and playId for the plot\ngame_id = 2022090800\nplay_id = 56\n\n# Filter data for the chosen game and play\nselected_play_data = tracking[(tracking['gameId'] == game_id) & (tracking['playId'] == play_id)]\n\nplt.figure(figsize=(10, 6))\nplt.scatter(selected_play_data['x'], selected_play_data['y'], c=selected_play_data['s'], cmap='viridis', s=5)\nplt.title('Player Tracking Data - Game {} Play {}'.format(game_id, play_id))\nplt.xlabel('X Position (yards)')\nplt.ylabel('Y Position (yards)')\nplt.colorbar(label='Speed (yards/second)')\nplt.show()\n\nfig = px.scatter(selected_play_data, x='x', y='y', color='s', size='s', title='Player Tracking Data - Game {} Play {}'.format(game_id, play_id),\n                 labels={'x': 'X Position (yards)', 'y': 'Y Position (yards)', 's': 'Speed (yards/second)'},\n                 color_continuous_scale='viridis')\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:55.842276Z","iopub.execute_input":"2024-01-07T05:17:55.842736Z","iopub.status.idle":"2024-01-07T05:17:58.446498Z","shell.execute_reply.started":"2024-01-07T05:17:55.842700Z","shell.execute_reply":"2024-01-07T05:17:58.445084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Filter rows where nflId is not available (corresponds to the ball)\nplayer_data = tracking.dropna(subset=['nflId'])\n\n# Plot player positions at a specific frameId\nframe_to_plot = 10\nframe_data = player_data[player_data['frameId'] == frame_to_plot]\n\n# Get unique teams in the 'club' column\nunique_teams = frame_data['club'].unique()\n\n# color palette for each unique team\nteam_palette = sns.color_palette(\"husl\", n_colors=len(unique_teams))\n\n# Map teams to colors\nteam_color_mapping = dict(zip(unique_teams, team_palette))\n\n# Plot the field\nplt.figure(figsize=(12, 8))\nplt.plot([0, 0, 120, 120, 0], [0, 53.3, 53.3, 0, 0], color='green')\n\n# Plot player positions with colors based on teams\nsns.scatterplot(x='x', y='y', hue='club', data=frame_data, palette=team_color_mapping.values(), s=100)\n\n# Add labels and title\nplt.xlabel('X Position (yards)')\nplt.ylabel('Y Position (yards)')\nplt.title(f'Player Positions at Frame {frame_to_plot}')\n\n# Add legend\nplt.legend(title='Team', loc='upper left')\n\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:17:58.448279Z","iopub.execute_input":"2024-01-07T05:17:58.448648Z","iopub.status.idle":"2024-01-07T05:18:00.119496Z","shell.execute_reply.started":"2024-01-07T05:17:58.448612Z","shell.execute_reply":"2024-01-07T05:18:00.118285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\n\nrows_to_take = 100\n\ncsv_files = [\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_1.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_2.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_3.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_4.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_5.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_6.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_7.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_8.csv',\n    '/kaggle/input/nfl-big-data-bowl-2024/tracking_week_9.csv'\n]\n\n#empty DataFrame to store merged data\nmerged_tracking = pd.DataFrame()\n\nfor csv_file in csv_files:\n    df = pd.read_csv(csv_file)\n    df = df.head(rows_to_take)\n    \n\nmerged_tracking = pd.concat([merged_tracking, df], ignore_index=True)\n\n    ","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:18:00.121205Z","iopub.execute_input":"2024-01-07T05:18:00.121734Z","iopub.status.idle":"2024-01-07T05:18:46.636267Z","shell.execute_reply.started":"2024-01-07T05:18:00.121685Z","shell.execute_reply":"2024-01-07T05:18:46.634811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracking_combined = downcast(merged_tracking)\ntracking_combined.head()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:18:46.638036Z","iopub.execute_input":"2024-01-07T05:18:46.638414Z","iopub.status.idle":"2024-01-07T05:18:46.684375Z","shell.execute_reply.started":"2024-01-07T05:18:46.638377Z","shell.execute_reply":"2024-01-07T05:18:46.682673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"column_names = tracking_combined.columns\nprint(\"Column Names in Merged Data:\")\nprint(column_names)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:18:46.686616Z","iopub.execute_input":"2024-01-07T05:18:46.687051Z","iopub.status.idle":"2024-01-07T05:18:46.694818Z","shell.execute_reply.started":"2024-01-07T05:18:46.687014Z","shell.execute_reply":"2024-01-07T05:18:46.693557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# columns of interest\ncolumns_of_interest = ['gameId', 'playId', 'nflId', 'displayName', 'frameId', 'time',\n                        'jerseyNumber', 'club', 'playDirection', 'x', 'y', 's', 'a',\n                        'dis', 'o', 'dir', 'event']\n\n# Subset DataFrame with selected columns\nselected_data = tracking_combined[columns_of_interest]\n\nprint(\"Information:\")\nprint(selected_data.info())\n\nprint(\"\\nSummary Statistics:\")\nprint(selected_data.describe())\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:18:46.697026Z","iopub.execute_input":"2024-01-07T05:18:46.697418Z","iopub.status.idle":"2024-01-07T05:18:46.763106Z","shell.execute_reply.started":"2024-01-07T05:18:46.697356Z","shell.execute_reply":"2024-01-07T05:18:46.761853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# subset of columns for pair plot\nsubset_columns = ['x', 'y', 's', 'a', 'dis', 'o', 'dir']\nsubset_data = selected_data[subset_columns]\n\nsns.pairplot(subset_data)\nplt.suptitle('# Distribution of numerical columns', y=1.02)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:18:46.764913Z","iopub.execute_input":"2024-01-07T05:18:46.765267Z","iopub.status.idle":"2024-01-07T05:19:01.467520Z","shell.execute_reply.started":"2024-01-07T05:18:46.765236Z","shell.execute_reply":"2024-01-07T05:19:01.466021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"column_names = players.columns\nprint(\"Column Names in Merged Data:\")\nprint(column_names)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:01.469065Z","iopub.execute_input":"2024-01-07T05:19:01.469405Z","iopub.status.idle":"2024-01-07T05:19:01.477671Z","shell.execute_reply.started":"2024-01-07T05:19:01.469372Z","shell.execute_reply":"2024-01-07T05:19:01.475680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# correlation matrix\ncorrelation_matrix = selected_data.corr()\nsns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f')\nplt.title('Tracking - Correlation Matrix')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:01.480297Z","iopub.execute_input":"2024-01-07T05:19:01.480940Z","iopub.status.idle":"2024-01-07T05:19:02.209623Z","shell.execute_reply.started":"2024-01-07T05:19:01.480899Z","shell.execute_reply":"2024-01-07T05:19:02.208254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# player positions\nplt.figure(figsize=(12, 6))\n\n# Scatter plot using 'x' and 'y' columns\nplt.scatter(tracking_combined['x'], tracking_combined['y'], alpha=0.5)\n\nplt.title('Player Positions')\nplt.xlabel('X-axis (Yards)')\nplt.ylabel('Y-axis (Yards)')\nplt.grid(True)\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:02.211073Z","iopub.execute_input":"2024-01-07T05:19:02.211404Z","iopub.status.idle":"2024-01-07T05:19:02.417165Z","shell.execute_reply.started":"2024-01-07T05:19:02.211372Z","shell.execute_reply":"2024-01-07T05:19:02.416168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracking_combined.head()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:02.418975Z","iopub.execute_input":"2024-01-07T05:19:02.419487Z","iopub.status.idle":"2024-01-07T05:19:02.445823Z","shell.execute_reply.started":"2024-01-07T05:19:02.419445Z","shell.execute_reply":"2024-01-07T05:19:02.444551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 6))\n\nplt.scatter(tracking_combined['x'], tracking_combined['y'], alpha=0.5)\n\n# Annotate points with player information\nfor index, player in tracking_combined.iterrows():\n    plt.annotate(player['displayName'], (player['x'], player['y']), fontsize=8, alpha=0.8)\n\nplt.title('Player Tracking on NFL Field')\nplt.xlabel('X-axis (Yards)')\nplt.ylabel('Y-axis (Yards)')\nplt.grid(True)\n\nlegend_text = ['{} - {} ({}, {})'.format(row['displayName'], row['jerseyNumber'], row['club'], row['playDirection'],row['dis']) for _, row in tracking_combined.iterrows()]\nplt.legend(legend_text, loc='upper left', bbox_to_anchor=(1, 1))\n\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:02.447763Z","iopub.execute_input":"2024-01-07T05:19:02.448502Z","iopub.status.idle":"2024-01-07T05:19:03.258183Z","shell.execute_reply.started":"2024-01-07T05:19:02.448448Z","shell.execute_reply":"2024-01-07T05:19:03.256858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import plotly.express as px\nfig = px.scatter(tracking_combined, x='x', y='y', color='club', size='dis', hover_data=['displayName', 'jerseyNumber', 'club', 'playDirection', 'dis','time'])\n\nfig.update_layout(\n    title='Player Tracking on NFL Field',\n    xaxis_title='X-axis (Yards)',\n    yaxis_title='Y-axis (Yards)',\n    legend_title='Club',\n    hovermode='closest',  # closest data on hover\n    showlegend=True,\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:03.260132Z","iopub.execute_input":"2024-01-07T05:19:03.260591Z","iopub.status.idle":"2024-01-07T05:19:03.376116Z","shell.execute_reply.started":"2024-01-07T05:19:03.260533Z","shell.execute_reply":"2024-01-07T05:19:03.374390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Taking longer time to execute so commented it\n# import matplotlib.patches as patches\n# from matplotlib.patches import Arc\n# from matplotlib import pyplot as plt\n# import matplotlib.patches as mpatches\n\n# # Change size of the figure\n# plt.rcParams['figure.figsize'] = [12, 8]\n# def drawPitch(width, height, color=\"w\"):\n#     fig = plt.figure()\n#     ax = plt.axes(xlim=(-10, width + 30), ylim=(-15, height + 5))\n#     plt.axis('off')\n\n#     # Grass around pitch\n#     rect = patches.Rectangle((-10, -5), width + 40, height + 10, linewidth=1, facecolor='#3f995b', capstyle='round')\n#     ax.add_patch(rect)\n\n#     # Pitch boundaries\n#     rect = plt.Rectangle((0, 0), width, height, ec=color, fc=\"None\", lw=2)\n#     ax.add_patch(rect)\n\n#     # Plot player positions using annotate\n#     for i, player in tracking_data.iterrows():\n#         ax.annotate(player['displayName'], (player['x'], player['y']),\n#                     xytext=(5, 5), textcoords='offset points',\n#                     color='red', fontsize=10, ha='center', va='center')\n\n#     # vertical lines - every 5 yards\n#     for i in range(21):\n#         plt.plot([10 + 5 * i, 10 + 5 * i], [0, height], c=\"w\", lw=2)\n#     ###################\n        \n#     # distance markers - every 10 yards\n#     for yards in range(10, width, 10):\n#         yards_text = yards if yards <= width / 2 else width - yards\n#         # top markers\n#         plt.text(10 + yards - 2, height - 7.5, yards_text, size=15, c=\"w\", weight=\"bold\")\n#         # botoom markers\n#         plt.text(10 + yards - 2, 7.5, yards_text, size=15, c=\"w\", weight=\"bold\", rotation=180)\n#     ###################\n\n#     # yards markers - every yard\n#     # bottom markers\n#     for x in range(20):\n#         for j in range(1, 5):\n#             plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [1, 3], color=\"w\", lw=2)\n\n#     # top markers\n#     for x in range(20):\n#         for j in range(1, 5):\n#             plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [height - 1, height - 3], color=\"w\", lw=2)\n\n#     # middle bottom markers\n#     y = (height - 18.5) / 2\n#     for x in range(20):\n#         for j in range(1, 5):\n#             plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [y, y + 2], color=\"w\", lw=2)\n\n#     # middle top markers\n#     for x in range(20):\n#         for j in range(1, 5):\n#             plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [height - y, height - y - 2], color=\"w\", lw=2)\n#     ###################\n\n#     # draw home end zone\n#     plt.text(2.5, (height - 15) / 2, \"HOME\", size=30, c=\"w\", weight=\"bold\", rotation=90)\n#     rect = plt.Rectangle((0, 0), 10, height, ec=color, fc=\"#0064dc\", lw=2)\n#     ax.add_patch(rect)\n\n#     # draw away end zone    \n#     plt.text(111, (height - 15) / 2, \"AWAY\", size=30, c=\"w\", weight=\"bold\", rotation=-90)\n#     rect = plt.Rectangle((width + 10, 0), 10, height, ec=color, fc=\"#c80014\", lw=2)\n#     ax.add_patch(rect)\n#     ###################\n    \n#     # draw extra spot point\n#     # left\n#     y = (height - 3) / 2\n#     plt.plot([10 + 2, 10 + 2], [y, y + 3], c=\"w\", lw=2)\n    \n#     # right\n#     plt.plot([width + 10 - 2, width + 10 - 2], [y, y + 3], c=\"w\", lw=2)\n#     ###################\n    \n#     # draw goalpost\n#     goal_width = 6 # yards\n#     y = (height - goal_width) / 2\n#     # left\n#     plt.plot([0, 0], [y, y + goal_width], \"-\", c=\"y\", lw=10, ms=20)\n#     # right\n#     plt.plot([width + 20, width + 20], [y, y + goal_width], \"-\", c=\"y\", lw=10, ms=20)\n    \n#     return fig, ax\n\n# # Call the function with appropriate width and height\n# drawPitch(120, 80)\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:03.378116Z","iopub.execute_input":"2024-01-07T05:19:03.378493Z","iopub.status.idle":"2024-01-07T05:19:03.386426Z","shell.execute_reply.started":"2024-01-07T05:19:03.378458Z","shell.execute_reply":"2024-01-07T05:19:03.385186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.patches as patches\nfrom matplotlib.patches import Arc\nfrom matplotlib import pyplot as plt\nimport matplotlib.patches as mpatches\n\ndef drawPitch(width, height, color=\"w\"):\n    fig = plt.figure()\n    ax = plt.axes(xlim=(-10, width + 30), ylim=(-15, height + 5))\n    plt.axis('off')\n\n    # Grass around pitch\n    rect = patches.Rectangle((-10, -5), width + 40, height + 10, linewidth=1, facecolor='#3f995b', capstyle='round')\n    ax.add_patch(rect)\n\n    # Pitch boundaries\n    rect = plt.Rectangle((0, 0), width + 20, height, ec=color, fc=\"None\", lw=2)\n    ax.add_patch(rect)\n\n    # Grid lines - every 5 yards\n    for i in range(21):\n        plt.plot([10 + 5 * i, 10 + 5 * i], [0, height], c=\"w\", lw=2)\n\n    # Distance markers - every 10 yards\n    for yards in range(10, width, 10):\n        yards_text = yards if yards <= width / 2 else width - yards\n        # Top markers\n        plt.text(10 + yards - 2, height - 7.5, yards_text, size=15, c=\"w\", weight=\"bold\")\n        # Bottom markers\n        plt.text(10 + yards - 2, 7.5, yards_text, size=15, c=\"w\", weight=\"bold\", rotation=180)\n\n    # Yard markers - every yard\n    for x in range(20):\n        for j in range(1, 5):\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [1, 3], color=\"w\", lw=2)\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [height - 1, height - 3], color=\"w\", lw=2)\n            y = (height - 18.5) / 2\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [y, y + 2], color=\"w\", lw=2)\n            plt.plot([10 + x * 5 + j, 10 + x * 5 + j], [height - y, height - y - 2], color=\"w\", lw=2)\n\n    # Draw home end zone\n    plt.text(2.5, (height - 15) / 2, \"HOME\", size=30, c=\"w\", weight=\"bold\", rotation=90)\n    rect = plt.Rectangle((0, 0), 10, height, ec=color, fc=\"#0064dc\", lw=2)\n    ax.add_patch(rect)\n\n    # Draw away end zone    \n    plt.text(width + 17.5, (height - 15) / 2, \"AWAY\", size=30, c=\"w\", weight=\"bold\", rotation=-90)\n    rect = plt.Rectangle((width + 10, 0), 10, height, ec=color, fc=\"#c80014\", lw=2)\n    ax.add_patch(rect)\n\n    # Draw extra spot points\n    y = (height - 3) / 2\n    plt.plot([10 + 2, 10 + 2], [y, y + 3], c=\"w\", lw=2)\n    plt.plot([width + 10 - 2, width + 10 - 2], [y, y + 3], c=\"w\", lw=2)\n\n    # Draw goalpost\n    goal_width = 6  # yards\n    y = (height - goal_width) / 2\n    plt.plot([0, 0], [y, y + goal_width], \"-\", c=\"y\", lw=10, ms=20)\n    plt.plot([width + 20, width + 20], [y, y + goal_width], \"-\", c=\"y\", lw=10, ms=20)\n\n    # Add center circle\n    center_circle = plt.Circle((width / 2 + 10, height / 2), 8, color='w', fill=False, lw=2)\n    ax.add_patch(center_circle)\n\n    return fig, ax\n\ndrawPitch(100, 50)\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:03.388347Z","iopub.execute_input":"2024-01-07T05:19:03.388868Z","iopub.status.idle":"2024-01-07T05:19:04.270342Z","shell.execute_reply.started":"2024-01-07T05:19:03.388827Z","shell.execute_reply":"2024-01-07T05:19:04.269180Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Draw football pitch\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\n\ndef draw_pitch():\n    # Create a figure and axis\n    fig, ax = plt.subplots()\n\n    # Pitch Outline & Centre Line\n    plt.plot([0, 0, 100, 100, 0], [0, 50, 50, 0, 0], color=\"black\")\n\n    # Left Penalty Area\n    plt.plot([16, 16, 0, 0], [37, 13, 13, 37], color=\"black\")\n\n    # Right Penalty Area\n    plt.plot([100, 84, 84, 100], [37, 37, 13, 13], color=\"black\")\n\n    # Left 6-yard Box\n    plt.plot([0, 6, 6, 0], [28, 28, 22, 22], color=\"black\")\n\n    # Right 6-yard Box\n    plt.plot([100, 94, 94, 100], [28, 28, 22, 22], color=\"black\")\n\n    # Prepare Circles; 10 yard circle at centre and 7 yard circle at penalty spot\n    centre_circle = plt.Circle((50, 25), 8.1, color=\"black\", fill=False)\n    centre_spot = plt.Circle((50, 25), 0.8, color=\"black\")\n    left_penalty_spot = plt.Circle((11, 25), 0.8, color=\"black\")\n    right_penalty_spot = plt.Circle((89, 25), 0.8, color=\"black\")\n\n    # Draw Circles\n    ax.add_patch(centre_circle)\n    ax.add_patch(centre_spot)\n    ax.add_patch(left_penalty_spot)\n    ax.add_patch(right_penalty_spot)\n\n    # Add Arcs\n    left_arc = patches.Arc((11, 25), height=16.2, width=16.2, angle=0, theta1=308, theta2=52, color=\"black\")\n    right_arc = patches.Arc((89, 25), height=16.2, width=16.2, angle=0, theta1=128, theta2=232, color=\"black\")\n\n    # Add Arcs to Axes\n    ax.add_patch(left_arc)\n    ax.add_patch(right_arc)\n\n    # Tidy Axes\n    plt.axis(\"off\")\n\n    # Display the pitch\n    plt.show()\n\n# Call function to draw pitch\ndraw_pitch()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:04.272111Z","iopub.execute_input":"2024-01-07T05:19:04.272567Z","iopub.status.idle":"2024-01-07T05:19:04.383857Z","shell.execute_reply.started":"2024-01-07T05:19:04.272528Z","shell.execute_reply":"2024-01-07T05:19:04.382019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\ndef draw_football_pitch():\n    fig, ax = plt.subplots()\n\n    # Plot the football pitch\n    pitch_length = 100  \n    pitch_width = 50\n    ax.plot([0, 0, pitch_length, pitch_length, 0], [0, pitch_width, pitch_width, 0, 0], color=\"black\")\n\n    # Plot the center circle\n    center_circle = plt.Circle((pitch_length / 2, pitch_width / 2), 9.15, color=\"black\", fill=False)\n    ax.add_patch(center_circle)\n\n    # Set the axis limits\n    ax.set_xlim(0, pitch_length)\n    ax.set_ylim(0, pitch_width)\n\n    # Set the aspect ratio to be equal\n    ax.set_aspect(\"equal\", adjustable=\"box\")\n\n    return fig, ax\n\ndef plot_players(ax, players):\n    # Plot players on the pitch\n    for player in players:\n        x, y = player\n        ax.plot(x, y, 'bo')  # Blue dots for players\n\nif __name__ == \"__main__\":\n    # Create a football pitch\n    fig, ax = draw_football_pitch()\n\n    # Example player positions \n    players = [\n        (10, 10),\n        (30, 20),\n        (50, 30),\n        (70, 40),\n        (90, 10),\n    ]\n\n    plot_players(ax, players)\n\n    plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:04.388097Z","iopub.execute_input":"2024-01-07T05:19:04.389099Z","iopub.status.idle":"2024-01-07T05:19:04.598654Z","shell.execute_reply.started":"2024-01-07T05:19:04.389017Z","shell.execute_reply":"2024-01-07T05:19:04.597544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Tackles","metadata":{}},{"cell_type":"code","source":"# Correlation matrix\ncorrelation_matrix = tackles.corr()\nplt.figure(figsize=(10, 8))\nsns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f', linewidths=0.5)\nplt.title('Correlation Matrix')\nplt.show()\n\n# Visualization of specific columns\nplt.figure(figsize=(12, 6))\nsns.countplot(x='tackle', data=tackles)\nplt.title('Distribution of Tackle')\nplt.xlabel('Tackle')\nplt.ylabel('Count')\nplt.show()\n\nplt.figure(figsize=(12, 6))\nsns.countplot(x='assist', data=tackles)\nplt.title('Distribution of Assist')\nplt.xlabel('Assist')\nplt.ylabel('Count')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:04.600239Z","iopub.execute_input":"2024-01-07T05:19:04.600650Z","iopub.status.idle":"2024-01-07T05:19:05.411821Z","shell.execute_reply.started":"2024-01-07T05:19:04.600603Z","shell.execute_reply":"2024-01-07T05:19:05.410647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Outlier detection and handling\nplt.figure(figsize=(12, 6))\nsns.boxplot(data=tackles[['tackle', 'assist', 'forcedFumble', 'pff_missedTackle']])\nplt.title('Boxplot of Tackle-related Columns')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:05.413650Z","iopub.execute_input":"2024-01-07T05:19:05.414137Z","iopub.status.idle":"2024-01-07T05:19:05.631090Z","shell.execute_reply.started":"2024-01-07T05:19:05.414088Z","shell.execute_reply":"2024-01-07T05:19:05.629934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Feature engineering\n# Total defensive actions combining tackle and assist\ntackles['totalDefensiveActions'] = tackles['tackle'] + tackles['assist']\n\n# Correlation matrix with new feature\ncorrelation_matrix = tackles.corr()\nplt.figure(figsize=(12, 8))\nsns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f', linewidths=0.5)\nplt.title('Correlation Matrix with Engineered Feature')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:05.632553Z","iopub.execute_input":"2024-01-07T05:19:05.632908Z","iopub.status.idle":"2024-01-07T05:19:06.197142Z","shell.execute_reply.started":"2024-01-07T05:19:05.632875Z","shell.execute_reply":"2024-01-07T05:19:06.195943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# correlation matrix\ncorrelation_matrix = selected_data.corr()\nsns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f')\nplt.title('Correlation Matrix for Selected Columns')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:06.198881Z","iopub.execute_input":"2024-01-07T05:19:06.199256Z","iopub.status.idle":"2024-01-07T05:19:06.907866Z","shell.execute_reply.started":"2024-01-07T05:19:06.199221Z","shell.execute_reply":"2024-01-07T05:19:06.906904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players_data = pd.read_csv('../input/nfl-big-data-bowl-2024/players.csv')\nplayers_data\nplayers_data = downcast(players_data)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:06.909106Z","iopub.execute_input":"2024-01-07T05:19:06.909423Z","iopub.status.idle":"2024-01-07T05:19:06.932354Z","shell.execute_reply.started":"2024-01-07T05:19:06.909392Z","shell.execute_reply":"2024-01-07T05:19:06.931278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(players_data['nflId'].dtypes)\nprint(tackles['nflId'].dtypes)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:06.934300Z","iopub.execute_input":"2024-01-07T05:19:06.934742Z","iopub.status.idle":"2024-01-07T05:19:06.942612Z","shell.execute_reply.started":"2024-01-07T05:19:06.934703Z","shell.execute_reply":"2024-01-07T05:19:06.941469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players_tackles = pd.merge(players_data, tackles, on='nflId', how='inner')\n\nplayers_tackles.head()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:06.944944Z","iopub.execute_input":"2024-01-07T05:19:06.945328Z","iopub.status.idle":"2024-01-07T05:19:06.986118Z","shell.execute_reply.started":"2024-01-07T05:19:06.945292Z","shell.execute_reply":"2024-01-07T05:19:06.984891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"column_names = players_tackles.columns\nprint(\"Column Names in Merged Data:\")\nprint(column_names)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:06.987873Z","iopub.execute_input":"2024-01-07T05:19:06.988301Z","iopub.status.idle":"2024-01-07T05:19:06.994465Z","shell.execute_reply.started":"2024-01-07T05:19:06.988263Z","shell.execute_reply":"2024-01-07T05:19:06.993468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### probability of tackles","metadata":{}},{"cell_type":"code","source":"successful_tackles = players_tackles['tackle'] == 1\nmissed_tackles = players_tackles['pff_missedTackle'] == 1\n\ntotal_tackles = successful_tackles.sum() + missed_tackles.sum()\nsuccess_rate = successful_tackles.sum() / total_tackles\n\nprint(f\"Tackle Success Rate: {success_rate * 100:.2f}%\")\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:06.995744Z","iopub.execute_input":"2024-01-07T05:19:06.996142Z","iopub.status.idle":"2024-01-07T05:19:07.011487Z","shell.execute_reply.started":"2024-01-07T05:19:06.996097Z","shell.execute_reply":"2024-01-07T05:19:07.010018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for index, row in players_tackles.iterrows():\n#     print(f\"Name: {row['displayName']}, Position: {row['position']}, Tackles: {row['tackle']}, Assists: {row['assist']}\")\n\n# first 5 players' position, tackles, assists, and names\ncount = 0\nfor index, row in players_tackles.iterrows():\n    print(f\"Name: {row['displayName']}, Position: {row['position']}, Tackles: {row['tackle']}, Assists: {row['assist']}\")\n    count += 1\n    if count >= 10: \n        break\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:07.013439Z","iopub.execute_input":"2024-01-07T05:19:07.013956Z","iopub.status.idle":"2024-01-07T05:19:07.038378Z","shell.execute_reply.started":"2024-01-07T05:19:07.013906Z","shell.execute_reply":"2024-01-07T05:19:07.037226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns_to_plot = ['position', 'displayName', 'tackle', 'assist']\n\nsubset_df = players_tackles[columns_to_plot]\n\nfig, ax = plt.subplots(figsize=(10, 6))\n\nscatter = ax.scatter(subset_df['displayName'], subset_df['tackle'], c=subset_df['assist'], cmap='viridis', s=50)\n\nax.set_xlabel('Player Name')\nax.set_ylabel('Tackles')\nax.set_title('Tackles and Assists by Player')\n\ncbar = plt.colorbar(scatter)\ncbar.set_label('Assists')\n\n# Rotating player names for better visibility\nplt.xticks(rotation=45, ha='right')\n\n# Adjusting text color and style for better visibility\nfor label in ax.get_xticklabels():\n    label.set_color('black')  \n    label.set_fontsize('medium')  \n\n# Adjusting layout for better spacing\nplt.tight_layout()\n\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:07.039511Z","iopub.execute_input":"2024-01-07T05:19:07.039841Z","iopub.status.idle":"2024-01-07T05:19:17.829158Z","shell.execute_reply.started":"2024-01-07T05:19:07.039809Z","shell.execute_reply":"2024-01-07T05:19:17.827109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subset_df = players_tackles[columns_to_plot]\n\n# subplots with 2 rows and 1 column\nfig, axs = plt.subplots(nrows=2, ncols=1, figsize=(10, 8))\n\n# first subplot\nscatter1 = axs[0].scatter(subset_df['displayName'], subset_df['tackle'], c=subset_df['assist'], cmap='viridis', s=50)\naxs[0].set_ylabel('Tackles')\naxs[0].set_title('Tackles and Assists by Player (Top Half)')\n\n# colorbar to the first subplot\ncbar1 = fig.colorbar(scatter1, ax=axs[0])\ncbar1.set_label('Assists')\n\n# second subplot\nscatter2 = axs[1].scatter(subset_df['displayName'], subset_df['tackle'], c=subset_df['assist'], cmap='viridis', s=50)\naxs[1].set_xlabel('Player Name')\naxs[1].set_ylabel('Tackles')\naxs[1].set_title('Tackles and Assists by Player (Bottom Half)')\n\ncbar2 = fig.colorbar(scatter2, ax=axs[1])\ncbar2.set_label('Assists')\n\n# Rotating player names for better visibility in the second subplot\n# axs[1].tick_params(axis='x', rotation=45, rotation_mode='anchor'\naxs[1].tick_params(axis='x', rotation=45)\n\nplt.tight_layout()\n\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:17.830876Z","iopub.execute_input":"2024-01-07T05:19:17.831374Z","iopub.status.idle":"2024-01-07T05:19:38.669901Z","shell.execute_reply.started":"2024-01-07T05:19:17.831326Z","shell.execute_reply":"2024-01-07T05:19:38.668724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10, 6))\nsns.scatterplot(x='tackle', y='assist', hue='position', data=players_tackles, s=100)\n\n# Annotate each point with player name\nfor i in range(len(players_tackles)):\n    plt.text(players_tackles['tackle'][i] + 0.1, players_tackles['assist'][i] + 0.1, players_tackles['displayName'][i], fontsize=8)\n\nplt.title('Player Tackles and Assists')\nplt.xlabel('Tackle')\nplt.ylabel('Assist')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:19:38.671402Z","iopub.execute_input":"2024-01-07T05:19:38.671755Z","iopub.status.idle":"2024-01-07T05:20:12.310910Z","shell.execute_reply.started":"2024-01-07T05:19:38.671721Z","shell.execute_reply":"2024-01-07T05:20:12.309744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# custom metrics\ndef calculate_tackle_score(row):\n    return row['tackle'] * 2 + row['assist'] * 1.5 - row['pff_missedTackle'] * 3\n\ndef calculate_defensive_efficiency(row):\n    return (row['tackle'] + row['assist']) / row['totalDefensiveActions'] if row['totalDefensiveActions'] != 0 else 0\n\n# Apply metrics to DataFrame\nplayers_tackles['tackle_score'] = players_tackles.apply(calculate_tackle_score, axis=1)\nplayers_tackles['defensive_efficiency'] = players_tackles.apply(calculate_defensive_efficiency, axis=1)\n\nprint(players_tackles)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:12.312314Z","iopub.execute_input":"2024-01-07T05:20:12.312730Z","iopub.status.idle":"2024-01-07T05:20:13.412350Z","shell.execute_reply.started":"2024-01-07T05:20:12.312692Z","shell.execute_reply":"2024-01-07T05:20:13.411130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# tackle_score vs defensive_efficiency\nfig = px.scatter(\n    players_tackles,\n    x='defensive_efficiency',\n    y='tackle_score',\n    hover_data=['displayName', 'position', 'gameId'],\n    title='Tackle Score vs Defensive Efficiency',\n    labels={'defensive_efficiency': 'Defensive Efficiency', 'tackle_score': 'Tackle Score'},\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:13.413968Z","iopub.execute_input":"2024-01-07T05:20:13.414664Z","iopub.status.idle":"2024-01-07T05:20:14.002846Z","shell.execute_reply.started":"2024-01-07T05:20:13.414591Z","shell.execute_reply":"2024-01-07T05:20:14.001016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.scatter(\n    players_tackles,\n    x='defensive_efficiency',\n    y='tackle_score',\n    color='position',\n    size='tackle',\n    hover_data=['displayName', 'position', 'tackle', 'assist'],\n    title='Tackle Score vs Defensive Efficiency',\n    labels={'defensive_efficiency': 'Defensive Efficiency', 'tackle_score': 'Tackle Score'},\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:14.005027Z","iopub.execute_input":"2024-01-07T05:20:14.006134Z","iopub.status.idle":"2024-01-07T05:20:15.564655Z","shell.execute_reply.started":"2024-01-07T05:20:14.006045Z","shell.execute_reply":"2024-01-07T05:20:15.563134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install PrettyTable","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:15.566246Z","iopub.execute_input":"2024-01-07T05:20:15.566614Z","iopub.status.idle":"2024-01-07T05:20:26.583729Z","shell.execute_reply.started":"2024-01-07T05:20:15.566577Z","shell.execute_reply":"2024-01-07T05:20:26.582006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from prettytable import PrettyTable\ncolumns_display = ['nflId', 'height', 'weight', 'position', 'displayName',\n                       'gameId', 'playId', 'tackle', 'assist', 'forcedFumble',\n                       'pff_missedTackle', 'totalDefensiveActions']\n\ndisplay_df = players_tackles[columns_display]\n\n# PrettyTable object\ntable = PrettyTable()\n\n# columns to PrettyTable\ntable.field_names = display_df.columns\n\n# rows to PrettyTable\nfor _, row in display_df.head(10).iterrows():\n    table.add_row(row)\n\nprint(table)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.585668Z","iopub.execute_input":"2024-01-07T05:20:26.586260Z","iopub.status.idle":"2024-01-07T05:20:26.612693Z","shell.execute_reply.started":"2024-01-07T05:20:26.586188Z","shell.execute_reply":"2024-01-07T05:20:26.610625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracking_combined.head()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.614703Z","iopub.execute_input":"2024-01-07T05:20:26.615107Z","iopub.status.idle":"2024-01-07T05:20:26.641083Z","shell.execute_reply.started":"2024-01-07T05:20:26.615070Z","shell.execute_reply":"2024-01-07T05:20:26.639994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles_tracking = pd.merge(tracking_combined,players_tackles, on='nflId', how='inner')\ntackles_tracking.head(3)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.642691Z","iopub.execute_input":"2024-01-07T05:20:26.643064Z","iopub.status.idle":"2024-01-07T05:20:26.699180Z","shell.execute_reply.started":"2024-01-07T05:20:26.643030Z","shell.execute_reply":"2024-01-07T05:20:26.697978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"column_names = tackles_tracking.columns\nprint(\"Column Names in Merged Data:\")\nprint(column_names)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.700544Z","iopub.execute_input":"2024-01-07T05:20:26.700875Z","iopub.status.idle":"2024-01-07T05:20:26.707409Z","shell.execute_reply.started":"2024-01-07T05:20:26.700842Z","shell.execute_reply":"2024-01-07T05:20:26.706248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# probability of players tackles location\n","metadata":{}},{"cell_type":"code","source":"# 'x' and 'y' are the columns representing the tackle locations\ntackle_locations = tackles_tracking[['x', 'y']]\n\n# occurrences of each tackle location\nlocation_counts = tackle_locations.groupby(['x', 'y']).size().reset_index(name='count')\n\n# total number of tackles\ntotal_tackles = location_counts['count'].sum()\n\n# probability for each location\nlocation_counts['probability'] = location_counts['count'] / total_tackles\n\nprint(location_counts)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.709336Z","iopub.execute_input":"2024-01-07T05:20:26.709826Z","iopub.status.idle":"2024-01-07T05:20:26.736734Z","shell.execute_reply.started":"2024-01-07T05:20:26.709762Z","shell.execute_reply":"2024-01-07T05:20:26.735693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Tackle type (solo vs gang, open field vs in the trenches, etc)","metadata":{}},{"cell_type":"code","source":"# Tackle type\n# new column 'tackle_type' based on the number of players involved in the tackle.\ntackles_tracking['event_type'] = np.where(tackles_tracking['event'] == 'tackle', 'normal_tackle',\n                                         np.where(tackles_tracking['event'] == 'forcedFumble', 'forced_fumble', 'other'))\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.738710Z","iopub.execute_input":"2024-01-07T05:20:26.739203Z","iopub.status.idle":"2024-01-07T05:20:26.748415Z","shell.execute_reply.started":"2024-01-07T05:20:26.739156Z","shell.execute_reply":"2024-01-07T05:20:26.747082Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles_tracking['event_type']","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.749906Z","iopub.execute_input":"2024-01-07T05:20:26.750349Z","iopub.status.idle":"2024-01-07T05:20:26.763657Z","shell.execute_reply.started":"2024-01-07T05:20:26.750304Z","shell.execute_reply":"2024-01-07T05:20:26.762397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\n\n# Solo Tackle vs. Gang Tackle\ntackles_tracking['tackle_type'] = np.where(tackles_tracking['assist'] > 0, 'gang', 'solo')","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.765352Z","iopub.execute_input":"2024-01-07T05:20:26.765686Z","iopub.status.idle":"2024-01-07T05:20:26.775611Z","shell.execute_reply.started":"2024-01-07T05:20:26.765655Z","shell.execute_reply":"2024-01-07T05:20:26.774542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles_tracking['tackle_type']","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.777574Z","iopub.execute_input":"2024-01-07T05:20:26.778135Z","iopub.status.idle":"2024-01-07T05:20:26.793280Z","shell.execute_reply.started":"2024-01-07T05:20:26.778089Z","shell.execute_reply":"2024-01-07T05:20:26.791919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Open Field vs. In the Trenches\nthreshold_x = 50\ntackles_tracking['tackle_location'] = np.where(\n    ((tackles_tracking['playDirection'] == 'right') & (tackles_tracking['x'] < threshold_x)) |\n    ((tackles_tracking['playDirection'] == 'left') & (tackles_tracking['x'] > threshold_x)),\n    'open_field', 'in_the_trenches'\n)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.794732Z","iopub.execute_input":"2024-01-07T05:20:26.795127Z","iopub.status.idle":"2024-01-07T05:20:26.808380Z","shell.execute_reply.started":"2024-01-07T05:20:26.795092Z","shell.execute_reply":"2024-01-07T05:20:26.807190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles_tracking['tackle_location']","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.810236Z","iopub.execute_input":"2024-01-07T05:20:26.810710Z","iopub.status.idle":"2024-01-07T05:20:26.827635Z","shell.execute_reply.started":"2024-01-07T05:20:26.810662Z","shell.execute_reply":"2024-01-07T05:20:26.826409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Tackle Events\ntackles_tracking['event_type'] = np.where(tackles_tracking['event'] == 'tackle', 'normal_tackle',\n                                          np.where(tackles_tracking['event'] == 'forcedFumble', 'forced_fumble', 'other'))\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.829521Z","iopub.execute_input":"2024-01-07T05:20:26.829990Z","iopub.status.idle":"2024-01-07T05:20:26.839893Z","shell.execute_reply.started":"2024-01-07T05:20:26.829954Z","shell.execute_reply":"2024-01-07T05:20:26.838194Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles_tracking['event_type']","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.841173Z","iopub.execute_input":"2024-01-07T05:20:26.841488Z","iopub.status.idle":"2024-01-07T05:20:26.856167Z","shell.execute_reply.started":"2024-01-07T05:20:26.841457Z","shell.execute_reply":"2024-01-07T05:20:26.854985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = '/kaggle/input/nfl-big-data-bowl-2024/tackles.csv'\ntackles_all = pd.read_csv(file_path)\n\ncolumn_names = tackles_all.columns\nprint(\"Column Names in Merged Data:\")\nprint(column_names)\n\ntackles_all = downcast(tackles_all)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.857412Z","iopub.execute_input":"2024-01-07T05:20:26.857811Z","iopub.status.idle":"2024-01-07T05:20:26.895642Z","shell.execute_reply.started":"2024-01-07T05:20:26.857746Z","shell.execute_reply":"2024-01-07T05:20:26.894223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"###  Include only the rows where a tackle was missed and percentage of missed tackles","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# rows where a tackle was missed\nmissed_tackles_df = tackles_all.loc[tackles_all['pff_missedTackle'] == 1]\n\n# percentage of missed tackles\ntotal_tackles = len(tackles_all)\nmissed_tackles = len(missed_tackles_df)\nmissed_tackle_percentage = (missed_tackles / total_tackles) * 100\n\n# percentage of missed tackles\nprint(f\"Percentage of Missed Tackles: {missed_tackle_percentage:.2f}%\")","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.897307Z","iopub.execute_input":"2024-01-07T05:20:26.897645Z","iopub.status.idle":"2024-01-07T05:20:26.909206Z","shell.execute_reply.started":"2024-01-07T05:20:26.897611Z","shell.execute_reply":"2024-01-07T05:20:26.908001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots()\nax.bar(['Total Tackles', 'Missed Tackles'], [total_tackles, missed_tackles_df.shape[0]])\nax.set_ylabel('Number of Tackles')\nax.set_title('Total Tackles vs Missed Tackles')\n\n# Pie Chart\nlabels = ['Missed Tackles', 'Successful Tackles']\nsizes = [missed_tackles, total_tackles - missed_tackles]\nexplode = (0.1, 0)  # explode 1st slice - Missed Tackles\nfig2, ax2 = plt.subplots()\nax2.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', startangle=90)\nax2.axis('equal')  # Equal aspect ratio so that pie is drawn as a circle.\nax2.set_title('Percentage of Missed Tackles')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:26.911171Z","iopub.execute_input":"2024-01-07T05:20:26.911517Z","iopub.status.idle":"2024-01-07T05:20:27.175595Z","shell.execute_reply.started":"2024-01-07T05:20:26.911483Z","shell.execute_reply":"2024-01-07T05:20:27.174530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tackles_time = pd.merge(tackles_all, games, on='gameId')\n\ncolumn_names = tackles_time.columns\nprint(\"Column Names in Merged Data:\")\nprint(column_names)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:27.176866Z","iopub.execute_input":"2024-01-07T05:20:27.177190Z","iopub.status.idle":"2024-01-07T05:20:27.194430Z","shell.execute_reply.started":"2024-01-07T05:20:27.177159Z","shell.execute_reply":"2024-01-07T05:20:27.193147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Predictions of tackle time","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.linear_model import LinearRegression\nfrom sklearn.metrics import mean_absolute_error\n\nX = tackles_time[['gameId', 'playId', 'nflId', 'assist', 'forcedFumble', 'pff_missedTackle', 'month', 'day', 'hour']]\ny = tackles_time['tackle']\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n\nmodel = LinearRegression()\nmodel.fit(X_train, y_train)\n\npredictions = model.predict(X_test)\nmae = mean_absolute_error(y_test, predictions)\nprint(f'Mean Absolute Error: {mae}')\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:27.195888Z","iopub.execute_input":"2024-01-07T05:20:27.196215Z","iopub.status.idle":"2024-01-07T05:20:27.453442Z","shell.execute_reply.started":"2024-01-07T05:20:27.196183Z","shell.execute_reply":"2024-01-07T05:20:27.452194Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# actual vs predicted tackle times\nplt.scatter(y_test, predictions, alpha=0.5)\nplt.title('Actual vs Predicted Tackle Times')\nplt.xlabel('Actual Tackle Time')\nplt.ylabel('Predicted Tackle Time')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:27.455226Z","iopub.execute_input":"2024-01-07T05:20:27.455890Z","iopub.status.idle":"2024-01-07T05:20:27.684289Z","shell.execute_reply.started":"2024-01-07T05:20:27.455841Z","shell.execute_reply":"2024-01-07T05:20:27.682856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Source \n   - https://www.kaggle.com/code/sasakitetsuya/1st-step-data-summary-and-understanding\n\n# tackle efficiency\n- Tackles efficiency is commonly calculated as the ratio of successful tackles to total tackle attempts. formula : \n![image.png](attachment:26cfae00-00b6-4cc7-b9d4-213a90fedc92.png)","metadata":{},"attachments":{"26cfae00-00b6-4cc7-b9d4-213a90fedc92.png":{"image/png":"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"}}},{"cell_type":"markdown","source":"### calculate - tackle efficiency","metadata":{}},{"cell_type":"code","source":"from prettytable import PrettyTable\n\ntackles_time['total_attempts'] = tackles_time['tackle'] + tackles_time['pff_missedTackle']\ntackles_time['tackles_efficiency'] = tackles_time['tackle'] / tackles_time['total_attempts']\n\ncolumns_to_display = ['gameId', 'playId', 'nflId', 'tackle', 'pff_missedTackle', 'total_attempts', 'tackles_efficiency']\ntable_data = tackles_time[columns_to_display]\n\n# PrettyTable instance\ntable = PrettyTable()\ntable.field_names = columns_to_display\n\n# Added first 10 rows to the table \nfor _, row in table_data.head(10).iterrows():\n    table.add_row(row)\n\nprint(table)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:27.686760Z","iopub.execute_input":"2024-01-07T05:20:27.687156Z","iopub.status.idle":"2024-01-07T05:20:27.708511Z","shell.execute_reply.started":"2024-01-07T05:20:27.687122Z","shell.execute_reply":"2024-01-07T05:20:27.707057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Team Performance","metadata":{}},{"cell_type":"code","source":"# Group by home team abbreviation and calculate team performance metrics\nhome_team_metrics = tackles_time.groupby(['homeTeamAbbr', 'season', 'week']).agg({\n    'tackle': 'sum',\n    'assist': 'sum',\n    'forcedFumble': 'sum',\n    'pff_missedTackle': 'sum',\n})\n\n# Group by visitor team abbreviation and calculate team performance metrics\nvisitor_team_metrics = tackles_time.groupby(['visitorTeamAbbr', 'season', 'week']).agg({\n    'tackle': 'sum',\n    'assist': 'sum',\n    'forcedFumble': 'sum',\n    'pff_missedTackle': 'sum',\n})\n\n# Renaming columns to distinguish between home and visitor metrics\nhome_team_metrics = home_team_metrics.add_prefix('home_').reset_index()\nvisitor_team_metrics = visitor_team_metrics.add_prefix('visitor_').reset_index()\n\nteam_metrics = pd.merge(home_team_metrics, visitor_team_metrics, how='outer', left_on=['season', 'week'], right_on=['season', 'week'])\n\n# NaN values with 0 \nteam_metrics = team_metrics.fillna(0)\n\n# total metrics (sum of home and visitor metrics)\nteam_metrics['total_tackle'] = team_metrics['home_tackle'] + team_metrics['visitor_tackle']\nteam_metrics['total_assist'] = team_metrics['home_assist'] + team_metrics['visitor_assist']\nteam_metrics['total_forcedFumble'] = team_metrics['home_forcedFumble'] + team_metrics['visitor_forcedFumble']\nteam_metrics['total_pff_missedTackle'] = team_metrics['home_pff_missedTackle'] + team_metrics['visitor_pff_missedTackle']\n\n# PrettyTable object\ntable = PrettyTable()\n\ntable.field_names = team_metrics.columns\n\nfor _, row in team_metrics.head(10).iterrows():\n    table.add_row(row)\n\nprint(table)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:27.710222Z","iopub.execute_input":"2024-01-07T05:20:27.710682Z","iopub.status.idle":"2024-01-07T05:20:27.773004Z","shell.execute_reply.started":"2024-01-07T05:20:27.710634Z","shell.execute_reply":"2024-01-07T05:20:27.771842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Tackle Efficiency of each Player","metadata":{}},{"cell_type":"code","source":"# This code - https://www.kaggle.com/code/sasakitetsuya/1st-step-data-summary-and-understanding\ngames=pd.read_csv('/kaggle/input/nfl-big-data-bowl-2024/games.csv')\nplayers=pd.read_csv('/kaggle/input/nfl-big-data-bowl-2024/players.csv')\ntackles=pd.read_csv('/kaggle/input/nfl-big-data-bowl-2024/tackles.csv')\nplays=pd.read_csv('/kaggle/input/nfl-big-data-bowl-2024/plays.csv')\n\n# Calculate tackle efficiency for each player\ntackles['total_tackles'] = tackles['tackle'] + tackles['assist']\nplayer_performance = tackles.groupby('nflId').agg(\n    total_tackles=('total_tackles', 'sum'),\n    missed_tackles=('pff_missedTackle', 'sum'),\n    forced_fumbles=('forcedFumble', 'sum')\n)\n\n# Calculate tackle efficiency\nplayer_performance['tackle_efficiency'] = player_performance['total_tackles'] / (player_performance['total_tackles'] + player_performance['missed_tackles'])\n\n# Merge with player names for better readability\nplayer_performance = player_performance.merge(players[['nflId', 'displayName', 'position']], on='nflId')\n\n# Sort players by tackle efficiency in descending order\nplayer_performance_sorted = player_performance.sort_values(by='tackle_efficiency', ascending=False)\n\n# Display top 10 players based on tackle efficiency\nplayer_performance_sorted.head(20)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:27.774757Z","iopub.execute_input":"2024-01-07T05:20:27.775125Z","iopub.status.idle":"2024-01-07T05:20:27.954649Z","shell.execute_reply.started":"2024-01-07T05:20:27.775091Z","shell.execute_reply":"2024-01-07T05:20:27.953303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"position_performance = player_performance.groupby('position').agg(\n    avg_tackle_efficiency=('tackle_efficiency', 'mean'),\n    total_tackles=('total_tackles', 'sum')\n)\n\nplayer_contribution = player_performance_sorted[['displayName', 'position', 'tackle_efficiency', 'total_tackles']]\n\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Example: Bar chart of top 10 players based on tackle efficiency\nplt.figure(figsize=(10, 6))\nsns.barplot(x='tackle_efficiency', y='displayName', data=player_performance_sorted.head(10))\nplt.title('Top 10 Players Based on Tackle Efficiency')\nplt.xlabel('Tackle Efficiency')\nplt.ylabel('Player Name')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:27.957054Z","iopub.execute_input":"2024-01-07T05:20:27.957559Z","iopub.status.idle":"2024-01-07T05:20:28.240366Z","shell.execute_reply.started":"2024-01-07T05:20:27.957510Z","shell.execute_reply":"2024-01-07T05:20:28.239106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"top_missed_tacklers = player_performance_sorted.sort_values(by='missed_tackles', ascending=False).head(10)\n\ntop_forced_fumblers = player_performance_sorted.sort_values(by='forced_fumbles', ascending=False).head(10)\n\nplt.scatter(player_performance['total_tackles'], player_performance['tackle_efficiency'])\nplt.title('Tackle Efficiency vs. Total Tackles')\nplt.xlabel('Total Tackles')\nplt.ylabel('Tackle Efficiency')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.241805Z","iopub.execute_input":"2024-01-07T05:20:28.242139Z","iopub.status.idle":"2024-01-07T05:20:28.444493Z","shell.execute_reply.started":"2024-01-07T05:20:28.242107Z","shell.execute_reply":"2024-01-07T05:20:28.443438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# overall tackling score\n- Total Tackles Score:\n    - higher score for more tackles.\n    - Normalize the values based on the maximum number of tackles in the dataset.\n    \n - Missed Tackles Penalty:\n    - Penalize missed tackles, assigning a lower score for more missed tackles.\n    - Normalize the values based on the maximum number of missed tackles in the dataset.\n    \n - Forced Fumbles Bonus:\n    - bonus for forced fumbles.\n    - Normalize the values based on the maximum number of forced fumbles in the dataset.\n    \n - Tackle Efficiency Score:\n    - tackle efficiency based on the ratio of successful tackles to total tackles.\n    - Normalize the values based on the maximum tackle efficiency in the dataset.\n    \n  \n - Overall Tackling Score:\n    - Combine scores with weights to calculate an overall tackling score.","metadata":{}},{"cell_type":"code","source":"# overall tackling score\nplayer_performance['total_tackles_score'] = player_performance['total_tackles'] / player_performance['total_tackles'].max()\n\nplayer_performance['missed_tackles_penalty'] = 1 - (player_performance['missed_tackles'] / player_performance['missed_tackles'].max())\n\nplayer_performance['forced_fumbles_bonus'] = player_performance['forced_fumbles'] / player_performance['forced_fumbles'].max()\n\nplayer_performance['tackle_efficiency_score'] = player_performance['total_tackles'] / (player_performance['total_tackles'] + player_performance['missed_tackles'])\nplayer_performance['tackle_efficiency_score'] /= player_performance['tackle_efficiency_score'].max()\n\nweight_total_tackles = 0.4\nweight_missed_tackles = 0.2\nweight_forced_fumbles = 0.2\nweight_tackle_efficiency = 0.2\n\nplayer_performance['overall_tackling_score'] = (\n    weight_total_tackles * player_performance['total_tackles_score'] +\n    weight_missed_tackles * player_performance['missed_tackles_penalty'] +\n    weight_forced_fumbles * player_performance['forced_fumbles_bonus'] +\n    weight_tackle_efficiency * player_performance['tackle_efficiency_score']\n)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:23:10.309754Z","iopub.execute_input":"2024-01-07T05:23:10.310214Z","iopub.status.idle":"2024-01-07T05:23:10.331534Z","shell.execute_reply.started":"2024-01-07T05:23:10.310177Z","shell.execute_reply":"2024-01-07T05:23:10.330392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# overall tackling score\nfrom prettytable import PrettyTable\n\n# PrettyTable object\ntable = PrettyTable()\n\ntable.field_names = ['Player', 'Total Tackles Score', 'Missed Tackles Penalty', 'Forced Fumbles Bonus', 'Tackle Efficiency Score', 'Overall Tackling Score']\n\nfor _, row in player_performance.head(10).iterrows():\n    table.add_row([\n        row['displayName'],\n        round(row['total_tackles_score'], 2),\n        round(row['missed_tackles_penalty'], 2),\n        round(row['forced_fumbles_bonus'], 2),\n        round(row['tackle_efficiency_score'], 2),\n        round(row['overall_tackling_score'], 2)\n    ])\n\n# formatted table as a string\ntable_string = table.get_string()\n\nprint(table_string)\n\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:27:03.439185Z","iopub.execute_input":"2024-01-07T05:27:03.439585Z","iopub.status.idle":"2024-01-07T05:27:03.458588Z","shell.execute_reply.started":"2024-01-07T05:27:03.439551Z","shell.execute_reply":"2024-01-07T05:27:03.457110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# overall tackling score\nimport matplotlib.pyplot as plt\n# overall tackling score\nplt.figure(figsize=(12, 8))  \nplt.bar(player_performance['displayName'], player_performance['overall_tackling_score'], color='blue')\nplt.xlabel('Player')\nplt.ylabel('Overall Tackling Score')\nplt.title('Overall Tackling Score for Each Player')\nplt.xticks(rotation=45, ha='right', fontsize=10)  # Adjust rotation and font size\nplt.yticks(fontsize=10)  \nplt.tight_layout()\nplt.show()\n\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:24:40.659564Z","iopub.execute_input":"2024-01-07T05:24:40.660171Z","iopub.status.idle":"2024-01-07T05:24:52.601186Z","shell.execute_reply.started":"2024-01-07T05:24:40.660113Z","shell.execute_reply":"2024-01-07T05:24:52.599728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# tackling performance\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.linear_model import LinearRegression\nfrom sklearn.metrics import mean_squared_error, r2_score\nfrom sklearn.preprocessing import StandardScaler\n\nfeatures = ['total_tackles', 'missed_tackles', 'forced_fumbles', 'tackle_efficiency']\ntarget = 'overall_tackling_score'  \n\nX = player_performance[features]\ny = player_performance[target]\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n\nscaler = StandardScaler()\nX_train_scaled = scaler.fit_transform(X_train)\nX_test_scaled = scaler.transform(X_test)\n\nmodel = LinearRegression()\n\nmodel.fit(X_train_scaled, y_train)\n\npredictions = model.predict(X_test_scaled)\n\nmse = mean_squared_error(y_test, predictions)\nr2 = r2_score(y_test, predictions)\n\nprint(f'Mean Squared Error: {mse:.2f}')\nprint(f'R-squared: {r2:.2f}')","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:32:16.279556Z","iopub.execute_input":"2024-01-07T05:32:16.280075Z","iopub.status.idle":"2024-01-07T05:32:16.309566Z","shell.execute_reply.started":"2024-01-07T05:32:16.280037Z","shell.execute_reply":"2024-01-07T05:32:16.308454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Coefficients:', model.coef_)\nprint('Intercept:', model.intercept_)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:32:42.169303Z","iopub.execute_input":"2024-01-07T05:32:42.169822Z","iopub.status.idle":"2024-01-07T05:32:42.177804Z","shell.execute_reply.started":"2024-01-07T05:32:42.169762Z","shell.execute_reply":"2024-01-07T05:32:42.176180Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# actual vs predicted values\nplt.figure(figsize=(10, 6))\nplt.scatter(y_test, predictions, alpha=0.5)\nplt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], '--', color='red', linewidth=2)\nplt.title('Actual vs Predicted Tackling Scores')\nplt.xlabel('Actual Tackling Scores')\nplt.ylabel('Predicted Tackling Scores')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:33:10.739066Z","iopub.execute_input":"2024-01-07T05:33:10.739527Z","iopub.status.idle":"2024-01-07T05:33:10.973646Z","shell.execute_reply.started":"2024-01-07T05:33:10.739486Z","shell.execute_reply":"2024-01-07T05:33:10.972414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Total yards to go","metadata":{}},{"cell_type":"code","source":"yards_to_go = plays.groupby('ballCarrierId')['yardsToGo'].sum()\n\nprint(yards_to_go)","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.445849Z","iopub.execute_input":"2024-01-07T05:20:28.446167Z","iopub.status.idle":"2024-01-07T05:20:28.458111Z","shell.execute_reply.started":"2024-01-07T05:20:28.446136Z","shell.execute_reply":"2024-01-07T05:20:28.456758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# total yards gained","metadata":{}},{"cell_type":"code","source":"total_yards_gained = plays['playResult'].sum()\n\nprint(f'Total Yards Gained: {total_yards_gained} yards')\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.459699Z","iopub.execute_input":"2024-01-07T05:20:28.460550Z","iopub.status.idle":"2024-01-07T05:20:28.469527Z","shell.execute_reply.started":"2024-01-07T05:20:28.460495Z","shell.execute_reply":"2024-01-07T05:20:28.468127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plays['total_yards_gained'] = plays['playResult'].cumsum()\nplays.head()","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.471218Z","iopub.execute_input":"2024-01-07T05:20:28.471593Z","iopub.status.idle":"2024-01-07T05:20:28.507225Z","shell.execute_reply.started":"2024-01-07T05:20:28.471556Z","shell.execute_reply":"2024-01-07T05:20:28.506300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# percentage of completed passes by a quarterback","metadata":{"execution":{"iopub.status.busy":"2024-01-01T12:36:14.192335Z","iopub.execute_input":"2024-01-01T12:36:14.192679Z","iopub.status.idle":"2024-01-01T12:36:14.198565Z","shell.execute_reply.started":"2024-01-01T12:36:14.192649Z","shell.execute_reply":"2024-01-01T12:36:14.197852Z"}}},{"cell_type":"code","source":"pass_attempts = plays[plays['passResult'].notnull()]\n\n# Count completed passes\ncompleted_passes = pass_attempts[pass_attempts['passResult'] == 'C']\n\n# percentage of completed passes\ncompletion_percentage = (completed_passes.shape[0] / pass_attempts.shape[0]) * 100\n\nprint(f\"Completion Percentage: {completion_percentage:.2f}%\")\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.508694Z","iopub.execute_input":"2024-01-07T05:20:28.509041Z","iopub.status.idle":"2024-01-07T05:20:28.526910Z","shell.execute_reply.started":"2024-01-07T05:20:28.509009Z","shell.execute_reply":"2024-01-07T05:20:28.525609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# percentage of plays in the red zone","metadata":{}},{"cell_type":"code","source":"max_value = plays['passLength'].max()\nmax_value","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.528294Z","iopub.execute_input":"2024-01-07T05:20:28.528607Z","iopub.status.idle":"2024-01-07T05:20:28.536284Z","shell.execute_reply.started":"2024-01-07T05:20:28.528577Z","shell.execute_reply":"2024-01-07T05:20:28.535105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# threshold value for pass length to determine if the play entered the end zone\npass_length_threshold = 109  # Adjust as needed\n\n# plays where the ball traveled beyond the line of scrimmage and into the end zone\nend_zone_plays = plays[(plays['passLength'] >= pass_length_threshold) & (plays['absoluteYardlineNumber'] <= 109)]\n\n# percentage of plays in the red zone\ntotal_plays_in_red_zone = end_zone_plays.shape[0]\ntotal_plays = plays.shape[0]\n\nif total_plays > 0:\n    percentage_plays_in_red_zone = (total_plays_in_red_zone / total_plays) * 100\n    print(f\"Percentage of plays in the red zone: {percentage_plays_in_red_zone:.2f}%\")\nelse:\n    print(\"No plays in the dataset.\")\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.538021Z","iopub.execute_input":"2024-01-07T05:20:28.538503Z","iopub.status.idle":"2024-01-07T05:20:28.551623Z","shell.execute_reply.started":"2024-01-07T05:20:28.538442Z","shell.execute_reply":"2024-01-07T05:20:28.550515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import ipywidgets as widgets\nfrom IPython.display import display\nfrom ipywidgets import interactive\n\ndef filter_data(nflId=None, height=None, weight=None, birthDate=None, collegeName=None,\n                position=None, displayName=None, gameId=None, playId=None, tackle=None,\n                assist=None, forcedFumble=None, pff_missedTackle=None, totalDefensiveActions=None):\n    # filters based on user input\n    filtered_data = players_tackles[\n        (players_tackles['nflId'] == nflId if nflId is not None else True) &\n        (players_tackles['height'] == height if height is not None else True) &\n        (players_tackles['weight'] == weight if weight is not None else True) &\n        (players_tackles['birthDate'] == birthDate if birthDate is not None else True) &\n        (players_tackles['collegeName'] == collegeName if collegeName is not None else True) &\n        (players_tackles['position'] == position if position is not None else True) &\n        (players_tackles['displayName'] == displayName if displayName is not None else True) &\n        (players_tackles['gameId'] == gameId if gameId is not None else True) &\n        (players_tackles['playId'] == playId if playId is not None else True) &\n        (players_tackles['tackle'] == tackle if tackle is not None else True) &\n        (players_tackles['assist'] == assist if assist is not None else True) &\n        (players_tackles['forcedFumble'] == forcedFumble if forcedFumble is not None else True) &\n        (players_tackles['pff_missedTackle'] == pff_missedTackle if pff_missedTackle is not None else True) &\n        (players_tackles['totalDefensiveActions'] == totalDefensiveActions if totalDefensiveActions is not None else True)\n    ]\n\n    display(filtered_data)\n\n# widgets for each column\nnflId_widget = widgets.IntText(description='nflId:')\nheight_widget = widgets.FloatText(description='height:')\nweight_widget = widgets.FloatText(description='weight:')\nbirthDate_widget = widgets.Text(description='birthDate:')\ncollegeName_widget = widgets.Text(description='collegeName:')\nposition_widget = widgets.Text(description='position:')\ndisplayName_widget = widgets.Text(description='displayName:')\ngameId_widget = widgets.IntText(description='gameId:')\nplayId_widget = widgets.IntText(description='playId:')\ntackle_widget = widgets.IntText(description='tackle:')\nassist_widget = widgets.IntText(description='assist:')\nforcedFumble_widget = widgets.IntText(description='forcedFumble:')\npff_missedTackle_widget = widgets.IntText(description='pff_missedTackle:')\ntotalDefensiveActions_widget = widgets.IntText(description='totalDefensiveActions:')\n\n# interactive widget\ninteractive_filter = interactive(filter_data,\n                                  nflId=nflId_widget,\n                                  height=height_widget,\n                                  weight=weight_widget,\n                                  birthDate=birthDate_widget,\n                                  collegeName=collegeName_widget,\n                                  position=position_widget,\n                                  displayName=displayName_widget,\n                                  gameId=gameId_widget,\n                                  playId=playId_widget,\n                                  tackle=tackle_widget,\n                                  assist=assist_widget,\n                                  forcedFumble=forcedFumble_widget,\n                                  pff_missedTackle=pff_missedTackle_widget,\n                                  totalDefensiveActions=totalDefensiveActions_widget)\n\n\ndisplay(interactive_filter)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.553798Z","iopub.execute_input":"2024-01-07T05:20:28.554400Z","iopub.status.idle":"2024-01-07T05:20:28.764616Z","shell.execute_reply.started":"2024-01-07T05:20:28.554354Z","shell.execute_reply":"2024-01-07T05:20:28.763588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import ipywidgets as widgets\n\n# filter for specific column\ndef create_filter(column_name):\n    options = ['All'] + players_tackles[column_name].unique().tolist()\n    dropdown = widgets.Dropdown(options=options, value='All', description=column_name)\n    return dropdown\n\ndef display_filtered_df(**kwargs):\n    filtered_df = players_tackles.copy()\n    for column_name, value in kwargs.items():\n        if value != 'All':\n            filtered_df = filtered_df[filtered_df[column_name] == value]\n    display(filtered_df)\n\n# filter widgets for each column\nfilters = {column: create_filter(column) for column in players_tackles.columns}\n\n# button to apply filters\napply_button = widgets.Button(description='Apply Filters')\n\n# handle button click event\ndef apply_filters(_):\n    filter_values = {column: filter_widget.value for column, filter_widget in filters.items()}\n    display_filtered_df(**filter_values)\n\napply_button.on_click(apply_filters)\n\ndisplay(*filters.values(), apply_button)\n","metadata":{"execution":{"iopub.status.busy":"2024-01-07T05:20:28.766081Z","iopub.execute_input":"2024-01-07T05:20:28.766426Z","iopub.status.idle":"2024-01-07T05:20:29.073623Z","shell.execute_reply.started":"2024-01-07T05:20:28.766394Z","shell.execute_reply":"2024-01-07T05:20:29.072651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}