{"cells":[{"metadata":{"_uuid":"79d24e7bbfbb2ac460862d9029c6f3fe741a1238"},"cell_type":"markdown","source":"# ------------------------------\n\n**MY PROPOSALS FOR REDUCING THE DANGER DURING PUNT PLAYS**\n\n- **To Prevent a player from lowering the heads to initiate contact with the helmet, give a constraint of tackling/blocking techniques**\n\n**RULE**\n\n- **Players who does not tackle/block “correctly” will receive a warning, and the team may get 5, 10, or 15 yards penalty when they receive it repeatedly.**\n\n# ------------------------------"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"markdown","source":"## Abstract\n\n### Objectives\n\n- To demonstrate how much the tackler’s head position and his speed during one-on-one tackling are related to the injury through analyzing game videos and NGS datasets.\n\n\n### Methods\n\n- Game Video Review data in which the injury play can be identified (37 samples).\n    - Video URL\n    - Player Activity Derived\n    - Primary Impact Type\n- NGS data which contains player position and direction data for each player during the entire course of the play. The NGS dataset is the only dataset that contains Time as a variable. Speed can be calculated from the provided time, and X, Y position coordinates of the player.\n\n\n### Results\n\n- Analyzing all 37 game video reviews provided in detail, you can notice some common features which may be related to cause the injury:\n    - players concerned to the injury tended to rush fastly to tackle/block \n    - players who got injured tended to lower the heads to initiate contact with the helmet\n\n\n### Conclusions\n\nTo solve these problems, the following ways will be effective:\n\n- **To prevent lower the heads to initiate contact with the helmet**\n    - give a constraint of tackling/blocking techniques"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","collapsed":true,"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"markdown","source":"---"},{"metadata":{"_uuid":"e8ee16cd8db0b497e04fa296c8a0d0caababb1ae"},"cell_type":"markdown","source":"## Introduction\n\nNFL has challenged to reduce the risk of injury and improve the safety for players. For this reason, NFL revised their kickoff rules by examining comprehensive review, including injury reports, player position and velocity data, and game video. It revealed that players had approximately four times the risk of concussion on returned kickoffs compared to running or passing plays.  \nIn addition, as of May 2018 NFL has already approved rule change such as kickoff: the main aims are to reduce the collisions in the state of being on speed and the acts of colliding with the helmet, and to enhance the safety of the players.  \nFurthermore, NFL owners also approved the helmet contact rule, which prohibited a player from lowering the head to initiate contact with the helmet against an opponent. Although this rule led to confusion and caused controversy, it is still an urgent task to deal with dangerous tackles, as there is an example that Pittsburgh Steelers linebacker Ryan Shazier injured by his tackle that ended his season in 2017.  "},{"metadata":{"trusted":true,"_uuid":"ad75a1aa50425da569e7b52c8b2a6308daa4e5b7","_kg_hide-input":true},"cell_type":"code","source":"from IPython.display import YouTubeVideo\nYouTubeVideo(\"voFHkaRWXvg\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e500ba729fe8109dd1e3283603160461606d773f"},"cell_type":"markdown","source":"To imporve the safety for players much further, they think that punt play rules should also be changed. We, kagglers, are challenged to this task with analyzing various data for all punt plays from the 2016 and 2017 NFL seasons that includes player rosters, on-field position data and video data, including the plays in which a player suffered a concussion.  \n\nSo, what should we do?  \n\nI will propose some rules to be changed. The idea of this notebook comes from [Garry's great kernel](https://www.kaggle.com/garlsham/nfl-punt-rule-changes-interactive-plots) that insipred me with referring to a rugby-style tackle, and most of this notebook owes to a precendent research paper: \n\n- ***Tackler’s head position relative to the ball carrier is highly correlated with head and neck injuries in rugby***  \n**http://dx.doi.org/10.1136/bjsports-2017-098135  **\n\nAccording to the research on the relationship between tackler's head position in rugby and the frequency of the occurrance of the concussion, tackling with incorrect head position relative to the ball carrier resulted in a significantly higher incidence of concussions, neck injuries, stingers and nasal fractures than tackling with correct head position. (the definition of the \"incorrect\" head position will be explained later)"},{"metadata":{"_uuid":"e6dcc3d542c45337f79fa7fa51946fe8a6191097"},"cell_type":"markdown","source":"## Objectives\n\nTo demonstrate how much the tackler’s head position and his speed during one-on-one tackling are related to the injury through analyzing game videos and NGS datasets.\n\n\n### Definitions\n\n- **tackle correct/incorrect**\n\nAccording to the research paper, there are two categories of the tackle. The first (*Figure A below*) is the tackles with correct head positioning, meaning that the tackler's head was behind or to one side of the ball carrier. The second (*Figure B below*) is the tackles with incorrect head positioning, meaning that the tackler’s head was in front of the ball carrier at the time of contact. below the figures are shown."},{"metadata":{"_uuid":"fd623ed3c8d23201940f4f62e9577b9b21739f42"},"cell_type":"markdown","source":"**Description**: Figure A is a correct tackle. Figure B is an incorrect tackle. The arrow means the direction of the ball carrier.\n\n<img src=\"https://prtimes.jp/i/21495/52/resize/d21495-52-166201-2.jpg\" alt=\"FigureA_and_FigureB\" title=\"FigureA_and_FigureB\">\n\n> cited from: https://prtimes.jp/main/html/rd/p/000000052.000021495.html"},{"metadata":{"_uuid":"e8341c2444f20785d81e4b5867a47468c233dd14"},"cell_type":"markdown","source":"## Methods\n\n- Game Video Review data in which the injury play can be identified (37 samples).\n    - Video URL\n    - Player Activity Derived\n    - Primary Impact Type\n- NGS data which contains player position and direction data for each player during the entire course of the play. The NGS dataset is the only dataset that contains Time as a variable. Speed can be calculated from the provided time, and X, Y position coordinates of the player."},{"metadata":{"_uuid":"084d2f64e4e2ab90ff59e3a51d496b145a09072d"},"cell_type":"markdown","source":"## Results\n\n- Analyzing all 37 game video reviews provided in detail, you can notice some common features which may be related to cause the injury:\n    - players concerned to the injury tended to rush fastly to tackle/block \n    - players who got injured tended to lower the heads to initiate contact with the helmet\n\n### ------------------------------\n\n### Analytics"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"68b735332c64d0f9c400be09e497a9aa62f7d743"},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport glob\nfrom plotly import offline\nimport plotly.graph_objs as go\nimport warnings; warnings.filterwarnings(\"ignore\")\n\nfrom IPython.display import HTML\npd.set_option('max.columns', None)\noffline.init_notebook_mode()\nconfig = dict(showLink=False)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"ffa4c5a603f4007379454205a12415489e040b35"},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \n\ndef reduce_mem_usage(df, verbose=True):\n    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']\n    start_mem = df.memory_usage().sum() / 1024**2    \n    for col in df.columns:\n        col_type = df[col].dtypes\n        if col_type in numerics:\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    end_mem = df.memory_usage().sum() / 1024**2\n    if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))\n    return df","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"bc3f4d26c7ab3b57470e08f748c3ab681b1795a8"},"cell_type":"code","source":"\"\"\"\nhttps://www.kaggle.com/slamer/speed-calculation-quick\n\"\"\"\n\nimport numpy as np\nimport pandas as pd\nimport glob\n\ndef calculate_speeds(df, dt=None, SI=False):\n    data_selected = df[['Time', 'x','y']]\n    if SI==True:\n        data_selected.x = data_selected.x.values / 1.0936132983\n        data_selected.y = data_selected.y.values / 1.0936132983\n    # Might have used shift pd function ?\n    data_selected_diff = data_selected.diff()\n    if dt==None:\n        # Time is now a timedelta and need to be converted\n        data_selected_diff.Time = data_selected_diff.Time.apply(lambda x: (x.total_seconds()))\n        data_selected_diff['Speed'] = np.sqrt(data_selected_diff.x.values **2 + data_selected_diff.y.values **2) / data_selected_diff.Time.values\n    else:\n        # Need to be sure about the time step...\n        data_selected_diff['Speed'] = (data_selected_diff.x.values **2 + data_selected_diff.y.values **2).astype(np.float64).apply(np.sqrt) / dt.values\n    #data_selected_diff.rename(columns={'Time':'TimeDelta'}, inplace=True)\n    #return data_selected_diff\n    df['TimeDelta'] = data_selected_diff.Time\n    df['Speed'] = data_selected_diff.Speed\n    return df[1:]\n\ndef remove_wrong_values(df, tested_columns=['Season_Year', 'GameKey', 'PlayID', 'GSISID', 'TimeDelta'], cutspeed=None):\n    dump = df.copy()\n    colums = dump.columns\n    mask = []\n    for col in tested_columns:\n        dump['shift_'+col] = dump[col].shift(-1)\n        mask.append(\"( dump['shift_\"+col+\"'] == dump['\"+col+\"'])\")\n    mask =eval(\" & \".join(mask))\n    # Keep results where next rows is equally space\n    dump = dump[mask]\n    dump = dump[colums]\n    if cutspeed!=None:\n        dump = dump[dump.Speed < cutspeed]\n    return dump\n\ndef get_speed(df):\n    df_with_speed = df.copy()\n    date_format = '%Y-%m-%d %H:%M:%S.%f'\n    sortBy = ['Season_Year', 'GameKey', 'PlayID', 'GSISID', 'Time']\n    df_with_speed.Time = pd.to_datetime(df_with_speed.Time, format =date_format)\n    df_with_speed.sort_values(sortBy, inplace=True)\n    df_with_speed = calculate_speeds(df_with_speed, SI=True)\n    cut_speed=100 / 9.58 # World record 9,857232 m/s for NFL\n    df_with_speed = remove_wrong_values(df_with_speed, cutspeed=cut_speed)\n    return df_with_speed","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"460c59a43b419585a2a1688532c0ee8f9e43453e"},"cell_type":"code","source":"import pandas as pd\nimport glob\nfrom plotly import offline\nimport plotly.graph_objs as go\n\noffline.init_notebook_mode()\nconfig = dict(showLink=False)\n\nimport os\nimport pandas as pd\nimport numpy as np\nfrom IPython.display import HTML\nimport seaborn as sns\n# import squarify\nimport matplotlib.pyplot as plt\nimport plotly.plotly as py\nfrom plotly.offline import download_plotlyjs, init_notebook_mode, plot,iplot\nimport plotly.figure_factory as ff\n#Always run this the command before at the start of notebook\ninit_notebook_mode(connected=True)\nimport plotly.graph_objs as go\n# import cufflinks as cf\n# cf.set_config_file(offline=True, world_readable=True, theme='ggplot')\nimport warnings\nwarnings.filterwarnings('ignore')\nsns.set_style(\"white\")\nplt.style.use('seaborn')\n\n\n\"\"\"\nReturns a dict for a Football themed Plot.ly layout \n\"\"\" \ndef load_layout():\n    layout = dict(\n        title = \"Player Activity\",\n        plot_bgcolor='darkseagreen',\n        showlegend=True,\n        xaxis=dict(\n            autorange=False,\n            range=[0, 120],\n            showgrid=False,\n            zeroline=False,\n            showline=True,\n            linecolor='black',\n            linewidth=1,\n            mirror=True,\n            ticks='',\n            tickmode='array',\n            tickvals=[10,20, 30, 40, 50, 60, 70, 80, 90, 100, 110],\n            ticktext=['Goal', 10, 20, 30, 40, 50, 40, 30, 20, 10, 'Goal'],\n            showticklabels=True\n        ),\n        yaxis=dict(\n            title='',\n            autorange=False,\n            range=[-3.3,56.3],\n            showgrid=False,\n            zeroline=False,\n            showline=True,\n            linecolor='black',\n            linewidth=1,\n            mirror=True,\n            ticks='',\n            showticklabels=False\n        ),\n        shapes=[\n            dict(\n                type='line',\n                layer='below',\n                x0=0,\n                y0=0,\n                x1=120,\n                y1=0,\n                line=dict(\n                    color='white',\n                    width=2\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=0,\n                y0=53.3,\n                x1=120,\n                y1=53.3,\n                line=dict(\n                    color='white',\n                    width=2\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=10,\n                y0=0,\n                x1=10,\n                y1=53.3,\n                line=dict(\n                    color='white',\n                    width=10\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=20,\n                y0=0,\n                x1=20,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=30,\n                y0=0,\n                x1=30,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=40,\n                y0=0,\n                x1=40,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=50,\n                y0=0,\n                x1=50,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=60,\n                y0=0,\n                x1=60,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),dict(\n                type='line',\n                layer='below',\n                x0=70,\n                y0=0,\n                x1=70,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),dict(\n                type='line',\n                layer='below',\n                x0=80,\n                y0=0,\n                x1=80,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=90,\n                y0=0,\n                x1=90,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),dict(\n                type='line',\n                layer='below',\n                x0=100,\n                y0=0,\n                x1=100,\n                y1=53.3,\n                line=dict(\n                    color='white'\n                )\n            ),\n            dict(\n                type='line',\n                layer='below',\n                x0=110,\n                y0=0,\n                x1=110,\n                y1=53.3,\n                line=dict(\n                    color='white',\n                    width=10\n                )\n            )\n        ]\n    )\n    return layout\n    \n    \n\"\"\"\nLoading and plotting functions\n\"\"\"\n\ndef load_player_role(GSISID):\n    player_role = pd.read_csv('../input/NFL-Punt-Analytics-Competition/play_player_role_data.csv')\n    player_role = player_role[player_role['GSISID'] == GSISID]\n    return player_role\n\n\ndef load_plays_for_game(GameKey):\n    \"\"\"\n    Returns a dataframe of play data for a given game (GameKey)\n    \"\"\"\n    play_information = pd.read_csv('../input/NFL-Punt-Analytics-Competition/play_information.csv')\n    play_information = play_information[play_information['GameKey'] == GameKey]\n    return play_information\n\n\ndef load_game_and_ngs(ngs_file=None, GameKey=None):\n    \"\"\"\n    Returns a dataframe of player movements (NGS data) for a given game\n    \"\"\"\n    if ngs_file is None:\n        print(\"Specifiy an NGS file.\")\n        return None\n    if GameKey is None:\n        print('Specify a GameKey')\n        return None\n    # Merge play data with NGS data    \n    plays = load_plays_for_game(GameKey)\n    ngs = pd.read_csv(ngs_file, low_memory=False)\n    merged = pd.merge(ngs, plays, how=\"inner\", on=[\"GameKey\", \"PlayID\", \"Season_Year\"])\n    return merged\n\n\ndef plot_play(game_df, PlayID, player1=None, player2=None, custom_layout=False):\n    \"\"\"\n    Plots player movements on the field for a given game, play, and two players\n    \"\"\"\n    game_df = game_df[game_df.PlayID==PlayID]\n    \n    GameKey=str(pd.unique(game_df.GameKey)[0])\n    HomeTeam = pd.unique(game_df.Home_Team_Visit_Team)[0].split(\"-\")[0]\n    VisitingTeam = pd.unique(game_df.Home_Team_Visit_Team)[0].split(\"-\")[1]\n    YardLine = game_df[(game_df.PlayID==PlayID) & (game_df.GSISID==player1)]['YardLine'].iloc[0]\n    \n    traces=[]   \n    if (player1 is not None) & (player2 is not None):\n        game_df = game_df[ (game_df['GSISID']==player1) | (game_df['GSISID']==player2)]\n        for player in pd.unique(game_df.GSISID):\n            player = int(player)\n            trace = go.Scatter(\n                x = game_df[game_df.GSISID==player].x,\n                y = game_df[game_df.GSISID==player].y,\n                name='GSISID '+str(player),\n                mode='markers'\n            )\n            traces.append(trace)\n    else:\n        print(\"Specify GSISIDs for player1 and player2\")\n        return None\n    \n    if custom_layout is not True:\n        layout = load_layout()\n        layout['title'] =  HomeTeam + \\\n        ' vs. ' + VisitingTeam + \\\n        '<br>Possession: ' + \\\n        YardLine.split(\" \")[0] +'@'+YardLine.split(\" \")[1]\n    data = traces\n    fig = dict(data=data, layout=layout)\n    play_description = game_df[(game_df.PlayID==PlayID) & (game_df.GSISID==player1)].iloc[0][\"PlayDescription\"]\n    print(\"\\n\\n\\t\",play_description)\n    offline.iplot(fig, config=config)\n    \n\n\"\"\"\nhttps://www.kaggle.com/garlsham/nfl-concussion-analysis-inc-suggested-changes\n\"\"\"\n\ndef get_NGS_data():\n    dir_path = os.getcwd()\n    files = os.listdir('../input/')\n    substring = 'NGS'\n    \n    NGS_files = []\n    for item in files:\n        if substring in item:\n            NGS_files.append(item)\n    \n    data = pd.read_csv('../input/' + NGS_files[0])    \n    for file in NGS_files[1:]:\n        temp_data = pd.read_csv('../input/' + file)\n        data.append(temp_data)\n        \n    return data\n\ndef vid_review_data():\n    dir_path = os.getcwd()\n    vid_data =  pd.read_csv('../input/NFL-Punt-Analytics-Competition/' + 'video_review.csv')\n        \n    return vid_data\n\ndef vid_injury_data():\n    dir_path = os.getcwd()\n    vid_data =  pd.read_csv('../input/NFL-Punt-Analytics-Competition/' + 'video_footage-injury.csv')\n        \n    return vid_data\n\ndef player_role_data():\n    dir_path = os.getcwd()\n    role_data =  pd.read_csv('../input/NFL-Punt-Analytics-Competition/' + 'play_player_role_data.csv')\n        \n    return role_data\n\ndef player_punt_data():\n    dir_path = os.getcwd()\n    punt_data =  pd.read_csv('../input/NFL-Punt-Analytics-Competition/' + 'player_punt_data.csv')\n        \n    return punt_data\n\ndef play_info_data():\n    dir_path = os.getcwd()\n    play_data =  pd.read_csv('../input/NFL-Punt-Analytics-Competition/' + 'play_information.csv')\n        \n    return play_data\n    \n    \ndef perform_merge(data1, data2, columns):\n    merged_data = pd.merge(data1, data2, left_on=columns, right_on=columns, suffixes=['','_1'])\n    return merged_data\n\n\ndef visiting_data(data):\n    score_away = []\n    away_team = []\n    for item in data['Score_Home_Visiting']:\n        scores = item.split('-')\n        temp =  int(scores[1])\n        score_away.append(temp)\n        \n    for item in data['Home_Team_Visit_Team']:\n        teams = item.split('-')\n        temp =  teams[1].strip()\n        away_team.append(temp)\n        \n    data['visiting_team'] = away_team    \n    data['visit_score'] = score_away\n    \n    return data\n\ndef home_data(data):\n    home_score = []\n    home_team = []\n    for item in data['Score_Home_Visiting']:\n        scores = item.split('-')\n        temp =  int(scores[0])\n        home_score.append(temp)\n        \n    for item in data['Home_Team_Visit_Team']:\n        teams = item.split('-')\n        temp =  teams[0].strip()\n        home_team.append(temp)\n\n    data['home_team'] = home_team \n        \n    data['home_score'] = home_score\n    \n    return data\n\ndef score_difference(data):\n    data['score_diff'] = abs(data['home_score'] - data['visit_score'])\n    \n    return data\n\n\ndef punt_received(data):\n    yards_gained = []\n    \n    for row in data['PlayDescription']:\n        temp = row.split('punts')[1].split(' ')[1]\n        yards_gained.append(int(temp))\n    \n    data['kicked_to'] = yards_gained\n    data['kicked_to'] = data['kicked_to'] + data['kicked_from']\n    return data\n\ndef punt_from(data):\n    yardline = []\n    \n    for row in data['YardLine']:\n        temp = row.split(' ')[1]\n        yardline.append(int(temp))\n    \n    data['kicked_from'] = yardline\n    return data\n\ndef opposition_team(data): \n    opposition = []\n    \n    for item in data.iterrows():\n        teams = item[1]['Home_Team_Visit_Team'].split('-')\n        poss_team = item[1]['Poss_Team']\n        for element in teams:\n            if poss_team != element:\n                opposition.append(element)\n    data['oppostion'] = opposition\n\n    return data\n\n\ndef draw_pitch(data, col1, col2, title, poss_team, oppostion):\n    #layout sourced from https://fcpython.com/visualisation/drawing-pitchmap-adding-lines-circles-matplotlib\n    #pitch is 53 yards by 100 yards excluding two 10 yard touchdown zones.\n    labels = ['Goal','10','20','30','40','50','40','30','20','10','Goal']\n    fig = plt.figure(facecolor='white', figsize=(12.5,5))\n    ax = fig.add_subplot(1,1,1)\n    ax.set_facecolor('green')\n    plt.yticks([]) # disable yticks\n    \n    start_x = -10\n    bottom_y = 0\n    top_y = 53\n    \n    ticks = [item * 10 for item in range(0,11)]\n    #(x1,x2) (y1,y2)\n    \n    plt.plot([-10, 110],[0, 0], color='white', linewidth=4)\n    plt.plot([-10, 110],[53, 53], color='white', linewidth=4)\n\n    \n    for item in range(0,28):\n        if item == 0:\n            plt.plot([start_x, start_x],[bottom_y, top_y], color='white', linewidth=4)\n        \n        if item >=1  and item <= 28:\n            if item % 2 == 1:\n                if item == 0 or item == 27:\n                    plt.plot([start_x, start_x],[bottom_y, top_y], color='white', linewidth=4)\n                    start_x = start_x + 5\n                else:\n                    plt.plot([start_x, start_x],[bottom_y, top_y], color='white', linestyle=\"dashed\")\n                    start_x = start_x + 5\n                \n            else:\n                if start_x >=0 and start_x < 110:\n                    plt.plot([start_x, start_x],[bottom_y, top_y], color='white', linewidth=4)\n                    start_x = start_x + 5 \n                    \n    y_value = []\n    for i in range(len(data)):\n        y_value.append(10 + i * 5)\n                    \n    for item in range(len(data)):\n        plt.scatter(data[col1][item], y_value[item], s=80, color=\"red\")\n        plt.scatter(data[col2][item], y_value[item], s=80, color=\"yellow\")\n        ax.text(data[col1][item], y_value[item], poss_team[item], ha='left', size=12.5, color='black')\n        ax.text(data[col2][item], y_value[item], oppostion[item], ha='left', size=12.5, color='black')\n\n    plt.xticks(ticks, labels, size=15)\n    plt.title(title, fontsize=20)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"176de5efb3bef5f66b2d8d3c7bc721d60ba3ad4c"},"cell_type":"code","source":"def plot_count_category(df, column):\n    x = df[column].value_counts().index\n    y = df[column].value_counts()\n    trace = go.Bar(\n        x=x,\n        y=y\n    )\n    data = [trace]\n    offline.iplot(data, config=config)\n    \ndef plot_punt_team(df, column, g1, g2):\n    trace1 = go.Bar(\n        x=df[df[\"punt_position_team\"]==g1][column].value_counts().index,\n        y=df[df[\"punt_position_team\"]==g1][column].value_counts(),\n        name=g1\n    )\n    trace2 = go.Bar(\n        x=df[df[\"punt_position_team\"]==g2][column].value_counts().index,\n        y=df[df[\"punt_position_team\"]==g2][column].value_counts(),\n        name=g2\n    )\n    data = [trace1, trace2]\n    layout = go.Layout(barmode='group')\n    fig = go.Figure(data=data, layout=layout)\n    offline.iplot(fig, config=config)\n    \ndef plot_punt_initial(df, column, g1, g2, g3):\n    trace1 = go.Bar(\n        x=df[df[\"punt_position_initial\"]==g1][column].value_counts().index,\n        y=df[df[\"punt_position_initial\"]==g1][column].value_counts(),\n        name=g1\n    )\n    trace2 = go.Bar(\n        x=df[df[\"punt_position_initial\"]==g2][column].value_counts().index,\n        y=df[df[\"punt_position_initial\"]==g2][column].value_counts(),\n        name=g2\n    )\n    trace3 = go.Bar(\n        x=df[df[\"punt_position_initial\"]==g3][column].value_counts().index,\n        y=df[df[\"punt_position_initial\"]==g3][column].value_counts(),\n        name=g3\n    )\n    data = [trace1, trace2, trace3]\n    layout = go.Layout(barmode='group')\n    fig = go.Figure(data=data, layout=layout)\n    offline.iplot(fig, config=config)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"a9bdef081d1af8abe19377041c47a4f7ed0ef64e"},"cell_type":"code","source":"# EDA of concussion plays\nvideo_review = pd.read_csv('../input/NFL-Punt-Analytics-Competition/video_review.csv')\ncols = [\"Primary_Impact_Type\", \"Primary_Partner_GSISID\", \"Primary_Partner_Activity_Derived\", \"Friendly_Fire\"]\nfor col in cols:  # change Unclear to NaN\n    if col == \"Primary_Partner_GSISID\":\n        video_review[col].iloc[33] = float(\"NaN\")\n    else:\n        video_review[col].iloc[33] = str(\"NaN\")\n# video_review.to_csv(\"../output/video_review.csv\", index=False)\nvideo_review[\"PAD_PIT\"] = [pad + \"_\" + pit.replace(\"Helmet-\", \"\") for pad, pit in zip(video_review[\"Player_Activity_Derived\"], video_review[\"Primary_Impact_Type\"])]\n# video_review.head(3)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d074c195f75ae5a6812540bbe81329aaf670c7e6"},"cell_type":"markdown","source":"**Which play type caused the injury most?**\n\nPlayers involved tackling face a bigger risk than others."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"1c91adb0fb6ac52df72c810516043d7c046beadc"},"cell_type":"code","source":"plot_count_category(video_review, 'Player_Activity_Derived')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d83f98373c931d836986956852cc49ef1eebe308"},"cell_type":"markdown","source":"**Which primary impact type caused the injury most?**\n\nHelmet-to-body contact is risky as well as helmet-to-helmet contact."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"0e828541fbbfed5e680c4f512e88c00d943927ad"},"cell_type":"code","source":"# Helmet-to-helmet and heltmet-to-body impacts result in the most coccussions\nplot_count_category(video_review, 'Primary_Impact_Type')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ede92377d815f752864811976dd4fa1ec88c65b7"},"cell_type":"markdown","source":"**Which the combination of play type and primary impact type caused the injury most?**\n\nTackling to body from helmet seems to be the most dangerous play."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"6378141c9e01d58ceb267808e1ba58d3843de352"},"cell_type":"code","source":"plot_count_category(video_review, 'PAD_PIT')","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"95f47059177262c54c048645233980eb1a2b1d88"},"cell_type":"code","source":"files = []\ngk_min = []\ngk_max = []\nfor file in sorted(os.listdir(\"../input/NFL-Punt-Analytics-Competition/\")):\n    if \"NGS\" in file: \n        files += [file]\n        gk = pd.read_csv('../input/NFL-Punt-Analytics-Competition/{}'.format(file)).GameKey\n        gk_min += [np.min(gk)]\n        gk_max += [np.max(gk)]\ndf_gamekey = pd.DataFrame({\"filename\": files, \"gamekey_min\": gk_min, \"gamekey_max\": gk_max}).sort_values(\"gamekey_min\")\n# df_gamekey.to_csv(\"../output/df_gamekey.csv\", index=False)\n\n# df_gamekey = pd.read_csv(\"../output/df_gamekey.csv\")\n# df_gamekey  # NGS-2017-reg-wk7-12.csv に 406 が混じってる","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b7895065f84b3fc932a8eae7248114cd20d5b0f5"},"cell_type":"markdown","source":"**This table shows some information of the video reviews with the video links**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"41827c62d1bb02c06acc41c65a7b1554cfbf0385"},"cell_type":"code","source":"layout = load_layout()\n# df_gamekey = pd.read_csv(\"../output/df_gamekey.csv\")\n\ndef watch_video():\n    role_data = pd.read_csv('../input/NFL-Punt-Analytics-Competition/play_player_role_data.csv')\n    \n    player_info = pd.read_csv('../input/NFL-Punt-Analytics-Competition/player_punt_data.csv')\n    grouped = player_info.groupby('GSISID').agg('count')\n    grouped_player_info = player_info.groupby('GSISID').agg({\n        'Number': lambda x: ','.join(x.replace(to_replace='[^0-9]', value='', regex=True).unique()), \n        'Position': lambda x: ','.join(x.unique())})\n    \n    video_review = pd.read_csv('../input/NFL-Punt-Analytics-Competition/video_review.csv', na_values='Unclear', dtype={'Primary_Partner_GSISID': np.float64}) \n    video_footage_injury = pd.read_csv('../input/NFL-Punt-Analytics-Competition/video_footage-injury.csv')\n\n    videos = pd.merge(video_review, video_footage_injury, left_on=['PlayID','GameKey'], right_on=['playid','gamekey'])\n    videos = pd.merge(videos, grouped_player_info, how='left', left_on='GSISID', right_on='GSISID')\n    videos = pd.merge(videos, role_data, how='left', on=[\"Season_Year\", \"GameKey\", \"PlayID\", \"GSISID\"])\n    videos.rename({'Number': 'Injured Player Number(s)', 'Position': 'Injured Player Position'}, axis=1, inplace=True)\n    videos = pd.merge(videos, grouped_player_info, how='left', left_on='Primary_Partner_GSISID', right_on='GSISID')\n    videos.rename({'Number': 'Other Player Number(s)', 'Position': 'Other Player Position'}, axis=1, inplace=True)\n    # Remove duplicate columns\n    # videos.drop(['gamekey', 'playid', 'season'], axis=1, inplace=True)\n\n    # Remove some columns that distract in manual viewing\n    watch = videos.drop(['GameKey', 'PlayID', 'GSISID', 'Season_Year', 'Primary_Partner_GSISID', 'Type', 'Week', 'Qtr', 'PlayDescription', 'Home_team', 'Visit_Team'], axis=1)\n    watch.rename({'Player_Activity_Derived': 'Injured Player Action', 'Primary_Partner_Activity_Derived': 'Other Player Action', 'Turnover_Related': 'From Turnover', 'Friendly_Fire': 'Friendly Fire'}, axis=1, inplace=True)\n    watch['PREVIEW LINK (5000K)'] = watch['PREVIEW LINK (5000K)'].apply(lambda x: '<a href=\"{0}\" target=\"__blank\">video link</a>'.format(x))\n    return watch\n\ndf_watch = watch_video()\npd.set_option('display.max_colwidth', -1)\nHTML(df_watch.to_html(escape=False))","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"5578d53609bec7686e1115a6b46267ebee0f8ad6"},"cell_type":"code","source":"punt_coverage_positions = [\"P\", \"PPR\",\"PPRi\", \"PPRo\", \"PPL\", \"PPLi\", \"PPLo\",\"PC\", \"PLW\",\"PRW\",\"GL\", \"GLi\",\n                           \"GLo\",  \"GR\",   \"GRi\",  \"GRo\",\"GR\",\"PLT\",\"PLG\",\"PLS\",\"PRG\",\"PRT\"]\npunt_return_positions = [\"PR\", \"PFB\", \"VL\", \"PDL1\", \"PDL2\", \"PDL3\", \"PDL4\", \"PDL5\", \"PDL6\",\n                         \"PDR1\", \"PDR2\", \"PDR3\", \"PDR4\", \"PDR5\", \"PDR6\",\"PLL\", \"PLL1\", \"PLL2\", \"PLL3\",\n                         \"PLR\",\"PLM1\", \"PLR1\", \"PLR2\", \"PLR3\",\"PLM\",\"VRi\",\"VRo\",\"VR\",\"VLi\", \"VLo\", \"PDM\"]\ndf_watch[\"punt_position_team\"] = [\"punt_coverage_positions\" if role in punt_coverage_positions \n                              else \"punt_return_positions\" if role in punt_return_positions\n                              else \"NaN\" for role in df_watch[\"Role\"]]\n\nfront_positions = [\"PLS\", \"PRG\", \"PRT\", \"PRW\", \"PLG\", \"PLT\", \"PLW\", \"PDR\", \"PDL\", \"PLR\", \"PLL\", \"PLM\"]\nback_positions = [\"P\", \"PPR\", \"PPL\", \"PC\", \"PR\", \"PFB\"]\nside_positions = [\"GL\", \"GR\", \"VL\", \"VRi\", \"VRo\"]\ndf_watch[\"punt_position_initial\"] = [\"front_positions\" if role in front_positions \n                                     else \"back_positions\" if role in back_positions\n                                     else \"side_positions\" if role in side_positions\n                                     else \"NaN\" for role in df_watch[\"Role\"]]\n\ndf_watch[\"action_position\"] = [action + \"_\" + position for action, position in zip(df_watch[\"Injured Player Action\"], df_watch[\"Injured Player Position\"])]\ndf_watch[\"action_role\"] = [action + \"_\" + role for action, role in zip(df_watch[\"Injured Player Action\"], df_watch[\"Role\"])]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a3bc59772199d1a006774df3823dddd5e1eab1b9"},"cell_type":"markdown","source":"**Count the number of the injured players by the role during punt plays**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"72346955ba0c1e5f65cdf3ea23cd2323375e2632"},"cell_type":"code","source":"plot_count_category(df_watch, \"Role\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"47afee2e5056b7c884a3753aa221a9384a9a3d29"},"cell_type":"markdown","source":"**Count the number of the injured players by the combination of the role and the play type during punt plays**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"e10cb34b6b929b8d730b0059769efcb3d6231e32"},"cell_type":"code","source":"plot_count_category(df_watch, \"action_role\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b24c3e4b86a94f73073b67b04428ba588c23bdb6"},"cell_type":"markdown","source":"**Count the number of the injured players by the punt coverage team and punt return team**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"781bdf6c1dcf6478d934d59f8e9c7ce7048bf55f"},"cell_type":"code","source":"plot_count_category(df_watch, \"punt_position_team\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9bdaba6ff0a36a8b6125865f8eb792a082da5eca"},"cell_type":"markdown","source":"**Count the number of the injured players by the initial position when punt plays started**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"1a9052d5a582f459163317d71e01adf1032804ad"},"cell_type":"code","source":"plot_count_category(df_watch, \"punt_position_initial\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6c1cdf298e9ef122ecab1de99b1ee42980637295"},"cell_type":"markdown","source":"**Count the number of the injured players by the combination of the role and the punt coverage/return team**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"86326788520d32c6a07380d397d50b52ae43a93d"},"cell_type":"code","source":"plot_punt_team(df_watch, \"Role\", \"punt_coverage_positions\", \"punt_return_positions\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"444fe4e8a0b3f7e4972b393a1dd4906f158e7a8e"},"cell_type":"markdown","source":"**Count the number of the injured players by the combination of the role and the initial position when punt plays started**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"609eed8946e70d61be71cbcb370fdc2aaec9d41d"},"cell_type":"code","source":"plot_punt_initial(df_watch, \"Role\", \"front_positions\", \"back_positions\", \"side_positions\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"53e0faade629cbbbc264f23176738fa93c846cc2"},"cell_type":"markdown","source":"#### **Watch Video Review**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"e914746e8e72e58fec986d1e2267819560ee7763"},"cell_type":"code","source":"def load_punt_data():\n    player_info = pd.read_csv('../input/NFL-Punt-Analytics-Competition/player_punt_data.csv')\n\n    grouped = player_info.groupby('GSISID').agg('count')\n    grouped_player_info = player_info.groupby('GSISID').agg({\n        'Number': lambda x: ','.join(x.replace(to_replace='[^0-9]', value='', regex=True).unique()), \n        'Position': lambda x: ','.join(x.unique())})\n    return grouped_player_info\n\ndef load_role_data():\n    return pd.read_csv('../input/NFL-Punt-Analytics-Competition/play_player_role_data.csv')\n\ndef load_plot(index, video=True):\n    i = index\n    # for i in range(len(video_review)):\n    gk = int(video_review[\"GameKey\"].iloc[i])\n    for j in range(len(df_gamekey)):\n        if gk <= int(df_gamekey[\"gamekey_max\"].iloc[j]):\n            filepath = df_gamekey.filename.iloc[j]\n            break\n    # Load the movements of players in GameKey 280. \n    df_game = load_game_and_ngs('../input/NFL-Punt-Analytics-Competition/{}'.format(filepath), GameKey=gk)\n    df_game = get_speed(df_game)\n    df_game = df_game.astype({\"GSISID\": int})\n    grouped_player_info = load_punt_data().reset_index()\n    role_data = load_role_data()\n    df_game = df_game.merge(grouped_player_info, how='left', on=\"GSISID\")\n    df_game = df_game.merge(role_data, how='left', on=[\"Season_Year\", \"GameKey\", \"PlayID\", \"GSISID\"])\n    del grouped_player_info, role_data\n\n    # Plot a single play, with two players\n    print(\"Injured GSISID: {}, Injured Player Number: #{}, Concerned Player Number: #{}, Play Type: {}, Primary Impact: {}\"\n          .format(video_review[\"GSISID\"].iloc[i],\n                  df_watch[\"Injured Player Number(s)\"].iloc[i],\n                  df_watch[\"Other Player Number(s)\"].iloc[i],\n                  video_review[\"Player_Activity_Derived\"].iloc[i], \n                  video_review[\"Primary_Impact_Type\"].iloc[i]))\n#     print(\"{} {}\".format(df_game[\"Speed\"].iloc[i]))\n    \n    plot_play(game_df=df_game, \n              PlayID=int(video_review[\"PlayID\"].iloc[i]), \n              player1=int(video_review[\"GSISID\"].iloc[i]), \n              player2=float(video_review[\"Primary_Partner_GSISID\"].iloc[i]))\n\n    if video == False:\n        return reduce_mem_usage(df_game, verbose=False)\n\n    # Check video\n    if video == True:\n        preview_link = df_watch[\"PREVIEW LINK (5000K)\"].iloc[i]\n        pl_start = preview_link.find('http')\n        pl_end = preview_link.find('mp4') + 3\n\n        video_url = preview_link[pl_start:pl_end]\n        return HTML('<video width=\"560\" height=\"315\" controls> <source src=\"{}\" type=\"video/mp4\"></video>'.format(video_url))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c6d2a4b278a79b4035aa65de226ea36c1be79e50"},"cell_type":"markdown","source":"**Some examples of the traces of the injured player and the concerned player**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"ae9c96a5a597ac245f5877658e9f8ceca7320b36"},"cell_type":"code","source":"for i in range(3):\n    load_plot(i)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2e8f4bfd488d9841da3765625a647e2c894866b8"},"cell_type":"markdown","source":"#### **Video Review in Detail**"},{"metadata":{"_uuid":"6fd76dbf0c84331146a75344ca38d276a0917702"},"cell_type":"markdown","source":"**From the trace graghs shown in the previous slide and the video reviews provided, \nI made up a table containing some new information, including whether tackles/blocks are made “correctly”.**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"9968c9eddc10f2a2bb0d796fcc874282b811e31f"},"cell_type":"code","source":"video_review_detail = pd.read_csv(\"../input/kaggle-nfl-tak/kaggle-nfl-video-review.csv\", header=1, nrows=37)\nvideo_review_detail","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"645652e24f9613c512a81523c822cb4e7730cb11"},"cell_type":"markdown","source":"**This Graph shows whether injure players tackled/blocked in a correct way or not.\nIncorrect tacklings/blockings are more than correct tacklings/blockings.\n(Incorrect are 64.29%(18/28) )**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"ab0c67a1441256b681a8f8ee4318e6dde3379b29"},"cell_type":"code","source":"plot_count_category(video_review_detail, \"Tackle Correct?\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2bed4c7cb309f856f80dfde5c51d0d0832da6379"},"cell_type":"markdown","source":"**This graph shows the combination of the play type of injure players and whether the players tackled/blocked in a correct way or not.\nThere are no significant differences between incorrect tackles and incorrect blocks, though correct tacklings are most.**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"7f56be24764224b48bf6c944245f63ac25644b58"},"cell_type":"code","source":"video_review_detail[\"pt_tc\"] = [pt + \"_\" + tc for pt, tc in zip(\n                                video_review_detail[\"Play Type\"].fillna(\"NaN\"), \n                                video_review_detail[\"Tackle Correct?\"].fillna(\"NaN\"))]\n\nplot_count_category(video_review_detail, \"pt_tc\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ad7a69013e9aa26301314c66e92f7bdd6378d589"},"cell_type":"markdown","source":"### ------------------------------"},{"metadata":{"_uuid":"f440a6ad637a46d91e9472fdff9a7cf968238b6f"},"cell_type":"markdown","source":"## Conclusions\n\nTo solve these problems, the following ways will be effective:\n\n- **To Prevent a player from lowering the heads to initiate contact with the helmet, give a constraint of tackling/blocking techniques**\n\nSo, the rule to be changed should be like this:\n\n- **Players who does not tackle/block “correctly” will receive a warning, and the team may get 5, 10, or 15 yards penalty when they receive it repeatedly.**\n\n### Discussion\n\n**Pro.**\n- Although there are still room to investigate more pricisely, the idea and the validation are somewhat useful to improve the circumstance around the safety of the players.\n\n**Con.**\n- To demonstrate clearly, I should have examined the statistical test to validate the relationship of tackler's head position and the injury. (however I'm sorry that I do not have much time to do so in this time)\n"},{"metadata":{"trusted":true,"_uuid":"92d5a358da0a8017f89f07f3c9efd34756612572"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}