{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# PART 1: Import Data and Dataframe Creation","metadata":{}},{"cell_type":"code","source":"from sklearn.datasets import fetch_20newsgroups\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nplays_raw_data = pd.read_csv(\"../input/nfl-big-data-bowl-2022/plays.csv\")\nplays = plays_raw_data\n\n# type - results\nspecialTeamsPlay = plays.groupby(['specialTeamsResult', 'specialTeamsPlayType']).size().unstack()\nspecialTeamsPlay","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:10.162319Z","iopub.execute_input":"2022-01-06T12:22:10.162631Z","iopub.status.idle":"2022-01-06T12:22:11.649296Z","shell.execute_reply.started":"2022-01-06T12:22:10.162547Z","shell.execute_reply":"2022-01-06T12:22:11.647844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plays_Punt = plays.loc[plays.specialTeamsPlayType=='Punt'].groupby(['specialTeamsResult', 'specialTeamsPlayType']).size().unstack()\n# plays_Kickoff = plays.loc[plays.specialTeamsPlayType=='Kickoff'].groupby(['specialTeamsResult', 'specialTeamsPlayType']).size().unstack()\n# plays_FieldGoal = plays.loc[plays.specialTeamsPlayType=='Field Goal'].groupby(['specialTeamsResult', 'specialTeamsPlayType']).size().unstack()\n# plays_ExtraPoint = plays.loc[plays.specialTeamsPlayType=='Extra Point'].groupby(['specialTeamsResult', 'specialTeamsPlayType']).size().unstack()\n\n# plays_Punt_Result = ['Blocked Punt', 'Downed', 'Fair Catch','Muffed', 'Non-Special Teams Result', 'Out of Bounds', 'Return', 'Touchback']\n# plays_Punt","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.651196Z","iopub.execute_input":"2022-01-06T12:22:11.651434Z","iopub.status.idle":"2022-01-06T12:22:11.656118Z","shell.execute_reply.started":"2022-01-06T12:22:11.651403Z","shell.execute_reply":"2022-01-06T12:22:11.655096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plays_Kickoff_Result = ['Downed', 'Fair Catch', 'Kickoff Team Recovery', 'Muffed', 'Out of Bounds', 'Return', 'Touchback']\n# plays_Kickoff","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.657945Z","iopub.execute_input":"2022-01-06T12:22:11.658201Z","iopub.status.idle":"2022-01-06T12:22:11.671063Z","shell.execute_reply.started":"2022-01-06T12:22:11.658173Z","shell.execute_reply":"2022-01-06T12:22:11.669266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plays_FieldGoal_Result = ['Blocked Kick Attempt', 'Downed', 'Kick Attempt Good', 'Kick Attempt No Good', 'Non-Special Teams Result', 'Out of Bounds']\n# plays_FieldGoal","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.672705Z","iopub.execute_input":"2022-01-06T12:22:11.672899Z","iopub.status.idle":"2022-01-06T12:22:11.684692Z","shell.execute_reply.started":"2022-01-06T12:22:11.672876Z","shell.execute_reply":"2022-01-06T12:22:11.683516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plays_ExtraPoint_Result = ['Blocked Kick Attempt', 'Kick Attempt Good', 'Kick Attempt No Good', 'Non-Special Teams Result']\n# plays_ExtraPoint","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.686511Z","iopub.execute_input":"2022-01-06T12:22:11.687559Z","iopub.status.idle":"2022-01-06T12:22:11.698617Z","shell.execute_reply.started":"2022-01-06T12:22:11.687517Z","shell.execute_reply":"2022-01-06T12:22:11.698123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# specialTeamsResultList = ['Blocked Kick Attempt', 'Blocked Punt', 'Downed', \n#                           'Fair Catch', 'Kick Attempt Good', 'Kick Attempt No Good', \n#                           'Kickoff Team Recovery', 'Muffed', 'Non-Special Teams Result', \n#                           'Out of Bounds', 'Return', 'Touchback']\n# plt.figure(figsize=(8,8))\n# plt.pie(plays_ExtraPoint['Extra Point'], explode=(0.5,0.3,0.1,0.5), autopct='%1.1f%%' )\n# plt.legend(loc=7,  labels = plays_ExtraPoint_Result, title = \"Extra Point:\", bbox_to_anchor=(0.6, 0.7))\n# plt.show()\n\n# plt.figure(figsize=(8,8))\n# plt.pie(plays_FieldGoal['Field Goal'], explode=(0.5, 0.5,0.1,0.1,0.5,0.5), autopct='%1.1f%%')\n# plt.legend(loc=7,  labels = plays_FieldGoal_Result, title = \"Field Goal:\", bbox_to_anchor=(0.85, 0.8))\n# plt.show()\n\n# plt.figure(figsize=(8,8))\n# plt.pie(plays_Kickoff['Kickoff'], explode=(0.5,0.5,0.5,0.5,0.5,0.1,0.1), autopct='%1.1f%%')\n# plt.legend(loc=7,  labels = plays_Kickoff_Result, title = \"Kickoff:\", bbox_to_anchor=(1, 0.2))\n# plt.show()\n\n# plt.figure(figsize=(8,8))\n# plt.pie(plays_Punt['Punt'], explode=(0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1), autopct='%1.1f%%' )\n# plt.legend(loc=7,  labels = plays_Punt_Result, title = \"Punt:\", bbox_to_anchor=(1.5, 0.5))\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.69975Z","iopub.execute_input":"2022-01-06T12:22:11.700028Z","iopub.status.idle":"2022-01-06T12:22:11.712661Z","shell.execute_reply.started":"2022-01-06T12:22:11.699988Z","shell.execute_reply":"2022-01-06T12:22:11.711287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a dataframe that shows the frequency play results with the involvement of each player in kick","metadata":{}},{"cell_type":"code","source":"import numpy as np\n\n# player - results\nkickers_results = plays.groupby(['kickerId','specialTeamsResult']).size().unstack().replace(np.nan, 0).reset_index()\nkickers_results","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.714002Z","iopub.execute_input":"2022-01-06T12:22:11.714299Z","iopub.status.idle":"2022-01-06T12:22:11.763128Z","shell.execute_reply.started":"2022-01-06T12:22:11.714262Z","shell.execute_reply":"2022-01-06T12:22:11.762273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a dataframe that shows the frequency play results with the involvement of each player in return","metadata":{}},{"cell_type":"code","source":"returners_results = plays.groupby(['returnerId','specialTeamsResult']).size().unstack().replace(np.nan, 0).reset_index()\nreturners_results","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.765257Z","iopub.execute_input":"2022-01-06T12:22:11.766046Z","iopub.status.idle":"2022-01-06T12:22:11.795881Z","shell.execute_reply.started":"2022-01-06T12:22:11.766004Z","shell.execute_reply":"2022-01-06T12:22:11.795426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Read the players dataset and define a function that query players name","metadata":{}},{"cell_type":"code","source":"players_raw_data = pd.read_csv(\"../input/nfl-big-data-bowl-2022/players.csv\")\nplayers = players_raw_data\n\ndef queryName(i):\n    name = players.query('nflId == @i').displayName.values\n    return name ","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.796857Z","iopub.execute_input":"2022-01-06T12:22:11.797584Z","iopub.status.idle":"2022-01-06T12:22:11.817931Z","shell.execute_reply.started":"2022-01-06T12:22:11.797557Z","shell.execute_reply":"2022-01-06T12:22:11.817295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Getting the returners' names","metadata":{}},{"cell_type":"code","source":"X=plays\nIDList = X.returnerId\nNameList = []\nfor i in IDList.values:\n    try:\n        if isinstance(i, float):\n            NameList.append(np.nan)\n        else:\n            NameList.append(queryName(int(float(i)))[0])\n    except:\n        NameList.append(np.nan)\n\nX['returner_name'] = NameList\nreturnerName_results = X.groupby(['returner_name','specialTeamsResult']).size().unstack().replace(np.nan, 0).reset_index()\nreturnerName_results","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:11.820902Z","iopub.execute_input":"2022-01-06T12:22:11.822243Z","iopub.status.idle":"2022-01-06T12:22:25.473114Z","shell.execute_reply.started":"2022-01-06T12:22:11.822176Z","shell.execute_reply":"2022-01-06T12:22:25.472058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Getting the kickers' names","metadata":{}},{"cell_type":"code","source":"IDList = X.kickerId\nNameList = []\nfor i in IDList.values:\n    try:\n        if isinstance(i, int):\n            NameList.append(np.nan)\n        else:\n            NameList.append(queryName(i)[0])\n    except:\n        NameList.append(np.nan)\nX['kicker_name'] = NameList\nkickerName_results = X.groupby(['kicker_name','specialTeamsResult']).size().unstack().replace(np.nan, 0).reset_index()\nkickerName_results","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:22:25.475467Z","iopub.execute_input":"2022-01-06T12:22:25.475661Z","iopub.status.idle":"2022-01-06T12:23:04.475222Z","shell.execute_reply.started":"2022-01-06T12:22:25.475636Z","shell.execute_reply":"2022-01-06T12:23:04.47434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Remove duplicates","metadata":{}},{"cell_type":"code","source":"# Drop these two rows because of duplicated names:\nkickerName_results = kickerName_results[kickerName_results.kicker_name != \"Aaron Brewer\"]\nkickerName_results = kickerName_results[kickerName_results.kicker_name != \"Chris Jones\"]\nkickerName_results = kickerName_results.reset_index(drop=True)\nkickerName_results","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:04.476446Z","iopub.execute_input":"2022-01-06T12:23:04.476704Z","iopub.status.idle":"2022-01-06T12:23:04.515838Z","shell.execute_reply.started":"2022-01-06T12:23:04.47667Z","shell.execute_reply":"2022-01-06T12:23:04.5149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Get the BMI and position for kicker dataframe","metadata":{}},{"cell_type":"code","source":"def queryHeight(i):\n    height = players.query('`displayName` == @i').height.values\n    return height\ndef queryWeight(i):\n    weight = players.query('`displayName` == @i').weight.values\n    return weight\ndef feetToM(f,i):\n    i += f * 12\n    return round(i * 2.54, 1)/100\ndef queryPosition(i):\n    position = players.query('`displayName` == @i').Position.values\n    return position\ndef getPositionIndex(i):\n    if i == \"WR\":\n        return 0\n    elif i == \"RB\":\n        return 1\n    elif i == \"CB\":\n        return 2\n    elif i == \"TE\":\n        return 3\n    elif i == \"FB\":\n        return 4\n    elif i == \"FS\":\n        return 5\n    elif i == \"SS\":\n        return 6\n    elif i == \"ILB\":\n        return 7\n    elif i == \"OLB\":\n        return 8\n    elif i == \"MLB\":\n        return 9\n    elif i == \"QB\":\n        return 10\n    elif i == \"NT\":\n        return 11\n    elif i == \"LB\":\n        return 12\n    elif i == \"DE\":\n        return 13\n    elif i == \"G\":\n        return 14\n    elif i == \"DB\":\n        return 15\n    elif i == \"P\":\n        return 16\n    elif i == \"K\":\n        return 17\n    else:\n        return 20\n\nNameList = kickerName_results.kicker_name\nHeightList = []\nHeightList2 = []\nWeightList = []\nBMI = []\nPositionList = []\n\n# Obtain H and W \nfor i in NameList.values:\n    try:\n        HeightList.append(queryHeight(i)[0])\n        WeightList.append(queryWeight(i)[0])\n    except:\n        HeightList.append(np.nan)\n        WeightList.append(np.nan)\n\n# Change height scale\nfor i in HeightList:\n    try: \n        feet = i.split('-')[0]\n        inch = i.split('-')[1]\n        m = feetToM(float(feet),float(inch))\n        HeightList2.append(m)\n    except:\n        feet = [char for char in i][0]\n        inch = [char for char in i][1]\n        m = feetToM(float(feet),float(inch))\n        HeightList2.append(m)    \n\n# Compute BMI\nfor h, w in zip(HeightList2, WeightList):\n    BMI.append(round(w * 0.453592 / (h * h), 2))\n    \n# Obtain Position\nfor i in NameList.values:\n    try:\n        PositionList.append(getPositionIndex(queryPosition(i)[0]))\n    except:\n        PositionList.append(np.nan)\n        \nkickerName_results2 = kickerName_results.copy(deep=True)\nkickerName_results2['BMI'] = BMI\nkickerName_results2['Position'] = PositionList\nkickerName_results2","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:04.517671Z","iopub.execute_input":"2022-01-06T12:23:04.518335Z","iopub.status.idle":"2022-01-06T12:23:05.189411Z","shell.execute_reply.started":"2022-01-06T12:23:04.518307Z","shell.execute_reply":"2022-01-06T12:23:05.18889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Get the BMI and position for returner dataframe","metadata":{}},{"cell_type":"code","source":"IDList = X.returnerId\n    \nNameList = returnerName_results.returner_name\nHeightList = []\nHeightList2 = []\nWeightList = []\nBMI = []\nPositionList = []\n\n# Obtain H and W \nfor i in NameList.values:\n    try:\n        HeightList.append(queryHeight(i)[0])\n        WeightList.append(queryWeight(i)[0])\n    except:\n        HeightList.append(np.nan)\n        WeightList.append(np.nan)\n\n# Change height scale\nfor i in HeightList:\n    try: \n        feet = i.split('-')[0]\n        inch = i.split('-')[1]\n        m = feetToM(float(feet),float(inch))\n        HeightList2.append(m)\n    except:\n        feet = [char for char in i][0]\n        inch = [char for char in i][1]\n        m = feetToM(float(feet),float(inch))\n        HeightList2.append(m)    \n\n# Compute BMI\nfor h, w in zip(HeightList2, WeightList):\n    BMI.append(round(w * 0.453592 / (h * h), 2))\n    \n# Obtain Position\nfor i in NameList.values:\n    try:\n        PositionList.append(getPositionIndex(queryPosition(i)[0]))\n    except:\n        PositionList.append(np.nan)\n#         print('haha')\n      \nreturnerName_results2 = returnerName_results.copy(deep=True)\nreturnerName_results2['BMI'] = BMI\nreturnerName_results2['Position'] = PositionList\nreturnerName_results2","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:05.190301Z","iopub.execute_input":"2022-01-06T12:23:05.190547Z","iopub.status.idle":"2022-01-06T12:23:07.181671Z","shell.execute_reply.started":"2022-01-06T12:23:05.190516Z","shell.execute_reply":"2022-01-06T12:23:07.181011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import seaborn as sns\n# plt.figure(figsize=(15,30))\n# ax = sns.heatmap(kickerName_results,\n#                  cmap=\"PuRd\",\n#                  vmin=0, vmax=200, annot=True)\n\n# returnerName_results2['Position'].value_counts()\n# a = returnerName_results2\n# a['Position'].replace({\"WR\": 0, \"b\": \"y\"}, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:07.182677Z","iopub.execute_input":"2022-01-06T12:23:07.182879Z","iopub.status.idle":"2022-01-06T12:23:07.187969Z","shell.execute_reply.started":"2022-01-06T12:23:07.182853Z","shell.execute_reply":"2022-01-06T12:23:07.186884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players_df = pd.read_csv('/kaggle/input/nfl-big-data-bowl-2022/players.csv')\nplayers_df = players_df[players_df.Position != \"WR\"]\nplayers_df = players_df[players_df.Position != \"CB\"]\nplayers_df = players_df[players_df.Position != \"DE\"]\nplayers_df = players_df[players_df.Position != \"OLB\"]\nplayers_df = players_df[players_df.Position != \"TE\"]\nplayers_df = players_df[players_df.Position != \"T\"]\nplayers_df = players_df[players_df.Position != \"RB\"]\nplayers_df = players_df[players_df.Position != \"DT\"]\nplayers_df = players_df[players_df.Position != \"ILB\"]\nplayers_df = players_df[players_df.Position != \"FS\"]\nplayers_df = players_df[players_df.Position != \"SS\"]\nplayers_df = players_df[players_df.Position != \"C\"]\nplayers_df = players_df[players_df.Position != \"NT\"]\nplayers_df = players_df[players_df.Position != \"DB\"]\nplayers_df = players_df[players_df.Position != \"LB\"]\nplayers_df = players_df[players_df.Position != \"MLB\"]\nplayers_df = players_df[players_df.Position != \"FB\"]\nplayers_df = players_df[players_df.Position != \"OT\"]\nplayers_df = players_df[players_df.Position != \"QB\"]\nplayers_df = players_df[players_df.Position != \"S\"]\nplayers_df = players_df[players_df.Position != \"OG\"]\nplayers_df = players_df[players_df.Position != \"HB\"]\nheight_dict = {\n    \"5-10\": 178,\n    \"5-11\": 180,\n    \"5-6\": 168,\n    \"5-7\": 170,\n    \"5-8\": 173,\n    \"5-9\": 175,\n    \"6-0\": 183,\n    \"6-1\": 185,\n    \"6-2\": 188,\n    \"6-3\": 190,\n    \"6-4\": 193,\n    \"6-5\": 196,\n    \"6-6\": 198,\n    \"6-7\": 201,\n    \"6-8\": 203,\n    \"6-9\": 206,\n    \"66\": 168,\n    \"67\": 170,\n    \"68\": 173,\n    \"69\": 175,\n    \"70\": 178,\n    \"71\": 180,\n    \"72\": 183,\n    \"73\": 185,\n    \"74\": 188,\n    \"75\": 191,\n    \"76\": 193,\n    \"77\": 196,\n    \"78\": 198,\n    \"79\": 201\n}\nplayers_df[\"height_cm\"] = players_df[\"height\"].replace(height_dict)\nplayers_df[\"height_m2\"] = players_df[\"height_cm\"]*0.01*players_df[\"height_cm\"]*0.01\nplayers_df[\"weight_kg\"] = players_df[\"weight\"]*0.45359237","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:38.314201Z","iopub.execute_input":"2022-01-06T12:23:38.314437Z","iopub.status.idle":"2022-01-06T12:23:38.36212Z","shell.execute_reply.started":"2022-01-06T12:23:38.314413Z","shell.execute_reply":"2022-01-06T12:23:38.360887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import plotly.express as px\nfig = px.box(players_df,x=\"Position\",y=\"height_cm\",points = \"all\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:40.58925Z","iopub.execute_input":"2022-01-06T12:23:40.589527Z","iopub.status.idle":"2022-01-06T12:23:43.409677Z","shell.execute_reply.started":"2022-01-06T12:23:40.589499Z","shell.execute_reply":"2022-01-06T12:23:43.409164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.box(players_df,x=\"Position\",y=\"weight_kg\", points = \"all\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:46.439742Z","iopub.execute_input":"2022-01-06T12:23:46.440157Z","iopub.status.idle":"2022-01-06T12:23:46.517995Z","shell.execute_reply.started":"2022-01-06T12:23:46.440119Z","shell.execute_reply":"2022-01-06T12:23:46.51736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players_df[\"bmi\"] = players_df[\"weight_kg\"]/players_df[\"height_m2\"]\nfig = px.box(players_df,x=\"Position\",y=\"bmi\", points = \"all\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:47.664214Z","iopub.execute_input":"2022-01-06T12:23:47.664613Z","iopub.status.idle":"2022-01-06T12:23:47.743213Z","shell.execute_reply.started":"2022-01-06T12:23:47.664561Z","shell.execute_reply":"2022-01-06T12:23:47.741753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import random\ncolor_dict = {\n    \"G\": 'red',\n    \"K\": 'limegreen',\n    \"P\": 'royalblue',\n    \"LS\": 'purple',\n    \"WR\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"CB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"DE\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"OLB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"TE\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"T\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"RB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"DT\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"ILB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"FS\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"SS\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"C\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"NT\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"DB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"MLB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"FB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"OT\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"QB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"S\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"OG\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"HB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)]),\n    \"LB\": \"#\"+''.join([random.choice('0123456789ABCDEF') for j in range(6)])\n}\nplayers_df[\"color\"] = players_df[\"Position\"].replace(color_dict)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:48.956231Z","iopub.execute_input":"2022-01-06T12:23:48.956493Z","iopub.status.idle":"2022-01-06T12:23:48.979519Z","shell.execute_reply.started":"2022-01-06T12:23:48.956465Z","shell.execute_reply":"2022-01-06T12:23:48.978943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfig = plt.figure(figsize=(10, 6))\nplayers_df[\"nomalized_bmi\"]=(players_df[\"bmi\"]-players_df[\"bmi\"].min())/(players_df[\"bmi\"].max()-players_df[\"bmi\"].min())*100\nplt.scatter(players_df[\"height_cm\"], players_df[\"weight_kg\"],c=players_df[\"color\"], s=players_df[\"nomalized_bmi\"],alpha=0.5)\nplt.xlabel('height_cm')\nplt.ylabel('weight_kg')\n\n\nimport matplotlib.patches as mpatches\nfrom collections import OrderedDict\n# plot the color description bar\ncolorlist = zip(players_df['Position'], players_df['color'])\ncolorlist = list(OrderedDict.fromkeys(colorlist))\nhandles = [mpatches.Patch(color=colour, label=label) for label, colour in colorlist]\ncolorlist = [i[0] for i in colorlist]\nplt.legend(handles, colorlist, bbox_to_anchor=(1.1, 1))\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:53.699128Z","iopub.execute_input":"2022-01-06T12:23:53.699536Z","iopub.status.idle":"2022-01-06T12:23:53.886995Z","shell.execute_reply.started":"2022-01-06T12:23:53.699509Z","shell.execute_reply":"2022-01-06T12:23:53.886301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# PART 2: CLUSTERING - RETURNER","metadata":{}},{"cell_type":"markdown","source":"Clustering: find the pattern of returner's information and play results. Preprocessing:","metadata":{}},{"cell_type":"code","source":"# clustering preprocessing \nfrom sklearn.preprocessing import MinMaxScaler\n\n# Instantiate the object\nreturnerName_results3 = returnerName_results2.drop('returner_name', 1)\n\nscaler = MinMaxScaler()\n# Fit and transform the data\n# StandardScaler()\nreturnerName_results3 = scaler.fit_transform(returnerName_results3)\nreturnerName_results3","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:07.232315Z","iopub.execute_input":"2022-01-06T12:23:07.232982Z","iopub.status.idle":"2022-01-06T12:23:07.25918Z","shell.execute_reply.started":"2022-01-06T12:23:07.23292Z","shell.execute_reply":"2022-01-06T12:23:07.257887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Find the optimum number of clusters","metadata":{}},{"cell_type":"code","source":"returnerName_results3.shape","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:07.260481Z","iopub.execute_input":"2022-01-06T12:23:07.261105Z","iopub.status.idle":"2022-01-06T12:23:07.270695Z","shell.execute_reply.started":"2022-01-06T12:23:07.261038Z","shell.execute_reply":"2022-01-06T12:23:07.269568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import the library\nfrom sklearn.cluster import KMeans\nimport seaborn as sns\nnp.random.seed(42)\ninertia = []\n\nstart = 1\nend = 20\n\n# Iterating the process\nfor i in range(start, end):\n  # Instantiate the model\n    model = KMeans(n_clusters=i)\n  # Fit The Model\n    model.fit(returnerName_results3)\n  # Extract the error of the model\n    inertia.append(model.inertia_)# Visualize the model\nsns.pointplot(x=list(range(start, end)), y=inertia)\nplt.title('SSE on K-Means based on # of clusters')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:07.272308Z","iopub.execute_input":"2022-01-06T12:23:07.272561Z","iopub.status.idle":"2022-01-06T12:23:09.283607Z","shell.execute_reply.started":"2022-01-06T12:23:07.272526Z","shell.execute_reply":"2022-01-06T12:23:09.282397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"clustering","metadata":{}},{"cell_type":"code","source":"np.random.seed(42)\n\n# Instantiate the model\nresults_returner = returnerName_results2.copy(deep=True)\nmodel = KMeans(n_clusters=10)\n\n# Fit the model\nmodel.fit(returnerName_results3)\n# Predict the cluster from the data and save it\ncluster = model.predict(returnerName_results3)\n# Add to the dataframe and show the result\nresults_returner['cluster'] = cluster\nresults_returner","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:09.285222Z","iopub.execute_input":"2022-01-06T12:23:09.2857Z","iopub.status.idle":"2022-01-06T12:23:09.379234Z","shell.execute_reply.started":"2022-01-06T12:23:09.285665Z","shell.execute_reply":"2022-01-06T12:23:09.378259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"visualisation:","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\nimport matplotlib.pyplot as plt\n\n# Create the dataframe to ease our visualization process\nvisualize = pd.DataFrame(model.cluster_centers_) #.reset_index()\nvisualize = visualize.T\nvisualize['column'] = ['Return', 'Fair Catch', 'Muffed', 'Kick Attempt No Good', 'BMI', 'Position']\nvisualize = visualize.melt(id_vars=['column'], var_name='cluster')\nvisualize['cluster'] = visualize.cluster.astype('category')\n# Visualize the result\nplt.figure(figsize=(12, 8))\nsns.barplot(x='cluster', y='value', hue='column', data=visualize)\nplt.title('The cluster\\'s characteristics')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:09.382576Z","iopub.execute_input":"2022-01-06T12:23:09.3828Z","iopub.status.idle":"2022-01-06T12:23:09.900641Z","shell.execute_reply.started":"2022-01-06T12:23:09.382772Z","shell.execute_reply":"2022-01-06T12:23:09.899499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"visualize","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:09.902188Z","iopub.execute_input":"2022-01-06T12:23:09.902554Z","iopub.status.idle":"2022-01-06T12:23:09.922848Z","shell.execute_reply.started":"2022-01-06T12:23:09.902522Z","shell.execute_reply":"2022-01-06T12:23:09.92204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# PART 3: CLUSTERING - KICKER","metadata":{}},{"cell_type":"code","source":"# Instantiate the object\nkickerName_results3 = kickerName_results2.drop('kicker_name', 1)\n\nscaler = MinMaxScaler()\n# Fit and transform the data\n# StandardScaler()\nkickerName_results3 = scaler.fit_transform(kickerName_results3)\nkickerName_results3","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:09.924088Z","iopub.execute_input":"2022-01-06T12:23:09.924409Z","iopub.status.idle":"2022-01-06T12:23:09.938809Z","shell.execute_reply.started":"2022-01-06T12:23:09.924373Z","shell.execute_reply":"2022-01-06T12:23:09.937408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kickerName_results3.shape","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:09.942297Z","iopub.execute_input":"2022-01-06T12:23:09.94254Z","iopub.status.idle":"2022-01-06T12:23:09.949747Z","shell.execute_reply.started":"2022-01-06T12:23:09.942509Z","shell.execute_reply":"2022-01-06T12:23:09.948535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.random.seed(42)\ninertia = []\n\nstart = 1\nend = 20\n\n# Iterating the process\nfor i in range(start, end):\n  # Instantiate the model\n    model = KMeans(n_clusters=i)\n  # Fit The Model\n    model.fit(kickerName_results3)\n  # Extract the error of the model\n    inertia.append(model.inertia_)# Visualize the model\nsns.pointplot(x=list(range(start, end)), y=inertia)\nplt.title('SSE on K-Means based on # of clusters')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:09.951038Z","iopub.execute_input":"2022-01-06T12:23:09.951256Z","iopub.status.idle":"2022-01-06T12:23:11.377Z","shell.execute_reply.started":"2022-01-06T12:23:09.951228Z","shell.execute_reply":"2022-01-06T12:23:11.375812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.random.seed(42)\n\n# Instantiate the model\nresults_kicker = kickerName_results2.copy(deep=True)\nmodel = KMeans(n_clusters=5)\n# Fit the model\nmodel.fit(kickerName_results3)\n# Predict the cluster from the data and save it\ncluster = model.predict(kickerName_results3)\n# Add to the dataframe and show the result\nresults_kicker['cluster'] = cluster\nresults_kicker","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:11.37855Z","iopub.execute_input":"2022-01-06T12:23:11.379181Z","iopub.status.idle":"2022-01-06T12:23:11.451268Z","shell.execute_reply.started":"2022-01-06T12:23:11.379141Z","shell.execute_reply":"2022-01-06T12:23:11.450236Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\nimport matplotlib.pyplot as plt\n\n# Create the dataframe to ease our visualization process\nvisualize = pd.DataFrame(model.cluster_centers_) #.reset_index()\nvisualize = visualize.T\nvisualize['column'] = ['Downed', 'Fair Catch', 'Muffed', 'Out of Bounds', 'Return', 'Touchback', 'Blocked Kick Attempt', 'Kick Attempt Good', 'Kick Attempt No Good', 'Kickoff Team Recovery', 'Blocked Punt', 'BMI', 'Position']\nvisualize = visualize.melt(id_vars=['column'], var_name='cluster')\nvisualize['cluster'] = visualize.cluster.astype('category')\n# Visualize the result\nplt.figure(figsize=(12, 8))\nsns.barplot(x='cluster', y='value', hue='column', data=visualize)\nplt.title('The cluster\\'s characteristics')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T12:23:11.452292Z","iopub.execute_input":"2022-01-06T12:23:11.452467Z","iopub.status.idle":"2022-01-06T12:23:12.062385Z","shell.execute_reply.started":"2022-01-06T12:23:11.452445Z","shell.execute_reply":"2022-01-06T12:23:12.0615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"# Exact statistics of plays.csv","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nplays=pd.read_csv('../input/nfl-big-data-bowl-2022/plays.csv')\nplays.describe(include='all').round(200)\n\n#19979 games total\n#top frequency of playdescription:W.Lutz kicks 65 yards from NO 35 to end zone\n#33 different possession teams top with 'BAL'\n#4 specialTeamsPlayTypes top with 'Kickoff'\n#12 specialTeamsResult top with 'KickAttempt Good'\n","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:38:58.712207Z","iopub.execute_input":"2022-01-06T20:38:58.712599Z","iopub.status.idle":"2022-01-06T20:38:58.957014Z","shell.execute_reply.started":"2022-01-06T20:38:58.71257Z","shell.execute_reply":"2022-01-06T20:38:58.95609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import libraries we want to use and get tracking data moved.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nimport seaborn as sns\nfrom ipywidgets import interact, fixed\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nfrom matplotlib import animation\nfrom matplotlib.animation import FFMpegWriter\npd.set_option('max_columns', 100)\n\nimport dateutil\nfrom math import radians\nfrom IPython.display import Video\n\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:52:32.559337Z","iopub.execute_input":"2022-01-06T20:52:32.559568Z","iopub.status.idle":"2022-01-06T20:52:32.566706Z","shell.execute_reply.started":"2022-01-06T20:52:32.559546Z","shell.execute_reply":"2022-01-06T20:52:32.566099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create a football field","metadata":{}},{"cell_type":"code","source":"def create_football_field(linenumbers=True,\n                          endzones=True,\n                          highlight_line=False,\n                          highlight_line_number=55,\n                          highlight_first_down_line=False,\n                          yards_to_go=10,\n                          highlighted_name='Line of Scrimmage',\n                          fifty_is_los=False,\n                          figsize=(12, 6.33)):\n    \"\"\"\n    Function that plots the football field for viewing plays.\n    Allows for showing or hiding endzones.\n    \"\"\"\n    rect = patches.Rectangle((0, 0), 120, 53.3, linewidth=0.1,\n                             edgecolor='r', facecolor='darkgreen', zorder=0)\n\n    fig, ax = plt.subplots(1, figsize=figsize)\n    ax.add_patch(rect)\n\n    plt.plot([10, 10, 10, 20, 20, 30, 30, 40, 40, 50, 50, 60, 60, 70, 70, 80,\n              80, 90, 90, 100, 100, 110, 110, 120, 0, 0, 120, 120],\n             [0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3,\n              53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 53.3, 0, 0, 53.3],\n             color='white')\n    if fifty_is_los:\n        plt.plot([60, 60], [0, 53.3], color='gold')\n        plt.text(62, 50, '<- Player Yardline at Snap', color='gold')\n    # Endzones\n    if endzones:\n        ez1 = patches.Rectangle((0, 0), 10, 53.3,\n                                linewidth=0.1,\n                                edgecolor='r',\n                                facecolor='blue',\n                                alpha=0.2,\n                                zorder=0)\n        ez2 = patches.Rectangle((110, 0), 120, 53.3,\n                                linewidth=0.1,\n                                edgecolor='r',\n                                facecolor='blue',\n                                alpha=0.2,\n                                zorder=0)\n        ax.add_patch(ez1)\n        ax.add_patch(ez2)\n    plt.xlim(0, 120)\n    plt.ylim(-5, 58.3)\n    plt.axis('off')\n    if linenumbers:\n        for x in range(20, 110, 10):\n            numb = x\n            if x > 50:\n                numb = 120 - x\n            plt.text(x, 5, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,  # fontname='Arial',\n                     color='white')\n            plt.text(x - 0.95, 53.3 - 5, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,  # fontname='Arial',\n                     color='white', rotation=180)\n    if endzones:\n        hash_range = range(11, 110)\n    else:\n        hash_range = range(1, 120)\n\n    for x in hash_range:\n        ax.plot([x, x], [0.4, 0.7], color='white')\n        ax.plot([x, x], [53.0, 52.5], color='white')\n        ax.plot([x, x], [22.91, 23.57], color='white')\n        ax.plot([x, x], [29.73, 30.39], color='white')\n\n    if highlight_line:\n        hl = highlight_line_number + 10\n        plt.plot([hl, hl], [0, 53.3], color='yellow')\n        #plt.text(hl + 2, 50, '<- {}'.format(highlighted_name),\n        #         color='yellow')\n        \n    if highlight_first_down_line:\n        fl = hl + yards_to_go\n        plt.plot([fl, fl], [0, 53.3], color='yellow')\n        #plt.text(fl + 2, 50, '<- {}'.format(highlighted_name),\n        #         color='yellow')\n    return fig, ax","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:52:36.359695Z","iopub.execute_input":"2022-01-06T20:52:36.360033Z","iopub.status.idle":"2022-01-06T20:52:36.37595Z","shell.execute_reply.started":"2022-01-06T20:52:36.359996Z","shell.execute_reply":"2022-01-06T20:52:36.375388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Definition of dx and dy, using game id as basis","metadata":{}},{"cell_type":"code","source":"def calculate_dx_dy_arrow(x, y, angle, speed, multiplier):\n    if angle <= 90:\n        angle = angle\n        dx = np.sin(radians(angle)) * multiplier * speed\n        dy = np.cos(radians(angle)) * multiplier * speed\n        return dx, dy\n    if angle > 90 and angle <= 180:\n        angle = angle - 90\n        dx = np.cos(radians(angle)) * multiplier * speed\n        dy = -np.sin(radians(angle)) * multiplier * speed\n        return dx, dy\n    if angle > 180 and angle <= 270:\n        angle = angle - 180\n        dx = -(np.sin(radians(angle)) * multiplier * speed)\n        dy = -(np.cos(radians(angle)) * multiplier * speed)\n        return dx, dy\n    if angle > 270 and angle <= 360:\n        angle = 360 - angle\n        dx = -np.sin(radians(angle)) * multiplier * speed\n        dy = np.cos(radians(angle)) * multiplier * speed\n        return dx, dy\n    \n        \ndef animate_player_movement(yearNumber, playId, gameId):\n    yearData = pd.read_csv('../input/nfl-big-data-bowl-2022/tracking'+ str(yearNumber) +'.csv')\n    playData = pd.read_csv('../input/nfl-big-data-bowl-2022/plays.csv')\n    \n    playHome = yearData.query('gameId==' + str(gameId) + ' and playId==' + str(playId) + ' and team == \"home\"')\n    playAway = yearData.query('gameId==' + str(gameId) + ' and playId==' + str(playId) + ' and team == \"away\"')\n    playFootball =  yearData.query('gameId==' + str(gameId) + ' and playId==' + str(playId) + ' and team == \"football\"')\n    \n    playHome['time'] = playHome['time'].apply(lambda x: dateutil.parser.parse(x).timestamp()).rank(method='dense')\n    playAway['time'] = playAway['time'].apply(lambda x: dateutil.parser.parse(x).timestamp()).rank(method='dense')\n    playFootball['time'] = playFootball['time'].apply(lambda x: dateutil.parser.parse(x).timestamp()).rank(method='dense')\n    \n    maxTime = int(playAway['time'].unique().max())\n    minTime = int(playAway['time'].unique().min())\n    \n    yardlineNumber = playData.query('gameId==' + str(gameId) + ' and playId==' + str(playId))['yardlineNumber'].item()\n    yardsToGo = playData.query('gameId==' + str(gameId) + ' and playId==' + str(playId))['yardsToGo'].item()\n    absoluteYardlineNumber = playData.query('gameId==' + str(gameId) + ' and playId==' + str(playId))['absoluteYardlineNumber'].item() - 10\n    playDir = playHome.sample(1)['playDirection'].item()\n    \n    if (absoluteYardlineNumber > 50):\n        yardlineNumber = 100 - yardlineNumber\n    if (absoluteYardlineNumber <= 50):\n        yardlineNumber = yardlineNumber\n        \n    if (playDir == 'left'):\n        yardsToGo = -yardsToGo\n    else:\n        yardsToGo = yardsToGo\n    \n    fig, ax = create_football_field(highlight_line=True, highlight_line_number=yardlineNumber, highlight_first_down_line=True, yards_to_go=yardsToGo)\n    playDesc = playData.query('gameId==' + str(gameId) + ' and playId==' + str(playId))['playDescription'].item()\n    plt.title(f'Game # {gameId} Play # {playId} \\n {playDesc}')\n    \n    def update_animation(time):\n        patch = []\n        \n        homeX = playHome.query('time == ' + str(time))['x']\n        homeY = playHome.query('time == ' + str(time))['y']\n        homeNum = playHome.query('time == ' + str(time))['jerseyNumber']\n        homeOrient = playHome.query('time == ' + str(time))['o']\n        homeDir = playHome.query('time == ' + str(time))['dir']\n        homeSpeed = playHome.query('time == ' + str(time))['s']\n        patch.extend(plt.plot(homeX, homeY, 'o',c='gold', ms=20, mec='white'))\n        \n        # Home players' jersey number \n        for x, y, num in zip(homeX, homeY, homeNum):\n            patch.append(plt.text(x, y, int(num), va='center', ha='center', color='black', size='medium'))\n            \n        # Home players' orientation\n        for x, y, orient in zip(homeX, homeY, homeOrient):\n            dx, dy = calculate_dx_dy_arrow(x, y, orient, 1, 1)\n            patch.append(plt.arrow(x, y, dx, dy, color='gold', width=0.5, shape='full'))\n            \n        # Home players' direction\n        for x, y, direction, speed in zip(homeX, homeY, homeDir, homeSpeed):\n            dx, dy = calculate_dx_dy_arrow(x, y, direction, speed, 1)\n            patch.append(plt.arrow(x, y, dx, dy, color='black', width=0.25, shape='full'))\n        \n        # Home players' location\n        awayX = playAway.query('time == ' + str(time))['x']\n        awayY = playAway.query('time == ' + str(time))['y']\n        awayNum = playAway.query('time == ' + str(time))['jerseyNumber']\n        awayOrient = playAway.query('time == ' + str(time))['o']\n        awayDir = playAway.query('time == ' + str(time))['dir']\n        awaySpeed = playAway.query('time == ' + str(time))['s']\n        patch.extend(plt.plot(awayX, awayY, 'o',c='orangered', ms=20, mec='white'))\n        \n        # Away players' jersey number \n        for x, y, num in zip(awayX, awayY, awayNum):\n            patch.append(plt.text(x, y, int(num), va='center', ha='center', color='white', size='medium'))\n            \n        # Away players' orientation\n        for x, y, orient in zip(awayX, awayY, awayOrient):\n            dx, dy = calculate_dx_dy_arrow(x, y, orient, 1, 1)\n            patch.append(plt.arrow(x, y, dx, dy, color='orangered', width=0.5, shape='full'))\n        \n        # Away players' direction\n        for x, y, direction, speed in zip(awayX, awayY, awayDir, awaySpeed):\n            dx, dy = calculate_dx_dy_arrow(x, y, direction, speed, 1)\n            patch.append(plt.arrow(x, y, dx, dy, color='black', width=0.25, shape='full'))\n        \n        # Away players' location\n        footballX = playFootball.query('time == ' + str(time))['x']\n        footballY = playFootball.query('time == ' + str(time))['y']\n        patch.extend(plt.plot(footballX, footballY, 'o', c='black', ms=10, mec='white', data=playFootball.query('time == ' + str(time))['team']))\n        \n        \n        return patch\n    \n    ims = [[]]\n    for time in np.arange(minTime, maxTime+1):\n        patch = update_animation(time)\n        ims.append(patch)\n        \n    anim = animation.ArtistAnimation(fig, ims, repeat=False)\n    \n    return anim\n\nanim = animate_player_movement(2018, 4003,2018123001 )","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:05.771026Z","iopub.execute_input":"2022-01-06T20:54:05.771785Z","iopub.status.idle":"2022-01-06T20:54:35.141395Z","shell.execute_reply.started":"2022-01-06T20:54:05.771704Z","shell.execute_reply":"2022-01-06T20:54:35.140548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"writer = FFMpegWriter(fps=10)\nanim.save('animation_notrail.mp4', writer=writer)\nVideo(\"animation_notrail.mp4\")","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:55:45.983769Z","iopub.execute_input":"2022-01-06T20:55:45.984045Z","iopub.status.idle":"2022-01-06T20:56:05.659906Z","shell.execute_reply.started":"2022-01-06T20:55:45.984017Z","shell.execute_reply":"2022-01-06T20:56:05.658889Z"},"trusted":true},"execution_count":null,"outputs":[]}]}