{"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":"# What makes a great punter?","metadata":{}},{"cell_type":"markdown","source":"## Defining a new tool for analyzing punter effectiveness\n\nIn recent seasons, NFL teams have opted to punt less and less often, and many argue that this has made for a more exciting game. Whether or not this is an effective strategy for teams depends greatly on the quality of their punter--the more effective the punter, the greater the opportunity cost of going for it on fourth down. \n\nThis project aims to create a new tool for analyzing punter effectiveness over the course of one or more seasons. \n\nIn working on this project, I collaborated with an avid football fan and non-coder (my mom). To make the notebook as readable for her as possible, I tried to err on the side of explaining what I was doing as often as possible. I hope, as a byproduct, that this makes the code more readable for all who choose to explore. \n\nI welcome any and all feedback on the code.\n\nThank you for reading.\n","metadata":{}},{"cell_type":"markdown","source":"Step 1: Prepare the environment, open the data, and build dfs.","metadata":{}},{"cell_type":"code","source":"# Import the necessary libraries\nimport pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom matplotlib.backends.backend_pdf import PdfPages\nimport os","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:48.732499Z","iopub.execute_input":"2021-10-26T13:32:48.733095Z","iopub.status.idle":"2021-10-26T13:32:49.64148Z","shell.execute_reply.started":"2021-10-26T13:32:48.73296Z","shell.execute_reply":"2021-10-26T13:32:49.640534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Access the csv files and build dfs\nscout_df = pd.read_csv(\"../input/nfl-big-data-bowl-2022/PFFScoutingData.csv\")\ngames_df = pd.read_csv(\"../input/nfl-big-data-bowl-2022/games.csv\")\nplayers_df = pd.read_csv(\"../input/nfl-big-data-bowl-2022/players.csv\")\nplays_df = pd.read_csv(\"../input/nfl-big-data-bowl-2022/plays.csv\")\n# track18_df = pd.read_csv(\"../input/nfl-big-data-bowl-2022/tracking2018.csv\")\n# track19_df = pd.read_csv(\"../input/nfl-big-data-bowl-2022/tracking2019.csv\")\n# track20_df = pd.read_csv(\"../input/nfl-big-data-bowl-2022/tracking2020.csv\")","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:49.64355Z","iopub.execute_input":"2021-10-26T13:32:49.643868Z","iopub.status.idle":"2021-10-26T13:32:49.917194Z","shell.execute_reply.started":"2021-10-26T13:32:49.643819Z","shell.execute_reply":"2021-10-26T13:32:49.916573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Make a list of all dfs for cleaning and analysis\n# df_list = [scout_df, games_df, players_df, plays_df, track18_df, track19_df, track20_df]","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:49.918355Z","iopub.execute_input":"2021-10-26T13:32:49.918731Z","iopub.status.idle":"2021-10-26T13:32:49.921284Z","shell.execute_reply.started":"2021-10-26T13:32:49.91869Z","shell.execute_reply":"2021-10-26T13:32:49.920791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"Step 2: Preview all dfs to understand available data.","metadata":{}},{"cell_type":"code","source":"# Define a function to insert commas into shape descriptions to make them human-legibile.\ndef insert_commas (tup):\n    new_list = []\n    for i in tup:\n        i_new = \"{:,}\".format(i)\n        new_list.append(i_new)\n    return new_list\n\n\n    \n# Get the shape (number of rows, number of columns) for each df\nscout_shape = insert_commas(scout_df.shape)\ngames_shape = insert_commas(games_df.shape)\nplayers_shape = insert_commas(players_df.shape)\nplays_shape = insert_commas(plays_df.shape)\n# track18_shape = insert_commas(track18_df.shape)\n# track19_shape = insert_commas(track19_df.shape)\n# track20_shape = insert_commas(track20_df.shape)\n\n\nprint(\"Number of rows and columns in each df:\")            \nprint(f'scout_df has {scout_shape[0]} rows and {scout_shape[1]} columns')\nprint(f'games_df: has {games_shape[0]} rows and {games_shape[1]} columns')\nprint(f'players_df: has {players_shape[0]} rows and {players_shape[1]} columns')\nprint(f'plays_df: has {plays_shape[0]} rows and {plays_shape[1]} columns')\n# print(f'track18_df: has {track18_shape[0]} rows and {track18_shape[1]} columns')\n# print(f'track19_df: has {track19_shape[0]} rows and {track19_shape[1]} columns')\n# print(f'track20_df: has {track20_shape[0]} rows and {track20_shape[1]} columns')","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:49.923038Z","iopub.execute_input":"2021-10-26T13:32:49.923272Z","iopub.status.idle":"2021-10-26T13:32:49.938932Z","shell.execute_reply.started":"2021-10-26T13:32:49.923244Z","shell.execute_reply":"2021-10-26T13:32:49.938021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"scout_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:49.939949Z","iopub.execute_input":"2021-10-26T13:32:49.940167Z","iopub.status.idle":"2021-10-26T13:32:49.983534Z","shell.execute_reply.started":"2021-10-26T13:32:49.940137Z","shell.execute_reply":"2021-10-26T13:32:49.982591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"scout_df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:49.985018Z","iopub.execute_input":"2021-10-26T13:32:49.985418Z","iopub.status.idle":"2021-10-26T13:32:50.027567Z","shell.execute_reply.started":"2021-10-26T13:32:49.985375Z","shell.execute_reply":"2021-10-26T13:32:50.026444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"games_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.028856Z","iopub.execute_input":"2021-10-26T13:32:50.029653Z","iopub.status.idle":"2021-10-26T13:32:50.042355Z","shell.execute_reply.started":"2021-10-26T13:32:50.029615Z","shell.execute_reply":"2021-10-26T13:32:50.041522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"games_df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.04333Z","iopub.execute_input":"2021-10-26T13:32:50.044019Z","iopub.status.idle":"2021-10-26T13:32:50.070042Z","shell.execute_reply.started":"2021-10-26T13:32:50.043984Z","shell.execute_reply":"2021-10-26T13:32:50.069254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.071076Z","iopub.execute_input":"2021-10-26T13:32:50.071286Z","iopub.status.idle":"2021-10-26T13:32:50.084715Z","shell.execute_reply.started":"2021-10-26T13:32:50.071262Z","shell.execute_reply":"2021-10-26T13:32:50.083613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"players_df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.087677Z","iopub.execute_input":"2021-10-26T13:32:50.088137Z","iopub.status.idle":"2021-10-26T13:32:50.103925Z","shell.execute_reply.started":"2021-10-26T13:32:50.088103Z","shell.execute_reply":"2021-10-26T13:32:50.10339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plays_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.104861Z","iopub.execute_input":"2021-10-26T13:32:50.105284Z","iopub.status.idle":"2021-10-26T13:32:50.131015Z","shell.execute_reply.started":"2021-10-26T13:32:50.105243Z","shell.execute_reply":"2021-10-26T13:32:50.130091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plays_df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.132256Z","iopub.execute_input":"2021-10-26T13:32:50.132525Z","iopub.status.idle":"2021-10-26T13:32:50.190976Z","shell.execute_reply.started":"2021-10-26T13:32:50.132497Z","shell.execute_reply":"2021-10-26T13:32:50.190391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# track18_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.191991Z","iopub.execute_input":"2021-10-26T13:32:50.192728Z","iopub.status.idle":"2021-10-26T13:32:50.195957Z","shell.execute_reply.started":"2021-10-26T13:32:50.192697Z","shell.execute_reply":"2021-10-26T13:32:50.1952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# track18_df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.197188Z","iopub.execute_input":"2021-10-26T13:32:50.197677Z","iopub.status.idle":"2021-10-26T13:32:50.207935Z","shell.execute_reply.started":"2021-10-26T13:32:50.197647Z","shell.execute_reply":"2021-10-26T13:32:50.207367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# track19_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.20901Z","iopub.execute_input":"2021-10-26T13:32:50.20967Z","iopub.status.idle":"2021-10-26T13:32:50.219614Z","shell.execute_reply.started":"2021-10-26T13:32:50.209632Z","shell.execute_reply":"2021-10-26T13:32:50.218971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# track19_df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.220773Z","iopub.execute_input":"2021-10-26T13:32:50.221395Z","iopub.status.idle":"2021-10-26T13:32:50.229132Z","shell.execute_reply.started":"2021-10-26T13:32:50.221363Z","shell.execute_reply":"2021-10-26T13:32:50.228439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# track20_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.230452Z","iopub.execute_input":"2021-10-26T13:32:50.231238Z","iopub.status.idle":"2021-10-26T13:32:50.23974Z","shell.execute_reply.started":"2021-10-26T13:32:50.231205Z","shell.execute_reply":"2021-10-26T13:32:50.238885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# track20_df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.240959Z","iopub.execute_input":"2021-10-26T13:32:50.24147Z","iopub.status.idle":"2021-10-26T13:32:50.249252Z","shell.execute_reply.started":"2021-10-26T13:32:50.241426Z","shell.execute_reply":"2021-10-26T13:32:50.248417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Step 3: Build a dataframe of all punters in players_df and all the punts in plays_df. This will allow for analyzing performance across punters and punts.","metadata":{}},{"cell_type":"code","source":"punters_df = players_df.loc[players_df['Position'] == \"P\"]\npunters_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.250523Z","iopub.execute_input":"2021-10-26T13:32:50.251197Z","iopub.status.idle":"2021-10-26T13:32:50.269462Z","shell.execute_reply.started":"2021-10-26T13:32:50.251113Z","shell.execute_reply":"2021-10-26T13:32:50.268694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"punters_df.info()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.270471Z","iopub.execute_input":"2021-10-26T13:32:50.271063Z","iopub.status.idle":"2021-10-26T13:32:50.289606Z","shell.execute_reply.started":"2021-10-26T13:32:50.271022Z","shell.execute_reply":"2021-10-26T13:32:50.288729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"punts_df = plays_df.loc[plays_df['specialTeamsPlayType'] == \"Punt\"]\npuntsbypunter_df = punts_df.groupby('kickerId')\npuntsbypunter_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.290931Z","iopub.execute_input":"2021-10-26T13:32:50.291153Z","iopub.status.idle":"2021-10-26T13:32:50.336116Z","shell.execute_reply.started":"2021-10-26T13:32:50.291128Z","shell.execute_reply":"2021-10-26T13:32:50.335254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Calculate each punter's mean data.\npuntsbypunter_df.mean()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.337405Z","iopub.execute_input":"2021-10-26T13:32:50.337621Z","iopub.status.idle":"2021-10-26T13:32:50.398009Z","shell.execute_reply.started":"2021-10-26T13:32:50.337596Z","shell.execute_reply":"2021-10-26T13:32:50.397167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Determine the number of punts each punter kicked\npunt_count = puntsbypunter_df.size().to_frame('npunts') \npunt_count = punt_count.astype(int)\npunt_count\n\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.399454Z","iopub.execute_input":"2021-10-26T13:32:50.399888Z","iopub.status.idle":"2021-10-26T13:32:50.417957Z","shell.execute_reply.started":"2021-10-26T13:32:50.399844Z","shell.execute_reply":"2021-10-26T13:32:50.417055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Merge punt counts with punter information \n# punters_df.merge(punt_count, how='left', left_on=\"nflId\", right_on=\"kickerId\")\npunters_df.merge(punt_count, how='left', left_index = True, right_index=True)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.419723Z","iopub.execute_input":"2021-10-26T13:32:50.420221Z","iopub.status.idle":"2021-10-26T13:32:50.459739Z","shell.execute_reply.started":"2021-10-26T13:32:50.420177Z","shell.execute_reply":"2021-10-26T13:32:50.459093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Step 4: Calculate summary statistics for each punter and add them to punter_df. Statistics include...\n- Mean punt length, kick return yards, and play result\n","metadata":{}},{"cell_type":"code","source":"punt_mean_df = puntsbypunter_df.mean()\npunt_mean_df = punt_mean_df[['kickLength', 'kickReturnYardage', 'playResult']]\npunt_mean_df","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.460932Z","iopub.execute_input":"2021-10-26T13:32:50.46201Z","iopub.status.idle":"2021-10-26T13:32:50.489013Z","shell.execute_reply.started":"2021-10-26T13:32:50.461962Z","shell.execute_reply":"2021-10-26T13:32:50.488423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Merge summary statistics to punters_df","metadata":{}},{"cell_type":"code","source":"punters_df = punters_df.join(punt_mean_df)\npunters_df","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.490147Z","iopub.execute_input":"2021-10-26T13:32:50.490524Z","iopub.status.idle":"2021-10-26T13:32:50.522884Z","shell.execute_reply.started":"2021-10-26T13:32:50.49049Z","shell.execute_reply":"2021-10-26T13:32:50.522281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Step 5: create data vizzes to understand punters data.","metadata":{}},{"cell_type":"code","source":"sns.histplot(data=punters_df, x=\"kickLength\", kde=True).set(title=\"Each Punter's Average Punt Length Histogram\")","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.523764Z","iopub.execute_input":"2021-10-26T13:32:50.524501Z","iopub.status.idle":"2021-10-26T13:32:50.762157Z","shell.execute_reply.started":"2021-10-26T13:32:50.524466Z","shell.execute_reply":"2021-10-26T13:32:50.761402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Step 6: Categorize punts based on starting yard line.","metadata":{}},{"cell_type":"code","source":"print(punts_df.columns)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.76616Z","iopub.execute_input":"2021-10-26T13:32:50.766422Z","iopub.status.idle":"2021-10-26T13:32:50.771742Z","shell.execute_reply.started":"2021-10-26T13:32:50.766393Z","shell.execute_reply":"2021-10-26T13:32:50.770882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.set_option('display.max_columns', None)  \nprint(punts_df[1:5])","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.773006Z","iopub.execute_input":"2021-10-26T13:32:50.773241Z","iopub.status.idle":"2021-10-26T13:32:50.793517Z","shell.execute_reply.started":"2021-10-26T13:32:50.773213Z","shell.execute_reply":"2021-10-26T13:32:50.792801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a calculation to normalize starting yard line.\npunt_starts = punts_df[['gameId','playId','possessionTeam',\"yardlineSide\", \"yardlineNumber\", \n                        \"specialTeamsResult\", \"kickerId\", \"kickLength\", \"kickReturnYardage\", \"playResult\"]].copy()\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.794808Z","iopub.execute_input":"2021-10-26T13:32:50.795249Z","iopub.status.idle":"2021-10-26T13:32:50.801174Z","shell.execute_reply.started":"2021-10-26T13:32:50.79522Z","shell.execute_reply":"2021-10-26T13:32:50.80042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"punt_starts.loc[punt_starts['possessionTeam'] == punt_starts['yardlineSide'], 'startYdsToEndzone'] = 100 - punt_starts['yardlineNumber']\npunt_starts.loc[punt_starts['possessionTeam'] != punt_starts['yardlineSide'], 'startYdsToEndzone'] = punt_starts['yardlineNumber']\npunt_starts","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.802615Z","iopub.execute_input":"2021-10-26T13:32:50.803101Z","iopub.status.idle":"2021-10-26T13:32:50.841159Z","shell.execute_reply.started":"2021-10-26T13:32:50.803066Z","shell.execute_reply":"2021-10-26T13:32:50.840548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.stripplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:50.842258Z","iopub.execute_input":"2021-10-26T13:32:50.842608Z","iopub.status.idle":"2021-10-26T13:32:52.900308Z","shell.execute_reply.started":"2021-10-26T13:32:50.842581Z","shell.execute_reply":"2021-10-26T13:32:52.899431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:52.901868Z","iopub.execute_input":"2021-10-26T13:32:52.90238Z","iopub.status.idle":"2021-10-26T13:32:58.74121Z","shell.execute_reply.started":"2021-10-26T13:32:52.902333Z","shell.execute_reply":"2021-10-26T13:32:58.73884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f, ax = plt.subplots(figsize=(10, 10))\nsns.scatterplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\", s=5, color=\".15\")\nsns.histplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\", bins=50, pthresh=.1, cmap=\"mako\")\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\", levels=15, color=\"w\", linewidths=1)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:32:58.742206Z","iopub.execute_input":"2021-10-26T13:32:58.742452Z","iopub.status.idle":"2021-10-26T13:33:04.568298Z","shell.execute_reply.started":"2021-10-26T13:32:58.742426Z","shell.execute_reply":"2021-10-26T13:33:04.567422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Based on the vizzes above, there appears to be a distinction between punts from more than 60 yards away from the endzone (where the punter aims to kick as far as possible) and from less than 60 yards away (where the punter aims to pin the opponent as close as possible to the endzone without kicking a touchback.\n\nUsing this information, I will split the punts data into these two groups.","metadata":{}},{"cell_type":"code","source":"punt_starts.loc[punt_starts['startYdsToEndzone'] >= 60, 'puntCategory'] = \"MaxLength\"\npunt_starts.loc[punt_starts['startYdsToEndzone'] < 60, 'puntCategory'] = \"Precision\"\npunt_starts","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:04.569539Z","iopub.execute_input":"2021-10-26T13:33:04.570097Z","iopub.status.idle":"2021-10-26T13:33:04.600222Z","shell.execute_reply.started":"2021-10-26T13:33:04.570059Z","shell.execute_reply":"2021-10-26T13:33:04.599426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"punt_starts_grouped = punt_starts.groupby('puntCategory')\npunt_starts_grouped.mean()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:04.601602Z","iopub.execute_input":"2021-10-26T13:33:04.601834Z","iopub.status.idle":"2021-10-26T13:33:04.619908Z","shell.execute_reply.started":"2021-10-26T13:33:04.601807Z","shell.execute_reply":"2021-10-26T13:33:04.61899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Produce graphs for each punter.","metadata":{}},{"cell_type":"code","source":"punters_df\npunter_list = punters_df['displayName'].tolist()\npunter_list","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:48:36.025783Z","iopub.execute_input":"2021-10-26T13:48:36.026081Z","iopub.status.idle":"2021-10-26T13:48:36.033814Z","shell.execute_reply.started":"2021-10-26T13:48:36.02605Z","shell.execute_reply":"2021-10-26T13:48:36.033244Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"punters_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:48:55.47291Z","iopub.execute_input":"2021-10-26T13:48:55.473216Z","iopub.status.idle":"2021-10-26T13:48:55.493044Z","shell.execute_reply.started":"2021-10-26T13:48:55.473179Z","shell.execute_reply":"2021-10-26T13:48:55.492429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"punter_ids = punters_df[\"nflId\"].tolist()\npunter_ids","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:49:16.948057Z","iopub.execute_input":"2021-10-26T13:49:16.948877Z","iopub.status.idle":"2021-10-26T13:49:16.957133Z","shell.execute_reply.started":"2021-10-26T13:49:16.948837Z","shell.execute_reply":"2021-10-26T13:49:16.956306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a dictionary with names and id numbers for labeling figures.","metadata":{}},{"cell_type":"code","source":"punters_df","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:04.639782Z","iopub.execute_input":"2021-10-26T13:33:04.64048Z","iopub.status.idle":"2021-10-26T13:33:04.675568Z","shell.execute_reply.started":"2021-10-26T13:33:04.64043Z","shell.execute_reply":"2021-10-26T13:33:04.674757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a directory for figures\nos.mkdir(\"figures\")","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:04.677036Z","iopub.execute_input":"2021-10-26T13:33:04.677298Z","iopub.status.idle":"2021-10-26T13:33:04.681543Z","shell.execute_reply.started":"2021-10-26T13:33:04.67727Z","shell.execute_reply":"2021-10-26T13:33:04.680584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create an \"optimal\" punt line by graphing a series of dots in a angled line 10 yards from the endzone.","metadata":{}},{"cell_type":"code","source":"optimal_dist_to_ez = [40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90]\noptimal_length = [30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80] \nsns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='red')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:04.683045Z","iopub.execute_input":"2021-10-26T13:33:04.683519Z","iopub.status.idle":"2021-10-26T13:33:04.910338Z","shell.execute_reply.started":"2021-10-26T13:33:04.683477Z","shell.execute_reply":"2021-10-26T13:33:04.909726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Testing out different plot options\n# Option 1: scatterplot\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\npunter = 46903\npunter_id = float(punter)\ntemp_punts_df_1 = punt_starts.loc[punt_starts['kickerId'] == punter_id]\nfig = sns.scatterplot(data=temp_punts_df_1, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=punter_id)\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:04.911357Z","iopub.execute_input":"2021-10-26T13:33:04.911663Z","iopub.status.idle":"2021-10-26T13:33:10.74409Z","shell.execute_reply.started":"2021-10-26T13:33:04.911637Z","shell.execute_reply":"2021-10-26T13:33:10.743376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Option 2: Stacked density plots\nplt.clf()\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\nfig = sns.kdeplot(data=temp_punts_df_1, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=punter_id)\nsns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='red')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:10.745352Z","iopub.execute_input":"2021-10-26T13:33:10.745686Z","iopub.status.idle":"2021-10-26T13:33:16.68336Z","shell.execute_reply.started":"2021-10-26T13:33:10.745657Z","shell.execute_reply":"2021-10-26T13:33:16.682713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Option 3: Filled density plot, \"Mako\" palette\nplt.clf()\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\nfig = sns.kdeplot(data=temp_punts_df_1, x=\"startYdsToEndzone\", y=\"kickLength\",fill=True, thresh=0, levels=100, cmap=\"mako\").set(title=punter_id)\nsns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='red')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:16.684412Z","iopub.execute_input":"2021-10-26T13:33:16.684729Z","iopub.status.idle":"2021-10-26T13:33:22.820083Z","shell.execute_reply.started":"2021-10-26T13:33:16.684702Z","shell.execute_reply":"2021-10-26T13:33:22.819241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Option 4: Filled density plot, \"Rocket\" palette\nplt.clf()\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\nfig = sns.kdeplot(data=temp_punts_df_1, x=\"startYdsToEndzone\", y=\"kickLength\",fill=True, thresh=0, levels=100, cmap=\"rocket\").set(title=punter_id)\nsns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='red')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:22.821237Z","iopub.execute_input":"2021-10-26T13:33:22.821501Z","iopub.status.idle":"2021-10-26T13:33:28.966933Z","shell.execute_reply.started":"2021-10-26T13:33:22.821473Z","shell.execute_reply":"2021-10-26T13:33:28.966055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Option 5: Filled density plot, \"Crest\" palette\nplt.clf()\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\nfig = sns.kdeplot(data=temp_punts_df_1, x=\"startYdsToEndzone\", y=\"kickLength\",fill=True, thresh=0, levels=100, cmap=\"crest\").set(title=punter_id)\nsns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='red')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:28.968382Z","iopub.execute_input":"2021-10-26T13:33:28.969156Z","iopub.status.idle":"2021-10-26T13:33:35.085064Z","shell.execute_reply.started":"2021-10-26T13:33:28.969109Z","shell.execute_reply":"2021-10-26T13:33:35.08424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Option 6: Filled density plot, \"Magma\" palette, fewer levels\nplt.clf()\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\nfig = sns.kdeplot(data=temp_punts_df_1, x=\"startYdsToEndzone\", y=\"kickLength\",fill=True, thresh=0, levels=10, cmap=\"magma\").set(title=punter_id)\nsns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='greys')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:35.086126Z","iopub.execute_input":"2021-10-26T13:33:35.086356Z","iopub.status.idle":"2021-10-26T13:33:41.220438Z","shell.execute_reply.started":"2021-10-26T13:33:35.086329Z","shell.execute_reply":"2021-10-26T13:33:41.219842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Option 7: Filled density plot, \"Magma\" palette, fewer levels, higher threshhold\nplt.clf()\nsns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\nfig = sns.kdeplot(data=temp_punts_df_1, x=\"startYdsToEndzone\", y=\"kickLength\",fill=True, thresh=.1, levels=10, cmap=\"magma\").set(title=punter_id)\nsns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='red')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:41.221355Z","iopub.execute_input":"2021-10-26T13:33:41.221874Z","iopub.status.idle":"2021-10-26T13:33:47.172943Z","shell.execute_reply.started":"2021-10-26T13:33:41.221841Z","shell.execute_reply":"2021-10-26T13:33:47.172101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"name_id = punters_df.loc[:,['displayName','nflId']]\n","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:47.174335Z","iopub.execute_input":"2021-10-26T13:33:47.174637Z","iopub.status.idle":"2021-10-26T13:33:47.180449Z","shell.execute_reply.started":"2021-10-26T13:33:47.174597Z","shell.execute_reply":"2021-10-26T13:33:47.179644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"# punter_id = 46903\n# name = name_id.loc[name_id['nflId'] == punter_id,'displayName']\n# # name = name.iloc[0]['displayName']\n# print(name)\n# # sub_df.iloc[0]['A']","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:33:47.181654Z","iopub.execute_input":"2021-10-26T13:33:47.182188Z","iopub.status.idle":"2021-10-26T13:33:47.198942Z","shell.execute_reply.started":"2021-10-26T13:33:47.182145Z","shell.execute_reply":"2021-10-26T13:33:47.197987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def punter_grapher (punter_ids, punt_starts):\n    \n    for punter in punter_ids:\n        sns.kdeplot(data=punt_starts, x=\"startYdsToEndzone\", y=\"kickLength\").set(title=\"Punt Lengths Based on Initial Distance to Endzone\")\n        punter_id = float(punter)\n        ## insert here\n        temp_punts_df = punt_starts.loc[punt_starts['kickerId'] == punter_id]\n        sns.kdeplot(data=temp_punts_df, x=\"startYdsToEndzone\", y=\"kickLength\",fill=True, thresh=0, levels=10, cmap=\"magma\").set(title=punter_id)\n        sns.scatterplot(x=optimal_dist_to_ez, y=optimal_length, palette='red')\n        plt.title(punter_id)\n        plot_title = f\"figures/{punter}.pdf\"\n        plt.savefig(plot_title)\n        plt.clf()\n\n        \n    ","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:49:33.789757Z","iopub.execute_input":"2021-10-26T13:49:33.790325Z","iopub.status.idle":"2021-10-26T13:49:33.797283Z","shell.execute_reply.started":"2021-10-26T13:49:33.790274Z","shell.execute_reply":"2021-10-26T13:49:33.796665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.clf()\npunter_grapher(punter_ids, punt_starts)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T13:49:37.832335Z","iopub.execute_input":"2021-10-26T13:49:37.832882Z","iopub.status.idle":"2021-10-26T13:49:55.601368Z","shell.execute_reply.started":"2021-10-26T13:49:37.832832Z","shell.execute_reply":"2021-10-26T13:49:55.599944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}}]}