{"cells":[{"metadata":{},"cell_type":"markdown","source":"![](https://i.imgur.com/WrndCh8.png)"},{"metadata":{},"cell_type":"markdown","source":"# 1. Introduction\nInjuries are a big problem in many sports, from football to wrestling. An injury could retire an athlete from weeks until an entire season, or even in the worst cases end a carreer. Given this scenario, it's important to guarantee the safe of athlete, recognizing patterns could be their body health in risk. The NFL has some notoriuos cases of serious injuries like [Tom Brady knee injury](http://www.nfl.com/news/story/09000d5d80a95089/article/brady-to-have-seasonending-knee-surgery-will-be-placed-on-ir) in 2008, what made Brady retires for all the rest of the Season, to take another sports as example and the danger of injuries, there's the case of [Paige's accidental kick](https://wrestletalk.com/news/nothing-was-ever-sashas-fault-paige-opens-up-about-career-ending-neck-injury/) delivered by Sasha Banks on WWE, this ended Paige's carreer.<br>\n<br>\nIn this work, I analyze the data of [NFL 1st and Future - Analytics](https://www.kaggle.com/c/nfl-playing-surface-analytics/data) competition to find patterns that could lead to an injury on a NFL match and aid to find ways to give a better condition to every player make your best without so many high risks, we want less injury and more touchdowns!<br>\n<br>\nThe data exploration is made with interactive plots, you can hover the mouse on it to see the values, and explanations for every insight from the plots. I will focus in every type of injury and how they interact with the different surfaces and some other features.<br>\n<br>\nYou can click on the buttons to see any hidden cells or outputs, and see which modules and the helper functions that I use in this kernel. I made this to have a clean visualization of the analysis."},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"_kg_hide-output":true,"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":false},"cell_type":"code","source":"# Modules\n# Core\nimport numpy as np\nimport pandas as pd\n# Visualizations\nimport matplotlib.pylab as plt\nimport matplotlib.patches as patches\nimport seaborn as sns\nsns.set_style(\"darkgrid\")\nfrom plotly.offline import init_notebook_mode, iplot, plot\nimport plotly as py\nfrom plotly.subplots import make_subplots\nimport plotly.graph_objs as go\ninit_notebook_mode(connected=True)\n# Tools\nfrom IPython.display import HTML, display\nimport os\nimport io\nimport pprint\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n%config InlineBackend.figure_format = \"retina\"\n\nDATA_PATH = '../input/nfl-playing-surface-analytics/'\n\nprint(os.listdir(DATA_PATH))","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_kg_hide-input":true,"_kg_hide-output":true,"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"code","source":"# Helper Functions\n# For reduce dataframe memory size, there's a big dataframe here\ndef reduce_mem_usage(df):\n    for col in df.columns:\n        col_type = df[col].dtype\n        \n        if col_type != object:\n            c_min = df[col].min()\n            c_max = df[col].max()\n            if str(col_type)[:3] == \"int\":\n                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                    df[col] = df[col].astype(np.int8)\n                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                    df[col] = df[col].astype(np.int16)\n                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                    df[col] = df[col].astype(np.int32)\n                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                    df[col] = df[col].astype(np.int64)  \n            else:\n                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                    df[col] = df[col].astype(np.float16)\n                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                    df[col] = df[col].astype(np.float32)\n                else:\n                    df[col] = df[col].astype(np.float64)\n        else:\n            df[col] = df[col].astype('category')\n    return df\n\n# Import data and reduce RAM usage\ndef import_data(file):\n    df = pd.read_csv(file, parse_dates=True, keep_date_col=True)\n    df = reduce_mem_usage(df)\n    return df\n\n# Get dataframe info like columns, missing values, data type, etc.\ndef get_df_info(df):\n    display(df.head(3).style.hide_index().\n            set_properties(**{'text-align': 'center'}))\n    buf = io.StringIO()\n    df.info(buf=buf)\n    info = buf.getvalue().split('\\n')[-2]\n    df_samples = pd.DataFrame({'Number of Samples': df.shape[0], \n                               'Number of Features' : df.shape[1]},\n                             index=[0])\n    display(df_samples.style.hide_index()\n            .set_properties(**{'text-align': 'center'}))\n    df_types = df.dtypes\n    df_types = pd.DataFrame({'Column':df_types.index, 'Type':df_types.values})\n    display(df_types.style.hide_index()\n            .set_properties(**{'text-align': 'center'})) \n    missing = df.isnull().sum().sort_values(ascending=False)\n    if missing.values.sum() == 0:\n        missing = pd.DataFrame({'Missing Values' : \"No Missing Values\"})\n    else:\n        missing = missing[missing > 0]\n        missing = pd.DataFrame({'Feature' : missing.index, 'Missing Values' : missing.values})\n        display(missing.style.hide_index()\n                .set_properties(**{'text-align': 'center'}))\n  \n\n# Plot the Football Field.\n# Source: https://www.kaggle.com/robikscube/nfl-big-data-bowl-plotting-player-position\ndef create_football_field(linenumbers=True,\n                          endzones=True,\n                          highlight_line=False,\n                          highlight_line_number=50,\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    return fig, ax","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 2. Data Information\n# 2.1 Basic Data Info\nThe Dataset contains 3 files in csv format, and they are:<br>\n<br>\n* **Injury Record:** The injury record file in .csv format contains information on 105 lower-limb injuries that occurred during regular season games over the two seasons. Injuries can be linked to specific records in a player history using the PlayerKey, GameID, and PlayKey fields.\n\n* **Play List:** The play list file contains the details for the 267,005 player-plays that make up the dataset. Each play is indexed by PlayerKey, GameID, and PlayKey fields. Details about the game and play include the player’s assigned roster position, stadium type, field type, weather, play type, position for the play, and position group.\n\n* **Player Track Data:** Player level data that describes the location, orientation, speed, and direction of each player during a play recorded at 10 Hz (i.e. 10 observations recorded per second).\n<br>\n\nEvery file is mapped in a variable, where every variable is a dataframe as shown in the Table 1.\n\n**Table 1 - Data File mapped Variables**\n   \n|File   |Variable |\n|---|---|\n| Injury Record  | `injury_record`|\n|  Play List | `play_list`|\n|  Player Track Data | `player_track`|<br>"},{"metadata":{},"cell_type":"markdown","source":"All the data was collected by [NFL Next Gen Stats](https://nextgenstats.nfl.com/), this system collects player information (location, speed) in match in real time, granting the possibility to make big data analysis. The dataset collects information of 250 Players, as described on the [data information for this competition](https://www.kaggle.com/c/nfl-playing-surface-analytics/data) for two seasons.<br> Every dataset by connected by keys as shown on Table 2, it is useful to take note because will be helpful to make dataframe joins.\n\n**Table 2 - Data File Keys**\n\n|File|PlayerKey|GameID|Playkey|\n|---|---|---|---|\n| Injury Record  | yes| yes |yes |\n|  Play List | yes| yes |yes |\n|  Player Track Data | no| no |yes |"},{"metadata":{},"cell_type":"markdown","source":"Let's load the data and see information about every file, like number of columns, samples, data type and missing values. And for now on, every file is treated as it variable name. Columns in dataframes will be called features and rows as samples."},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":false},"cell_type":"code","source":"injury_record = import_data(DATA_PATH+\"InjuryRecord.csv\")\nplay_list = import_data(DATA_PATH+\"PlayList.csv\")\nplayer_track = pd.read_csv(DATA_PATH+\"PlayerTrackData.csv\")","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"print('injury_record Data Information')\nget_df_info(injury_record)\nprint('play_list Data Information')\nget_df_info(play_list)\nprint('player_track Data Information')\nget_df_info(player_track)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Some important notes to take about these dataframes:\n* `injury_record` has 28 missing values, it represents almost 30% of the total values, the dataframe has 105 samples, is tiny. It's an important feature to use to make de Explanatory Data Analysis (EDA). A good way is reconstruct the `PlayKey`.\n* `injury_record` has features one-hot encoded (DM_M1 to DM_42), which represent the amount of days that the Player is out of the Season, to make easy the EDA, this feature will return to the original values as integer type.\n* `play_list` has a good amount of samples (267005) and features (14) and it will provide so much valuable information to get insights and how the injuries ocurred. The missing values could be bypassed with Feature Engineering or dropped if so tiny in relation of the dataframe total size.\n* `player_track` has a huge amount of samples (76366748) and 9 features and it provides the coordinates, speed and time of plays. On the missing values it has a tiny amount in `o` and `dir`, it could be dropped, but `event` has a extreme large amount (74526875), it's good investigate the values when make the EDA.\n\nTime to deal with the issues on the dataframes, let's start understanding how `PlayKey` is build and try to reconstruct it. <br>\nLet's clean the data and proceed with the analysis."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"# Clean Data\n# StadiumType corrections\nstadium_dict = {\"Oudoor\" : \"Outdoor\", \"Outdoors\" : \"Outdoor\", \"Outdor\" : \"Outdoor\", \"Ourdoor\" : \"Outdoor\", \n                \"Outdoor Retr Roof-Open\" : \"Outdoor\", \"Open\" : \"Outdoor\", 'Outdoor Retr Roof-Open' : \"Outdoor\",\n                \"Outddors\" : \"Outdoor\", 'Retr. Roof-Open' : \"Outdoor\",  \"Indoor, Open Roof\" : \"Outdoor\", \"Heinz Field\" : \"Outdoor\",\n                 \"Domed, Open\" : \"Outdoor\", \"Domed, open\" : \"Outdoor\", 'Retr. Roof - Open' : \"Outdoor\", \"Outside\" : \"Outdoor\",\n                \"Closed Dome\" : \"Indoor\", \"Domed, closed\" : \"Indoor\", \"Dome\" : \"Indoor\", \"Domed\" : \"Indoor\", \n                \"Indoors\" : \"Indoor\", 'Retr. Roof-Closed' : \"Indoor\", \"Retractable Roof\" : \"Indoor\",  'Indoor, Roof Closed' : \"Indoor\",\n                \"Retr. Roof - Closed\" : \"Indoor\", 'Dome, closed' : \"Indoor\", \"Retr. Roof Closed\" : \"Indoor\", \"nan\" : np.NaN, 'Cloudy' : np.NaN}\n\n# Weather corrections\nweather_dict = {\"Indoors\" : \"Indoor\", \"N/A (Indoors)\": \"Indoor\", \"Clear skies\" : \"Clear\", \"Clear Skies\" : \"Clear\",\n                \"Clear and cold\" : \"Clear\", 'Cloudy, light snow accumulating 1-3\"' : \"Cloudy\",\n                \"Rain shower\" : \"Rain\", \"Cloudy, 50% change of rain\" : \"Cloudy\", \"Clear and warm\" : \"Clear\", \n                \"Cloudy with periods of rain\" : \"Cloudy\", \"Light Rain\" : \"Rain\", \"Light rain\" : \"Rain\", 'Rain Chance 40%' : \"Cloudy\",\n                \"Mostly sunny\" : \"Sunny\", \"Mostly Sunny\" : \"Sunny\", \"Sun & clouds\" : \"Sunny\", \"Partly Cloudy\" : \"Cloudy\",\n                \"Partly cloudy\" : \"Cloudy\", \"Coudy\" : \"Cloudy\", \"Party Cloudy\" : \"Cloudy\", \"Mostly Cloudy\" : \"Cloudy\",\n                \"Mostly cloudy\" : \"Cloudy\", \"Cloudy, 50% change of rain\" : \"Cloudy\", \"Cloudy and Cool\" : \"Cloudy\" , \"nan\" : np.NaN,\n               'Cloudy, fog started developing in 2nd quarter' : \"Cloudy\", 'N/A Indoor' : \"Indoor\", 'Rain likely, temps in low 40s.' : \"Rain\",\n               'Mostly Coudy' : \"Cloudy\", 'Scattered Showers' : \"Showers\", 'Heavy lake effect snow' : \"Snow\", 'Sunny Skies' : \"Sunny\",\n               'Partly clear' : \"Clear\", 'Sunny, Windy' : \"Sunny\", 'cloudy' : \"Cloudy\", 'Sunny, highs to upper 80s' : \"Sunny\",\n               'Cloudy with periods of rain, thunder possible. Winds shifting to WNW, 10-20 mph.' : \"Cloudy\", '10% Chance of Rain' : \"Cloudy\",\n               '30% Chance of Rain' : \"Cloudy\", 'Mostly Sunny Skies' : \"Sunny\", 'Rainy' : \"Rain\", 'Cloudy, chance of rain' : \"Cloudy\",\n               'Partly Clouidy' : \"Cloudy\", 'Partly Sunny' : \"Sunny\", 'Partly sunny' : \"Sunny\", 'Cloudy, Rain' : \"Rain\",\n               'Clear and sunny' : \"Clear and Sunny\", 'Clear and Cool' : \"Clear and Cold\", 'Heat Index 95' : \"Sunny\", 'Clear to Partly Cloudy' : \"Clear\",\n               'Clear and Cold' : 'Clear and cold'}\n\n# Revert Days Missed to the Original\ndays_missed_dict = {1 : \"1+\", 2: \"7+\", 3 : \"28+\", 4 : \"42+\"}\n\nplay_list[\"StadiumType\"] = play_list[\"StadiumType\"].astype(str)\nplay_list[\"StadiumType\"].replace(stadium_dict, inplace=True)\nplay_list[\"Weather\"] = play_list[\"Weather\"].astype(str)\nplay_list[\"Weather\"].replace(weather_dict, inplace=True)\nplay_list[\"PlayType\"] = play_list[\"PlayType\"].replace('0', np.NaN)\ninjury_record['DaysMissed'] = injury_record['DM_M1'] + injury_record['DM_M7'] + injury_record['DM_M28'] + injury_record['DM_M42']\ninjury_record['DaysMissed'] = injury_record[\"DaysMissed\"].map(days_missed_dict)\ninjury_record.drop([\"DM_M1\", \"DM_M7\", \"DM_M28\", \"DM_M42\"], axis=1, inplace=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 2.2 Reconstructing \"PlayKey\" missing values\nTo start the reconstruction, let's find if there's any `PlayKey` value duplicated."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"display(injury_record[injury_record.duplicated([\"PlayKey\"], keep=False)]\n        .dropna().style.hide_index())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"And what's mean the duplicated sample? As can be noted on `BodyPart`, which represents where the player suffered an injury, there are two different injury types: on knee and on ankle, it's not necessarily a duplicated sample, but just a way to input how the player got ywo injuries at the same time.<br>\nThis sample will be not dropped for now.<br>\n<br>\nTime to understand the format of `PlayKey` feature, as can be see the format follows this structure, starting with `GameID` format:<br>\n<br>\n`GameID` = `PlayerKey`+`x`<br>\n<br>\nWhere `x` represents the match that the player is in, with this information, let's understand now `PlayKey`: <br>\n<br>\n`PlayKey` = `GameID`+`y`<br>\n<br>\nWhere `y` represents the moment of the match that the player makes a play, and matches with `PlayerGamePlay` in `play_list`, but we have missing values for it at `injury_record`, how to reconstruct it?<br>\nLet's think about the `GameID` on `play_list`, it value occurs many times and some players get lesser occurrences of it. Why?<br>\nWe can guess that the last ocurrence is the moment when the player finish his play or the player gets a injury and he is out of the game, hence his last participation in that game. <br>\nNow, compare with the `PlayKey` values on `injury_record` and check if the last ocurrence has the same `PlayKey` in `injury_records`, for it, let's create a DataFrame with the last `PlayKey` in a `GameID` and see the first 15 samples in `play_list` and `injury_record`.<br>"},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"gameid_list = injury_record[\"GameID\"]\n\ndf_aux = pd.DataFrame().reindex_like(play_list)\ndf_aux = df_aux.dropna().reset_index()\nfor id in gameid_list:\n    df_aux_b = play_list[play_list[\"GameID\"] == id]\n    df_aux = df_aux.append(df_aux_b.tail(1))\ndf_aux = df_aux.drop(\"index\", 1).reset_index(drop=True)\ndisplay(df_aux.head(15).style.hide_index())\ndisplay(injury_record.head(15).style.hide_index())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"And for the last 15 samples."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"display(df_aux.tail(15).style.hide_index())\ndisplay(injury_record.tail(15).style.hide_index())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As can be noted, the `GameID` in the `play_list` follows the same order on `injury_record`, and if we can see at the `PlayKey` at `play_list` are almost the same, except for the values \"44806-7-61\"/\"44806-7-62\", just these values not coincide, but are near in number, maybe an error? Let's consider it as valid. <br>\t\t\nWe have now a good proof that the last `PlayKey` occurs when the player got injured. <br>\nWith this information, would be possible reconstruct `PlayKey` feature. <br>\nTime to input the values in the missing values, the `PlayKey` \"44806-7-61\" will be replaced with 44806-7-62, it will be helpful when make joins."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"injury_record[\"PlayKey\"] = df_aux[\"PlayKey\"]\naux = injury_record.isnull().sum().sum()\nprint(f\"There are {aux} Features with missing values on Injury Record.\")","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"inj_playlist = play_list[[\"PlayKey\", \"RosterPosition\", \"StadiumType\", \"Temperature\", \"Weather\",\n                        \"PlayType\", \"PlayerGamePlay\", \"Position\", \"PositionGroup\"]].merge(\n                        injury_record, on=\"PlayKey\", how=\"left\")\n\ninj_playlist.drop(inj_playlist.columns[9], axis=1)\ndel play_list\ninj_playlist[\"StadiumType\"] = inj_playlist[\"StadiumType\"].astype('category')\ninj_playlist[\"DaysMissed\"] = inj_playlist[\"DaysMissed\"].astype('category')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"With the `PlayKey` missing values gone, it's time to start the EDA."},{"metadata":{},"cell_type":"markdown","source":"# 3. Exploratory Data Analysis (EDA)\n# 3.1 Exploration for Injury Record and Play List\nFor this EDA, let's take some notes:\n* Everytime an analysis needs `BodyPart`, the duplicated sample will be not dropped.\n* Otherwise, the duplicated sample will be dropped.\n\nLet's start looking at the `BodyPart` distribution as shown on Figure 1."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"value = inj_playlist['BodyPart'].value_counts().sort_values(ascending=False)\nlabel = value.index\ntrace = go.Bar(y=value, \n               x=label,\n               marker={'color': value,\n                   'colorscale': 'hsv'})\nlayout = go.Layout(title='Figure 1 - Injured Body Parts', \n                   xaxis={'title' : 'Body Part'},\n                  yaxis={'title' : 'Total Count'},\n                  title_x=0.5)\nfig = go.Figure(data=trace, layout=layout)\niplot(fig)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As can be noted, injuries on the knee and on the ankle are in high number, while injuries in heel are in minor number. It's interisting to note that foot and toes are the same count of injuries, as they have basically the same location.<br>\n<br>\nLet's see the distribution of `Surface` and `DaysMissed`, as shown on Figure 2."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"df_aux = inj_playlist.loc[inj_playlist['BodyPart'].notnull()]\ndf_aux = inj_playlist.drop_duplicates(subset=\"PlayKey\", keep=\"first\", inplace=False)\n\nfig = make_subplots(rows=1, cols=2, specs=[[{\"type\": \"domain\"}, {\"type\": \"domain\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Surface Distribution', \n                                      '(b) Minimum Days Missed Distribution'))\n\nfeatures = [\"Surface\", \"DaysMissed\"]\ncol_num = 1\nfor i in features:\n    value = df_aux[i].value_counts()\n    label = value.index\n    fig.add_trace(go.Pie(labels=label, \n                         values=value,\n                         showlegend=False,\n                         hoverinfo=\"value\",\n                         title_text=\" \",\n                         title_position = \"top center\",\n                         texttemplate = \"%{label} <br>(%{percent})\",\n                         textposition = \"inside\"),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, title=\"Figure 2 - Surface and Days Missed Distribution\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"On the Figure 2(a) can be noted that most injuries occur on Synthetic Surface (53.8%), not so imbalanced when compared to Natural Surface (46.2%), leading most times to 7 or more days missed on the season, as described by Figure 2(b). It's interesting to note that 1 or 42 more days missed are the same percent distribution (27.9%).\nLet's go more deeper in this analysis, let's see the Body Part Injuries by Surface, as shown on Figure 3."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=2, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Synthetic)', \n                                      '(b) Natural)'))\n\nfeature = \"BodyPart\"\nfeature_filter = \"Surface\"\nfeature_value = [\"Synthetic\", \"Natural\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    df_aux = df_aux[feature].value_counts()\n    df_aux = df_aux[df_aux > 0]\n    value = df_aux.values\n    label = df_aux.index\n\n    fig.add_trace(go.Bar(y=value, \n                         x=label,\n                         hoverinfo='y',\n                         showlegend=False,\n                         marker={'color': value,\n                         'colorscale': 'hsv'}),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 3 - Injuries by Surface Type\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The Figures 3(a) and 3(b) show that most injuries on Knee and Ankle are high in both surfaces, but it's important to take note that Ankle injuries are the most in the Synthetic, but in Natural there are much less of it.<br>\nOn the Natural Surface there are less injuries on Toes than on Synthetic and more Injuries on Foot on Natural than on Synthetic. <br>\nInjuries on Heel are rare on both. <br>\n<br>\nLet's see how the missed days are distributed by surfaces on the Figure 4."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=2, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Synthetic)', \n                                      '(b) Natural)'))\n\nfeature = \"DaysMissed\"\nfeature_filter = \"Surface\"\nfeature_value = [\"Synthetic\", \"Natural\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    df_aux = df_aux[feature].value_counts()\n    df_aux = df_aux[df_aux > 0]\n    value = df_aux.values\n    label = df_aux.index\n\n    fig.add_trace(go.Bar(y=value, \n                         x=label,\n                         hoverinfo='y',\n                         showlegend=False,\n                         marker={'color': value,\n                         'colorscale': 'hsv'}),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 4 - Days Missed by Surface Type\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The Figure 4(a) and 4(b) show the same distribution for the Days Missed. <br>\nMany athletes miss 7 or more days in the season due injuries, the count is almost same for both surfaces, 19 on Synthetic and 20 on Natural, while 42 or more days and 1 or more days are equals, in Synthetic or Natual. An athlete have more chances to miss 28 or more days in Synthetic Surface than on Natural Surface. <br>\nLet's analysis the total Days Missed by each injurie body part and show in the Figure 5."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature = \"DaysMissed\"\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    df_aux = df_aux[feature].value_counts()\n    df_aux = df_aux[df_aux > 0]\n    value = df_aux.values\n    label = df_aux.index\n\n    fig.add_trace(go.Bar(y=value, \n                         x=label,\n                         hoverinfo='y',\n                         showlegend=False,\n                         marker={'color': value,\n                         'colorscale': 'hsv'}),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 5 - Injuries by Days Missed\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's explore the injuries get on the Play Type as shown on Figure 6."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature = \"PlayType\"\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    df_aux = df_aux[feature].value_counts()\n    df_aux = df_aux[df_aux > 0]\n    value = df_aux.values\n    label = df_aux.index\n\n    fig.add_trace(go.Bar(y=value, \n                         x=label,\n                         hoverinfo='y',\n                         showlegend=False,\n                         marker={'color': value,\n                         'colorscale': 'hsv'}),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=850, title=\"Figure 6 - Injuries by Play Type\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Most Ankle, Knee and Toe injuries occur in Pass or Rush Play Types, while Punt types will injury the player sometimes in the Knee.<br>\nTime to explore the injuries by Roster Position, as shown on the Figure 7."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature = \"RosterPosition\"\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    df_aux = df_aux[feature].value_counts()\n    df_aux = df_aux[df_aux > 0]\n    value = df_aux.values\n    label = df_aux.index\n\n    fig.add_trace(go.Bar(y=value, \n                         x=label,\n                         hoverinfo='y',\n                         showlegend=False,\n                         marker={'color': value,\n                         'colorscale': 'hsv'}),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=870, title=\"Figure 7 - Injuries by Roster Position\", \n                  title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Linebackers and Wide Receivers have a high chance to get injuries on Ankle and Knee, the other injuries types are rare in any Position.<br>\nLet's check the weather when a player get a injury, showed on the Figure 8."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature = \"Weather\"\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    df_aux = df_aux[feature].value_counts()\n    df_aux = df_aux[df_aux > 0]\n    value = df_aux.values\n    label = df_aux.index\n\n    fig.add_trace(go.Bar(y=value, \n                         x=label,\n                         hoverinfo='y',\n                         showlegend=False,\n                         marker={'color': value,\n                         'colorscale': 'hsv'}),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=850, title=\"Figure 8 - Injuries by Weather\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Cloudy weather has a high count for Ankle and Knee injuries, and these injuries occur sometimes in a Sunny Weather. Foot injuries have more frequency in Cloudy weather too.<br>\nHeel injuries only occured in Sunny and clear weather.<br>\nLet's check the injuries occured by Stadium Type, as shown on the Figure 9.<br>\nAny retractable roof is classified as your state at moment, Outdoor if open, Indoor if closed."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature = \"StadiumType\"\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    df_aux = df_aux[feature].value_counts()\n    df_aux = df_aux[df_aux > 0]\n    value = df_aux.values\n    label = df_aux.index\n\n    fig.add_trace(go.Bar(y=value, \n                         x=label,\n                         hoverinfo='y',\n                         showlegend=False,\n                         marker={'color': value,\n                         'colorscale': 'hsv'}),\n                         row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 9 - Injuries by Stadium Type\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The most part of injuries occured in Outdoor Stadiums, except on Toes that occured more in the Indoor Stadiums.<br>\nTime to explore the Temperature distribution by injury, showed on the Figure 10."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"inj_playlist[\"Temperature\"] = inj_playlist[\"Temperature\"].replace(-999, np.NaN)\n\nfig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_playlist[inj_playlist[feature_filter] == i]\n    value = df_aux.Temperature.values\n\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 10 - Injuries by Temperature\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Ankle, Knee and Foot injuries occur between 60°F and 80°F, with more occurences of knee injuries occurring near 80°F. <br>\nToes and Heel injuries have equal distribution, between 40°F and 99°F for Toes, while Heel occurring between 42.5°F and 43.5°F.<br>\nLet's check the correlation (Pearson and Spearman) between some features, with not some distinct values for categorics, as shown on Figure 11.\n"},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"days_miss_dict = {\"1+\" : 1, \"7+\" : 2, \"28+\" : 3, \"42+\" : 4}\n\ninj_playlist['Days_Missed'] = inj_playlist[\"DaysMissed\"].map(days_miss_dict)\ninj_playlist['Days_Missed'] = inj_playlist[\"Days_Missed\"].astype(float)\n\nbody_part_dict = {\"Ankle\" : 0, \"Knee\" : 1, \"Toes\" : 2, \"Foot\" : 3, \"Heel\" : 4}\n\ninj_playlist[\"Body_Part\"] = inj_playlist[\"BodyPart\"].map(body_part_dict)\ninj_playlist[\"Body_Part\"] = inj_playlist[\"Body_Part\"].astype(float)\n\nsurface_dict = {\"Synthetic\" : 0, \"Natural\" : 1}\n\ninj_playlist[\"Surface_\"] = inj_playlist[\"Surface\"].map(surface_dict)\ninj_playlist[\"Surface_\"] = inj_playlist[\"Surface_\"].astype(float)\n\n\nstadium_dict = {\"Outdoor\" : 0, \"Indoor\" : 1, \"Bowl\" : 2, \"Heinz Field\" : 3, \"Outside\" : 4}\n\ninj_playlist[\"Stadium_Type\"] = inj_playlist[\"StadiumType\"].map(stadium_dict)\ninj_playlist[\"Stadium_Type\"] = inj_playlist[\"Stadium_Type\"].astype(float)\n\nplaytype_dict = {'Pass' : 0,\n 'Rush' : 1,\n 'Kickoff' : 2,\n 'Kickoff Not Returned' : 3,\n 'Kickoff Returned' : 4,               \n 'Field Goal' : 5,\n 'Punt' : 6,\n 'Punt Not Returned' : 7,\n 'Punt Returned' : 8,\n 'Extra Point' : 9}\n\ninj_playlist[\"Play_Type\"] = inj_playlist[\"PlayType\"].map(playtype_dict)\ninj_playlist[\"Play_Type\"] = inj_playlist[\"Play_Type\"].astype(float)\n\nf,ax = plt.subplots(figsize=(12, 9))\nsns.heatmap(inj_playlist.corr(\"pearson\"), annot=True, linewidths=.5, fmt= '.4f',ax=ax)\nplt.title(\"Figure 11(a) - Correlation of some Features (Pearson)\", fontsize=14)\nplt.show()\n\nf,ax = plt.subplots(figsize=(12, 9))\nsns.heatmap(inj_playlist.corr(\"spearman\"), annot=True, linewidths=.5, fmt= '.4f',ax=ax)\nplt.title(\"Figure 11(b) - Correlation of some Features (Spearman)\", fontsize=14)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Analyzing the features correlation (Pearson and Spearman) with `BodyPart`, can be noted:\n* None of the features have a high correlation (0.75 or more, negative or positive) with `BodyPart`.\n* `BodyPart` has positive correlation with all features."},{"metadata":{},"cell_type":"markdown","source":"# 3.2 Exploring Player Track Data\n\nLet's explore the `player_track` and see how the plays lead the player to an injury.<br>\nStarting with the routes for injured players in synthetic field, as shown on Figure 12. See this nice [Kernel](https://www.kaggle.com/robikscube/nfl-1st-and-future-analytics-intro) where the field plot was developed."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"df_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Synthetic\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Ankle\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 12(a) - Routes for Ankle Injuries (Synthetic)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Synthetic\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Knee\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 12(b) - Routes for Knee Injuries (Synthetic)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Synthetic\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Toes\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 12(c) - Routes for Toes Injuries (Synthetic)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Synthetic\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Foot\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 12(d) - Routes for Foot Injuries (Synthetic)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Synthetic\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Ankle\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 12(e) - Routes for Heel Injuries (Synthetic)\", fontsize=14)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"On Figure 12 we can note:\n* Ankle, Knee and Heel injuries there are no visible pattern.\n* There some routes outside the field for knee injuries.\n* Toes Injuries are near from the traced lines of the field center.\n* Foot Injuries are outside from the traced lines of the field center.\n\nAnd now on Natural Surface, as shown on Figure 13."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"df_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Natural\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Ankle\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 13(a) - Routes for Ankle Injuries (Natural)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Natural\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Knee\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 13(b) - Routes for Knee Injuries (Natural)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Natural\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Toes\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 13(c) - Routes for Toes Injuries (Natural)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Natural\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Foot\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 13(d) - Routes for Foot Injuries (Natural)\", fontsize=14)\nplt.show()\n\ndf_syn = inj_playlist[inj_playlist[\"Surface\"] == \"Natural\"]\ndf_syn = df_syn[df_syn[\"BodyPart\"] == \"Ankle\"]\ndf_syn_list = df_syn['PlayKey'].tolist()\nfig, ax = create_football_field()\nfor playkey, inj_play in player_track.query('PlayKey in @df_syn_list').groupby('PlayKey'):\n    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)\n\nplt.title(\"Figure 13(e) - Routes for Heel Injuries (Natural)\", fontsize=14)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"On the Figure 13 we can note:\n* Ankle, Knee and Heel injuries there are no visible pattern.\n* There are concentrated knee injuries on the traced lines of the field center.\n* Toes Injuries are inside from the traced lines of the field center.\n* Foot Injuries are outside from the traced lines of the field center, with some part of the route on the traced lines on the field center."},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":false},"cell_type":"code","source":"df_data = {\"delta_time\": [0.0], \"delta_x\": [0.0], \"delta_y\": [0.0], \n                               \"delta_dir\": [0.0], \"delta_dis\": [0.0], \"delta_o\": [0.0], \"delta_s\": [0.0]}\n\n\ndf_aux_c = pd.DataFrame(columns=[\"delta_time\", \"delta_x\", \"delta_y\", \"delta_dir\", \"delta_dis\", \"delta_o\", \"delta_s\"])\ndf_aux = pd.DataFrame(data=df_data)\ndf_aux_b = inj_playlist[inj_playlist.BodyPart.notnull()]\nfor i in range(len(inj_playlist[inj_playlist.BodyPart.notnull()])):\n    aux = df_aux_b[\"PlayKey\"].values[i]\n    aux = player_track[player_track[\"PlayKey\"] == aux]\n    aux_a = aux.head(1)\n    aux_b = aux.tail(1)\n    df_aux_c[[\"delta_time\", \"delta_x\", \"delta_y\", \"delta_dir\", \"delta_dis\", \"delta_o\", \"delta_s\"]] = aux_b[[\"time\",\n                                                                                                          \"x\", \"y\", \"dir\", \"dis\", \n                                                              \"o\", \"s\"]] - aux_a[[\"time\", \"x\", \"y\", \"dir\", \"dis\", \"o\", \"s\"]].values\n    df_aux = df_aux.append(df_aux_c)\n    df_aux_c.reset_index(drop=True, inplace=True)\n    df_aux_c = df_aux_c.drop(df_aux_c.index[0])\n    df_aux.reset_index(drop=True, inplace=True)\ndf_aux = df_aux.drop(df_aux.index[0])","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"inj_track = pd.concat([injury_record, df_aux], axis=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"For the other features on `player_track` (`time`, `x`, `y`, `dir`, `dis`, `o`, `s`), let's calculate the difference between the feature value at the end of the play and the start of the play, and call it \"Delta\". <br>\nI will not use absolute values, because is worth to see any change for negative values, like orientatation changes. <br>\nStarting with Delta Time, on the Figure 14. This feature cannot get negative values."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_track[inj_track[feature_filter] == i]\n    value = df_aux.delta_time.values\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 14 - Injuries by Delta Time\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can see that most Ankle and Knee injuries occur before 40s, while all toe injuries occur before 40s. Foot injuries occur most times between 20s and 30s. The documented Heel injury occured around 30s.<br>\nLet's check Delta X on the Figure 15."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_track[inj_track[feature_filter] == i]\n    value = df_aux.delta_x.values\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 15 - Injuries by Delta X\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Notable things here:\n* Most Ankle injuries occur when Delta X goes negative.\n* Most Knee injuries occur with Delta X around zero, almost no movement at x coordinate of the field.\n<br>\n<br>\nLet's see Delta Y on the Figure 16."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_track[inj_track[feature_filter] == i]\n    value = df_aux.delta_y.values\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 16 - Injuries by Delta Y\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"While Delta X goes negative most times for Ankle injuries, Delta Y goes positive.<br>\nKnee injuries have some outliers with negative values near -40. Most Toes injuries are negative.<br>\nTime to explore Delta Direction on the Figure 17."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_track[inj_track[feature_filter] == i]\n    value = df_aux.delta_dir.values\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 17 - Injuries by Delta Direction\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"There's no much changes in direction for Ankle and Knee injuries, most values are around 0. In toes, most injuries occur between 0 and 100. <br>\nLet's the Delta distance on the Figure 18.\n"},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_track[inj_track[feature_filter] == i]\n    value = df_aux.delta_dis.values\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 18 - Injuries by Delta Distance\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Interest to note in the Figure 18 that most injuries not occur by changes in distance, and sometimes the value is negative, maybe the player got a super tackle? We can see that only for heel injury the player got 1 yard in the delta.<br>\nLet's explore the Delta Orientation on the Figure 19."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_track[inj_track[feature_filter] == i]\n    value = df_aux.delta_o.values\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 19 - Injuries by Delta Orientation\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"On the orientation, most injuries occur with no changes, but on heel there's a change between -179 and -178 degrees.\n\nAnd finally, explore Delta speed on the Figure 20."},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, specs=[[{\"type\": \"xy\"}, {\"type\": \"xy\"}, {\"type\": \"xy\"},\n                                          {\"type\": \"xy\"}, {\"type\": \"xy\"}]], \n                    shared_xaxes=True, shared_yaxes=True,\n                    vertical_spacing=1,\n                    subplot_titles = ('(a) Ankle', \n                                      '(b) Knee',\n                                      '(c) Toes',\n                                      '(d) Foot',\n                                      '(e) Heel'))\n\nfeature_filter = \"BodyPart\"\nfeature_value = [\"Ankle\", \"Knee\", \"Toes\", \"Foot\", \"Heel\"]\ncol_num = 1\n\nfor i in feature_value:\n    df_aux = inj_track[inj_track[feature_filter] == i]\n    value = df_aux.delta_s.values\n    fig.add_trace(go.Histogram(x=value, showlegend=False),\n                 row=1, col=col_num)\n    col_num = col_num+1\n\nfig.update_layout(height=500, width=800, title=\"Figure 20 - Injuries by Delta Speed\", title_x=0.5)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"For all injuries, the most values are around 0 speed (No movement), with some peaks between 2 and 4 yards/s for knee, foot and toes injuries.<br>\nLet's see the correlation of the Delta Features with the injured body part on Figure 21.\n"},{"metadata":{"_kg_hide-input":true,"trusted":false},"cell_type":"code","source":"inj_track = inj_track.drop(columns=['PlayerKey'])\n\ninj_track[\"Body_Part\"] = inj_track[\"BodyPart\"].map(body_part_dict)\ninj_track[\"Body_Part\"] = inj_track[\"Body_Part\"].astype(float)\n\nf,ax = plt.subplots(figsize=(12, 9))\nsns.heatmap(inj_track.corr(\"pearson\"), annot=True, linewidths=.5, fmt= '.4f',ax=ax)\nplt.title(\"Figure 21(a) - Correlation of Delta Features with Body Part (Pearson)\", fontsize=14)\nplt.show()\n\nf,ax = plt.subplots(figsize=(12, 9))\nsns.heatmap(inj_track.corr(\"spearman\"), annot=True, linewidths=.5, fmt= '.4f',ax=ax)\nplt.title(\"Figure 21(b) - Correlation of Delta Features with Body Part (Spearman)\", fontsize=14)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"On Spearman's Rank coefficient can be noted that all Delta Features have positive correlation with the injured body part, but on the Pearson coefficient, there's a difference on the correlation between Delta Time and the Body Part, is negative here,confirming the information obtained in the Figure 14, where as shown with more time in a play, more chances to get a heel injury, and explain why at certain moments the Ankle and Knee injuries are present in the increased time of the play and decrease when have high values."},{"metadata":{},"cell_type":"markdown","source":"# 4. Conclusion\n\nOn this work, the data about injuries on football was explored and explained. <br>\nWe can draw the following conclusions:\n* Ankle and Knee injuries are the most commons.\n* Heel injury is the most rare.\n* Most injuries occur in Synthetic Surfaces.\n* A player is out of season, due injuries, most times between 1 and 7 days, or in long 42 or more days.\n* Pass is the Play Type with most injuries.\n* Linebackers and Wide Receivers have most injury risk.\n* Most injuries occur in cloudy weather.\n* Most injuries occur in Outdoor stadiums.\n* High Temperatures contribute for injuries.\n* Toes injuries occur most times in the center of the field, for both surfaces.\n* Plays with high time value tend to cause more heel injuries, but remember that a heel injury is rare to confirming it with the available data.\n* Players that got injured are stopped in few yards of distance. \n\nIn this finish my work here! <br>\nFeel free to give your feedback, I will appreciate it.<br>\n<br>\nThanks for your reading!\n\n![](https://media.giphy.com/media/jwKpxz0uGrqcTjDKvs/giphy.gif)"}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.6"}},"nbformat":4,"nbformat_minor":4}