{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt\nimport plotly.express as px\nfrom plotly.subplots import make_subplots\nimport plotly.graph_objs as go\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-02T05:03:26.050017Z","iopub.execute_input":"2022-01-02T05:03:26.050411Z","iopub.status.idle":"2022-01-02T05:03:27.558593Z","shell.execute_reply.started":"2022-01-02T05:03:26.050322Z","shell.execute_reply":"2022-01-02T05:03:27.557644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"1. Game Data\nGame data: The games.csv contains the teams playing in each game. The key variable is gameId.\n\ngameId: Game identifier, unique (numeric)\n\ngameDate: Game Date (time, mm/dd/yyyy)\n\ngameTimeEastern: Start time of game (time, HH:MM:SS, EST)\n\nhomeTeamAbbr: Home team three-letter code (text)\n\nvisitorTeamAbbr: Visiting team three-letter code (text)\n\nweek: Week of game (numeric)","metadata":{}},{"cell_type":"code","source":"games = pd.read_csv('../input/nfl-big-data-bowl-2022/games.csv')\ngames","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:03:58.585069Z","iopub.execute_input":"2022-01-02T05:03:58.585387Z","iopub.status.idle":"2022-01-02T05:03:58.623830Z","shell.execute_reply.started":"2022-01-02T05:03:58.585357Z","shell.execute_reply":"2022-01-02T05:03:58.623226Z"},"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","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:04:25.205661Z","iopub.execute_input":"2022-01-02T05:04:25.206108Z","iopub.status.idle":"2022-01-02T05:04:25.213638Z","shell.execute_reply.started":"2022-01-02T05:04:25.206064Z","shell.execute_reply":"2022-01-02T05:04:25.212653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = games['gameDate'].value_counts().reset_index()\n\ncheck.columns = [\n    'date', \n    'games'\n]\n\ncheck = check.sort_values('games')\n\nfig = px.bar(\n    check, \n    y='date', \n    x=\"games\", \n    orientation='h', \n    title='Number of games for every date', \n    height=900, \n    width=800\n)\n\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:04:35.616245Z","iopub.execute_input":"2022-01-02T05:04:35.616535Z","iopub.status.idle":"2022-01-02T05:04:36.616089Z","shell.execute_reply.started":"2022-01-02T05:04:35.616505Z","shell.execute_reply":"2022-01-02T05:04:36.615494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = games['gameTimeEastern'].value_counts().reset_index()\n\ncheck.columns = [\n    'time', \n    'games'\n]\n\ncheck = check.sort_values('games')\n\nfig = px.bar(\n    check, \n    y='time', \n    x=\"games\", \n    orientation='h', \n    title='Number of games for every time', \n    height=400, \n    width=800\n)\n\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:04:47.185747Z","iopub.execute_input":"2022-01-02T05:04:47.186552Z","iopub.status.idle":"2022-01-02T05:04:47.258895Z","shell.execute_reply.started":"2022-01-02T05:04:47.186504Z","shell.execute_reply":"2022-01-02T05:04:47.258084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = games['homeTeamAbbr'].value_counts().reset_index()\n\ncheck.columns = [\n    'team', \n    'games'\n]\n\ncheck = check.sort_values('games')\n\nfig = px.bar(\n    check, \n    y='team', \n    x=\"games\", \n    orientation='h', \n    title='Number of games for every team (home)', \n    height=700, \n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:04:59.191312Z","iopub.execute_input":"2022-01-02T05:04:59.191588Z","iopub.status.idle":"2022-01-02T05:04:59.264783Z","shell.execute_reply.started":"2022-01-02T05:04:59.191560Z","shell.execute_reply":"2022-01-02T05:04:59.263819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = games['visitorTeamAbbr'].value_counts().reset_index()\n\ncheck.columns = [\n    'team', \n    'games'\n]\n\ncheck = check.sort_values('games')\n\nfig = px.bar(\n    check, \n    y='team', \n    x=\"games\", \n    orientation='h', \n    title='Number of games for every team (away)', \n    height=700, \n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:05:09.305765Z","iopub.execute_input":"2022-01-02T05:05:09.306088Z","iopub.status.idle":"2022-01-02T05:05:09.376276Z","shell.execute_reply.started":"2022-01-02T05:05:09.306028Z","shell.execute_reply":"2022-01-02T05:05:09.375472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = games['week'].value_counts().reset_index()\n\ncheck.columns = [\n    'week', \n    'games'\n]\n\ncheck = check.sort_values('games')\ncheck['week'] = check['week'].astype(str) + '-'\n\nfig = px.bar(\n    check, \n    y='week', \n    x=\"games\", \n    orientation='h', \n    title='Number of games for every week', \n    height=500, \n    width=800\n)\n\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:05:22.945668Z","iopub.execute_input":"2022-01-02T05:05:22.946352Z","iopub.status.idle":"2022-01-02T05:05:23.015485Z","shell.execute_reply.started":"2022-01-02T05:05:22.946303Z","shell.execute_reply":"2022-01-02T05:05:23.014668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"2. Player Data\nPlayer 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\n\nnflId: Player identification number, unique across players (numeric)\n\nheight: Player height (text)\n\nweight: Player weight (numeric)\n\nbirthDate: Date of birth (YYYY-MM-DD)\n\ncollegeName: Player college (text)\n\nposition: Player position (text)\n\ndisplayName: Player name (text)","metadata":{}},{"cell_type":"code","source":"players = pd.read_csv('../input/nfl-big-data-bowl-2022/players.csv')\nplayers","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:05:55.415713Z","iopub.execute_input":"2022-01-02T05:05:55.416015Z","iopub.status.idle":"2022-01-02T05:05:55.451946Z","shell.execute_reply.started":"2022-01-02T05:05:55.415980Z","shell.execute_reply":"2022-01-02T05:05:55.451135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resumetable(players)","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:06:02.246355Z","iopub.execute_input":"2022-01-02T05:06:02.246652Z","iopub.status.idle":"2022-01-02T05:06:02.274142Z","shell.execute_reply.started":"2022-01-02T05:06:02.246619Z","shell.execute_reply":"2022-01-02T05:06:02.273292Z"},"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 = [\n    'first', \n    'second'\n]\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":"2022-01-02T05:06:23.886606Z","iopub.execute_input":"2022-01-02T05:06:23.887466Z","iopub.status.idle":"2022-01-02T05:06:24.035994Z","shell.execute_reply.started":"2022-01-02T05:06:23.887415Z","shell.execute_reply":"2022-01-02T05:06:24.035227Z"},"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":"2022-01-02T05:06:31.405215Z","iopub.execute_input":"2022-01-02T05:06:31.405784Z","iopub.status.idle":"2022-01-02T05:06:31.426243Z","shell.execute_reply.started":"2022-01-02T05:06:31.405744Z","shell.execute_reply":"2022-01-02T05:06:31.425397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = make_subplots(rows=1, cols=2)\ntraces = [\n    go.Histogram(\n        x=players[col[0]], \n        nbinsx=col[1], \n        name=col[0]\n    ) for col in [('height', 20), ('weight', 50)]\n]\n\nfor i in range(len(traces)):\n    fig.append_trace(\n        traces[i], \n        (i // 2) + 1, \n        (i % 2) + 1\n    )\n\nfig.update_layout(\n    title_text='Height & weight distributions',\n    height=400,\n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:07:00.146354Z","iopub.execute_input":"2022-01-02T05:07:00.146973Z","iopub.status.idle":"2022-01-02T05:07:00.191482Z","shell.execute_reply.started":"2022-01-02T05:07:00.146926Z","shell.execute_reply":"2022-01-02T05:07:00.190849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = players['collegeName'].value_counts().reset_index()\n\ncheck.columns = [\n    'college', \n    'players'\n]\n\ncheck = check.sort_values('players').tail(50)\n\nfig = px.bar(\n    check, \n    y='college', \n    x=\"players\", \n    orientation='h', \n    title='Top 50 colleges by number of players',\n    height=900,\n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:07:09.966100Z","iopub.execute_input":"2022-01-02T05:07:09.966756Z","iopub.status.idle":"2022-01-02T05:07:10.034871Z","shell.execute_reply.started":"2022-01-02T05:07:09.966716Z","shell.execute_reply":"2022-01-02T05:07:10.034246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Players positions abbreviation\n\nWR: Wide Receiver;\n    \nCB: Cornerback;\n    \nRB: Running Back;\n    \nTE: Tight End;\n    \nOLB: Outside Linebacker;\n    \nQB: Quarterback;\n    \nFS: Free Safety;\n    \nLB: Linebacker;\n    \nSS: Strong Safety;\n    \nILB: Inside Linebacker;\n    \nDE: Defensive End;\n    \nDB: Defensive Back;\n    \nMLB: Middle Linebacker\n    \nDT: Defensive Tackle;\n    \nFB: Fullback;\n    \nP: Punter;\n    \nLS: Long snapper;\n    \nS: Safety;\n    \nK: Kicker;\n    \nHB: Running back;\n    \nNT: Nose Tackle","metadata":{}},{"cell_type":"markdown","source":"3. Play Data\n\nPlay data: The plays.csv file contains play-level information from each game. The key variables are gameId and playId\n\ngameId: Game identifier, unique (numeric)\n\nplayId: Play identifier, not unique across games (numeric)\n\nplayDescription: Description of play (text)\n\nquarter: Game quarter (numeric)\n\ndown: Down (numeric)\n\nyardsToGo: Distance needed for a first down (numeric)\n\npossessionTeam: Team on offense (text)\n\nplayType: Outcome of dropback: sack or pass (text)\n\nyardlineSide: 3-letter team code corresponding to line-of-scrimmage (text)\n\nyardlineNumber: Yard line at line-of-scrimmage (numeric)\n\noffenseFormation: Formation used by possession team (text)\n\npersonnelO: Personnel used by offensive team (text)\n\ndefendersInTheBox: Number of defenders in close proximity to line-of-scrimmage (numeric)\n\nnumberOfPassRushers: Number of pass rushers (numeric)\n\npersonnelD: Personnel used by defensive team (text)\n\ntypeDropback: Dropback categorization of quarterback (text)\n\npreSnapHomeScore: Home score prior to the play (numeric)\n\npreSnapVisitorScore: Visiting team score prior to the play (numeric)\n\ngameClock: Time on clock of play (MM:SS)\n\nabsoluteYardlineNumber: Distance from end zone for possession team (numeric)\n\npenaltyCodes: NFL categorization of the penalties that ocurred on the play. For purposes of this contest, the most important penalties are Defensive Pass Interference (DPI), Offensive Pass Interference (OPI), Illegal Contact (ICT), and Defensive Holding (DH). Multiple penalties on a play are separated by a ; (text)\n\npenaltyJerseyNumber: Jersey number and team code of the player commiting each penalty. Multiple penalties on a play are separated by a ; (text)\n\npassResult: Outcome of the passing play (C: Complete pass, I: Incomplete pass, S: Quarterback sack, IN: Intercepted pass, text)\n\noffensePlayResult: Yards gained by the offense, excluding penalty yardage (numeric)\n\nplayResult: Net yards gained by the offense, including penalty yardage (numeric)\n\nepa: Expected points added on the play, relative to the offensive team. Expected points is a metric that estimates the average of every next scoring outcome given the play's down, distance, yardline, and time remaining (numeric)\n\nisDefensivePI: An indicator variable for whether or not a DPI penalty ocurred on a given play (TRUE/FALSE)","metadata":{}},{"cell_type":"code","source":"plays = pd.read_csv('../input/nfl-big-data-bowl-2022/plays.csv')\n\nplays","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:09:51.525662Z","iopub.execute_input":"2022-01-02T05:09:51.525933Z","iopub.status.idle":"2022-01-02T05:09:51.715790Z","shell.execute_reply.started":"2022-01-02T05:09:51.525905Z","shell.execute_reply":"2022-01-02T05:09:51.714920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resumetable(plays)","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:10:05.405405Z","iopub.execute_input":"2022-01-02T05:10:05.406396Z","iopub.status.idle":"2022-01-02T05:10:05.478771Z","shell.execute_reply.started":"2022-01-02T05:10:05.406350Z","shell.execute_reply":"2022-01-02T05:10:05.477898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = plays['quarter'].value_counts().reset_index()\n\ncheck.columns = [\n    'quarter', \n    'plays'\n]\n\ncheck = check.sort_values('plays')\n\nfig = px.pie(\n    check, \n    names='quarter', \n    values=\"plays\",  \n    title='Number of plays of every quarter',\n    height=500,\n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:10:30.655153Z","iopub.execute_input":"2022-01-02T05:10:30.655432Z","iopub.status.idle":"2022-01-02T05:10:30.728444Z","shell.execute_reply.started":"2022-01-02T05:10:30.655403Z","shell.execute_reply":"2022-01-02T05:10:30.727488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = plays['down'].value_counts().reset_index()\n\ncheck.columns = [\n    'down', \n    'plays'\n]\n\ncheck = check.sort_values('plays')\n\nfig = px.pie(\n    check, \n    names='down', \n    values=\"plays\",  \n    title='Number of plays of every down',\n    height=500,\n    width=800\n)\n\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:10:41.745952Z","iopub.execute_input":"2022-01-02T05:10:41.746753Z","iopub.status.idle":"2022-01-02T05:10:41.801282Z","shell.execute_reply.started":"2022-01-02T05:10:41.746711Z","shell.execute_reply":"2022-01-02T05:10:41.800498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = plays['yardsToGo'].value_counts().reset_index()\n\ncheck.columns = [\n    'yardsToGo', \n    'plays'\n]\n\ncheck['yardsToGo'] = check['yardsToGo'].astype(str) + '-'\ncheck = check.sort_values('plays')\n\nfig = px.bar(\n    check, \n    y='yardsToGo', \n    x=\"plays\", \n    orientation='h', \n    title='Number of plays for every yards to go category',\n    height=800,\n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:10:51.085525Z","iopub.execute_input":"2022-01-02T05:10:51.086331Z","iopub.status.idle":"2022-01-02T05:10:51.155114Z","shell.execute_reply.started":"2022-01-02T05:10:51.086285Z","shell.execute_reply":"2022-01-02T05:10:51.154272Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = plays['possessionTeam'].value_counts().reset_index()\n\ncheck.columns = [\n    'team', \n    'plays'\n]\n\ncheck = check.sort_values('plays')\n\nfig = px.bar(\n    check, \n    y='team', \n    x=\"plays\", \n    orientation='h', \n    title='Number of plays for every team',\n    height=800,\n    width=800\n)\n\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:11:02.305686Z","iopub.execute_input":"2022-01-02T05:11:02.305983Z","iopub.status.idle":"2022-01-02T05:11:02.377851Z","shell.execute_reply.started":"2022-01-02T05:11:02.305949Z","shell.execute_reply":"2022-01-02T05:11:02.376917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = plays['yardlineSide'].value_counts().reset_index()\n\ncheck.columns = [\n    'yardlineSide', \n    'plays'\n]\n\ncheck = check.sort_values('plays')\n\nfig = px.bar(\n    check, \n    y='yardlineSide', \n    x=\"plays\", \n    orientation='h', \n    title='Number of plays for every team yard side',\n    height=800,\n    width=800\n)\n\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:11:15.125553Z","iopub.execute_input":"2022-01-02T05:11:15.125845Z","iopub.status.idle":"2022-01-02T05:11:15.194994Z","shell.execute_reply.started":"2022-01-02T05:11:15.125815Z","shell.execute_reply":"2022-01-02T05:11:15.194191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = plays['yardlineNumber'].value_counts().reset_index()\n\ncheck.columns = [\n    'yardline', \n    'plays'\n]\n\ncheck = check.sort_values('plays')\n\nfig = px.bar(\n    check, \n    x='yardline', \n    y=\"plays\",  \n    title='Number of plays for every yardline',\n    height=500,\n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:11:26.904834Z","iopub.execute_input":"2022-01-02T05:11:26.905165Z","iopub.status.idle":"2022-01-02T05:11:26.973982Z","shell.execute_reply.started":"2022-01-02T05:11:26.905115Z","shell.execute_reply":"2022-01-02T05:11:26.973062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.histogram(\n    plays, \n    x='absoluteYardlineNumber',\n    width=800,\n    height=500,\n    nbins=50,\n    title='Absolute Yardline Number distribution'\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:11:35.985455Z","iopub.execute_input":"2022-01-02T05:11:35.985726Z","iopub.status.idle":"2022-01-02T05:11:36.149383Z","shell.execute_reply.started":"2022-01-02T05:11:35.985696Z","shell.execute_reply":"2022-01-02T05:11:36.148477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check = plays['passResult'].value_counts().reset_index()\n\ncheck.columns = [\n    'passResult', \n    'plays'\n]\n\ncheck = check.sort_values('plays')\n\nfig = px.pie(\n    check, \n    names='passResult', \n    values=\"plays\",  \n    title='Number of plays for every pass result',\n    height=500,\n    width=800\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:11:45.335511Z","iopub.execute_input":"2022-01-02T05:11:45.335811Z","iopub.status.idle":"2022-01-02T05:11:45.389177Z","shell.execute_reply.started":"2022-01-02T05:11:45.335778Z","shell.execute_reply":"2022-01-02T05:11:45.388536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.histogram(\n    plays, \n    x=\"playResult\",\n    width=800,\n    height=500,\n    nbins=50,\n    title='Play result distribution'\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:11:54.027728Z","iopub.execute_input":"2022-01-02T05:11:54.028539Z","iopub.status.idle":"2022-01-02T05:11:54.167501Z","shell.execute_reply.started":"2022-01-02T05:11:54.028496Z","shell.execute_reply":"2022-01-02T05:11:54.166595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.histogram(\n    plays, \n    x=\"preSnapVisitorScore\",\n    width=800,\n    height=500,\n    nbins=50,\n    title='Pre Snap Visitor Score distribution'\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:12:04.905771Z","iopub.execute_input":"2022-01-02T05:12:04.906090Z","iopub.status.idle":"2022-01-02T05:12:05.041493Z","shell.execute_reply.started":"2022-01-02T05:12:04.906057Z","shell.execute_reply":"2022-01-02T05:12:05.040677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.histogram(\n    plays, \n    x=\"preSnapHomeScore\",\n    width=800,\n    height=500,\n    nbins=50,\n    title='Pre Snap Home Score distribution'\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:12:16.636109Z","iopub.execute_input":"2022-01-02T05:12:16.636536Z","iopub.status.idle":"2022-01-02T05:12:16.901727Z","shell.execute_reply.started":"2022-01-02T05:12:16.636503Z","shell.execute_reply":"2022-01-02T05:12:16.900853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"4. Tracking Data","metadata":{}},{"cell_type":"code","source":"tracking2018 = pd.read_csv('../input/nfl-big-data-bowl-2022/tracking2018.csv')\ntracking2018.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:12:43.785864Z","iopub.execute_input":"2022-01-02T05:12:43.786180Z","iopub.status.idle":"2022-01-02T05:13:31.236464Z","shell.execute_reply.started":"2022-01-02T05:12:43.786143Z","shell.execute_reply":"2022-01-02T05:13:31.234070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"2018123000 and playId == 36","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 8))\ntracking2018.query('gameId == 2018123000 and playId == 36').groupby('team') \\\n    .plot(x='x', y='y', ax=ax, style='.')\nplt.legend().remove();","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:13:31.243371Z","iopub.execute_input":"2022-01-02T05:13:31.244988Z","iopub.status.idle":"2022-01-02T05:13:32.058161Z","shell.execute_reply.started":"2022-01-02T05:13:31.244678Z","shell.execute_reply":"2022-01-02T05:13:32.057444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"gameId == 2018091001 and playId == 4033","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 8))\ntracking2018.query('gameId == 2018091001 and playId == 4033').groupby('team') \\\n    .plot(x='x', y='y', ax=ax, style='.')\nplt.legend().remove();","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:13:42.108769Z","iopub.execute_input":"2022-01-02T05:13:42.109956Z","iopub.status.idle":"2022-01-02T05:13:42.516220Z","shell.execute_reply.started":"2022-01-02T05:13:42.109879Z","shell.execute_reply":"2022-01-02T05:13:42.515192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"gameId == 2018091609 and position == \"CB\"","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 8))\ntracking2018.query('gameId == 2018091609 and position == \"CB\"').groupby('team') \\\n    .plot(x='x', y='y', ax=ax, style='.')\nplt.legend().remove();","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:14:14.656153Z","iopub.execute_input":"2022-01-02T05:14:14.656446Z","iopub.status.idle":"2022-01-02T05:14:15.419783Z","shell.execute_reply.started":"2022-01-02T05:14:14.656415Z","shell.execute_reply":"2022-01-02T05:14:15.418920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"gameId == 2018091609 and position == \"LB\"","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 8))\ntracking2018.query('gameId == 2018091609 and position == \"LB\"').groupby('team') \\\n    .plot(x='x', y='y', ax=ax, style='.')\nplt.legend().remove();","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:14:40.785986Z","iopub.execute_input":"2022-01-02T05:14:40.786336Z","iopub.status.idle":"2022-01-02T05:14:41.526059Z","shell.execute_reply.started":"2022-01-02T05:14:40.786299Z","shell.execute_reply":"2022-01-02T05:14:41.525109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"gameId == 2018091609 and position == \"RB\"","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 8))\ntracking2018.query('gameId == 2018091609 and position == \"RB\"').groupby('team') \\\n    .plot(x='x', y='y', ax=ax, style='.')\nplt.legend().remove();","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:15:00.025115Z","iopub.execute_input":"2022-01-02T05:15:00.025407Z","iopub.status.idle":"2022-01-02T05:15:00.759728Z","shell.execute_reply.started":"2022-01-02T05:15:00.025375Z","shell.execute_reply":"2022-01-02T05:15:00.758683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"5. Football field 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":{"execution":{"iopub.status.busy":"2022-01-02T05:15:45.218211Z","iopub.execute_input":"2022-01-02T05:15:45.218495Z","iopub.status.idle":"2022-01-02T05:15:45.243907Z","shell.execute_reply.started":"2022-01-02T05:15:45.218465Z","shell.execute_reply":"2022-01-02T05:15:45.243280Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = drawPitch(100, 53.3)\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:15:51.345802Z","iopub.execute_input":"2022-01-02T05:15:51.346646Z","iopub.status.idle":"2022-01-02T05:15:51.979716Z","shell.execute_reply.started":"2022-01-02T05:15:51.346588Z","shell.execute_reply":"2022-01-02T05:15:51.978801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Function to create animation","metadata":{}},{"cell_type":"code","source":"games_ids = {}\ngames_tracking2018 = tracking2018.groupby(by=[\"gameId\"])\nfor game, data in games_tracking2018:\n    games_ids[game] = list(set(data.playId.tolist()))","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:17:01.956630Z","iopub.execute_input":"2022-01-02T05:17:01.957053Z","iopub.status.idle":"2022-01-02T05:17:05.602393Z","shell.execute_reply.started":"2022-01-02T05:17:01.956994Z","shell.execute_reply":"2022-01-02T05:17:05.601581Z"},"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":{"execution":{"iopub.status.busy":"2022-01-02T05:17:12.005807Z","iopub.execute_input":"2022-01-02T05:17:12.006145Z","iopub.status.idle":"2022-01-02T05:17:12.016102Z","shell.execute_reply.started":"2022-01-02T05:17:12.006103Z","shell.execute_reply":"2022-01-02T05:17:12.015068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from matplotlib import animation\nfrom IPython.display import HTML\ndef 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":{"execution":{"iopub.status.busy":"2022-01-02T05:17:25.165679Z","iopub.execute_input":"2022-01-02T05:17:25.166217Z","iopub.status.idle":"2022-01-02T05:17:25.184656Z","shell.execute_reply.started":"2022-01-02T05:17:25.166179Z","shell.execute_reply":"2022-01-02T05:17:25.183738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"animate_one_play(2018123000, 36, tracking2018)","metadata":{"execution":{"iopub.status.busy":"2022-01-02T05:17:31.925347Z","iopub.execute_input":"2022-01-02T05:17:31.925615Z","iopub.status.idle":"2022-01-02T05:17:43.434966Z","shell.execute_reply.started":"2022-01-02T05:17:31.925586Z","shell.execute_reply":"2022-01-02T05:17:43.434109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}