{"cells":[{"metadata":{"_uuid":"5f472d908dbf1d542f7513f092650b206cb1aae8"},"cell_type":"markdown","source":"**Outline**\n\n* [Recommendations to the NFL](#Recommendations to the NFL)\n* [Data Set-Up and Exploration](#Data Set-Up and Exploration)\n* [Dangerous Blocks](#Dangerous Blocks)\n    * [Recommendation 1: Peel Back Blocking](#Recommendation 1: Peel Back Blocking)\n* [Use of Helmet](# Use of Helmet)\n    * [Recommendation 2: Emphasize the Use of Helmet Rule on Punt Plays](#Recommendation 2: Emphasize the Use of Helmet Rule on Punt Plays)\n* [Decreasing Return and Tackle Probability](#Decreasing Return and Tackle Probability)\n    * [Recommendation 3: Return Team Formation Restrictions](#Recommendation 3: Return Team Formation Restrictions)\n* [Conclusion](#Conclusion)"},{"metadata":{"_uuid":"a4b789ea466a2114fe4ac67b19c9f289ef2a00b5"},"cell_type":"markdown","source":"### Recommendations to the NFL\nBelow, we outline the three recommendations we have for the NFL in order to reduce the number of concussions on punt plays and make them generally safer.\n\n- **Recommendation 1: Peel Back Blocking**\n\nWe recommend the following changes to the definition of a peel back block:\n\n*Rule 12.2.4 An offensive player cannot initiate contact on the side and below the waist **or to the head/neck area** against an opponent if:*\n- *the blocker is moving toward **or parallel to** his own end line; and*\n- *he approaches the opponent from behind or from the side.*\n\n- **Recommendation 2: Use of Helmet**\n\nWe recommend that the league re-emphasize and apply the Use of Helmet rule more strictly on punt plays.\n\n- **Recommendation 3: Return Team Formation Restrictions:**\n\nWe recommend the league prevent return teams from double covering the gunner.\n\nWhen considering rule changes, the NFL considers the [following criteria](#https://operations.nfl.com/the-rules/2018-rules-changes-and-points-of-emphasis/):\n\n- Does the change improve the game?\n- How will it be officiated?\n- How will it be coached?\n- How can the player play by the rule? \n\nWe believe that these criteria can be readily met by all three recommendations.  Our first two recommendations are slight modifications to the application of existing rules.  Our third recommendation applies to a formation change which improves the game by decreasing return plays.  It can be officiated by the field judge whose responsibility is already to count the number of defensive players.  And players and coaches can abide by the rule by only aligning in the proper formations.  Moreover, the spirit of this suggested rule is similar to the prohibiting blocking within the first 15 yards during a kickoff.\n"},{"metadata":{"_uuid":"bbe82d156f69089372a9501dd592c6df25e21637"},"cell_type":"markdown","source":"### Data Set-Up and Exploration"},{"metadata":{"trusted":true,"_uuid":"12c8a00531f9adb840ec54c87c60cd8a40b6c60b","_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"library(tidyverse)\nlibrary(data.table)\nlibrary(ggplot2)\nlibrary(magick)\noptions(stringsAsFactors = FALSE)\n#list.files(path = \"../input/test-png\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9144a93aab01d5d2ba40a9f3f2367597e9beced2"},"cell_type":"markdown","source":"#### Pre-process Game and Video Data\n- play_info \n     - Add column *pos*: how far the kicking team is in their own territory\n     - Add column *receive_win*: indicates whether the receiving team is winning, losing or tied at the time of the punt\n     - Note: doesn't contain information about down and distance to first down\n     \n     \n - player_punt\n     - Join multiple numbers of same GSISID into comma separated column"},{"metadata":{"trusted":true,"_uuid":"cb88a1320ea021ac1327e96dd612ac907a22e770","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"play_info <- read.csv('../input/NFL-Punt-Analytics-Competition/play_information.csv', header=TRUE)\n\n# Calculate field position of punting team\nplay_info$YardLine <- as.character(play_info$YardLine)\ntemp_YardLine <- strsplit(play_info$YardLine, \"[[:space:]]\")\nplay_info$pos <- ifelse(sapply(temp_YardLine, \"[[\", 1) == play_info$Poss_Team,\n                           as.numeric(sapply(temp_YardLine, \"[[\", 2)),\n                           100 - as.numeric(sapply(temp_YardLine, \"[[\", 2)))\n\n# Make column denoting receiving team as winning, losing or tied\nplay_info$Home_Team_Visit_Team <- as.character(play_info$Home_Team_Visit_Team)\nHomeTeam <- sapply(strsplit(play_info$Home_Team_Visit_Team, \"-\"), \"[[\", 1)\nplay_info$Score_Home_Visiting <- as.character(play_info$Score_Home_Visiting)\ntemp_Score_Home_Visiting <- strsplit(play_info$Score_Home_Visiting, \"[ - ]\")\nhome_score <- as.numeric(sapply(temp_Score_Home_Visiting, \"[[\", 1))\naway_score <- as.numeric(sapply(temp_Score_Home_Visiting, \"[[\", 3))\nplay_info$receive_win <- ifelse(home_score == away_score, \"Tie \", \n                             ifelse(xor(play_info$Poss_Team == HomeTeam, home_score > away_score),\n                                    \"Win\", \"Lose\"))\n\nplay_player_role <- read.csv('../input/NFL-Punt-Analytics-Competition/play_player_role_data.csv', header=TRUE) %>%\n  rename(Season=\"Season_Year\")\nplayer_punt <- read.csv('../input/NFL-Punt-Analytics-Competition/player_punt_data.csv', header=TRUE)\n\n# Join multiple numbers of same GSISID into comma separated column\nplayer_punt <- as.data.table(player_punt)[, toString(Number), by = list(GSISID, Position)]\nnames(player_punt) <- c(\"GSISID\", \"Position\", \"Number\")\n\nvideo_footage_injury <- read.csv('../input/NFL-Punt-Analytics-Competition/video_footage-injury.csv', header=TRUE) %>%\n  rename(GameKey=gamekey, PlayID=playid, Season=season)\nvideo_review <- read.csv('../input/NFL-Punt-Analytics-Competition/video_review.csv', header=TRUE) %>%\n  rename(Season=Season_Year) %>%\n  arrange(GameKey, PlayID)\n\npreprocess_ngs <- function(ngs){\n  ngs <- ngs %>% \n    mutate(Time = as.numeric(as.POSIXct(Time)))\n    \n  snaps <- ngs %>%\n    filter(Event == \"ball_snap\") %>%\n    select(Season_Year, GameKey, PlayID, Time) %>%\n    group_by(Season_Year, GameKey, PlayID) %>%\n    filter(row_number() == 1) \n  \n  last_event <- ngs %>%\n    select(Season_Year, GameKey, PlayID, Time, Event) %>%\n    distinct() %>% \n    filter(Event != \"\") %>%\n    group_by(Season_Year, GameKey, PlayID) %>% \n    arrange(Time) %>%\n    filter(row_number()==n()-1) %>%\n    select(Season_Year, GameKey, PlayID, Time)\n  \n  ngs <- ngs %>%\n    left_join(snaps, by=c(\"Season_Year\", \"GameKey\", \"PlayID\")) %>%\n    filter(Time.x >= Time.y) %>%\n    select(-Time.y) %>%\n    rename(Time=Time.x) %>%\n    left_join(last_event, by=c(\"Season_Year\", \"GameKey\", \"PlayID\")) %>%\n    filter(Time.x <= Time.y) %>%\n    select(-Time.y) %>%\n    rename(Time=Time.x) %>%\n    group_by(Season_Year, GameKey, PlayID, GSISID) %>%\n    arrange(Time) %>%\n    ungroup()\n  \n  return(ngs)\n}\n\nngs_all <- bind_rows(preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2016-pre.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2016-reg-wk1-6.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2016-reg-wk7-12.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2016-reg-wk13-17.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2016-post.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2017-pre.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2017-reg-wk1-6.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2017-reg-wk7-12.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2017-reg-wk13-17.csv', header=TRUE)),\n                    preprocess_ngs(read.csv('../input/NFL-Punt-Analytics-Competition/NGS-2017-post.csv', header=TRUE)))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fd12807b0dc73a6108861fb8500168a22512d5c4"},"cell_type":"markdown","source":"#### Outlier (punter sneak)\n\nWe will remove the punter sneak (GameKey == 274, PlayID == 3609) as an outlier.  It doesn't apply to our analysis of punt coverages."},{"metadata":{"trusted":true,"_uuid":"ac2df0a00c0d42afe66749be827144b3a5765606","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"video_footage_injury <- video_footage_injury[!(video_footage_injury$GameKey == 274 & video_footage_injury$PlayID == 3609),]\nvideo_review <- video_review[!(video_review$GameKey == 274 & video_review$PlayID == 3609),]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5b627961391acba5e295c16f68c48135bb09d253"},"cell_type":"markdown","source":"#### Amending the data\nChange video data based on watching videos, examining NGS data\n - Change entry GameKey == 506, PlayID == 1988 into helmet-to-helmet with player 31209"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"a40e4c02ec6946a1f82e33afad1898b8b2443136"},"cell_type":"code","source":"video_review$Primary_Partner_GSISID[video_review$GameKey == 506 & video_review$PlayID == 1988] <- 31209\n\np2017_506_1988_1 <- image_read(\"../input/test-png/2017_506_1988_1.png\")\np2017_506_1988_2 <- image_read(\"../input/test-png/2017_506_1988_2.png\")\np2017_506_1988_3 <- image_read(\"../input/test-png/2017_506_1988_3.png\")\nimg <- c(p2017_506_1988_1, p2017_506_1988_2, p2017_506_1988_3)\nimg <- image_scale(img, \"600x600\")\nimage_animate(image_scale(img, \"600x600\"), fps = 0.8, dispose = \"previous\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a2d2aaf9ffb36ff6416d4053d9358e5da9672f1a"},"cell_type":"markdown","source":"\n - Change entry GameKey == 218, PlayID == 3468 into collision with player 29744 \n (video does not show collision, but proximity in NGS data indicates contact was made)"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"3c5fa16fe8f9f8e4df2ccf32ea78bf26c96cf447"},"cell_type":"code","source":"video_review$Primary_Partner_GSISID[video_review$GameKey == 218 & video_review$PlayID == 3468] <- 29744\nvideo_review$Primary_Partner_Activity_Derived[video_review$GameKey == 218 & video_review$PlayID == 3468] <- \"Blocking\"\nvideo_review$Friendly_Fire[video_review$GameKey == 218 & video_review$PlayID == 3468] <- \"No\"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"279f9f32e3adbe2b12529ff8f2b9be2a9b3a7814"},"cell_type":"markdown","source":" - Change entry GameKey == 54, PlayID == 1045 into helmet-to-helmet with player 31867"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"b0cfdd87f26fc037db2fc3a230c0ac8fc1d4f511"},"cell_type":"code","source":"video_review$Primary_Impact_Type[video_review$GameKey == 54 & video_review$PlayID == 1045] <- \"Helmet-to-helmet\"\nvideo_review$Primary_Partner_GSISID[video_review$GameKey == 54 & video_review$PlayID == 1045] <- 31867\nvideo_review$Primary_Partner_Activity_Derived[video_review$GameKey == 54 & video_review$PlayID == 1045] <- \"Blocking\"\nvideo_review$Friendly_Fire[video_review$GameKey == 54 & video_review$PlayID == 1045] <- \"No\"\n\np2016_54_1045_1 <- image_read(\"../input/test-png/2016_54_1045_1.png\")\np2016_54_1045_2 <- image_read(\"../input/test-png/2016_54_1045_2.png\")\np2016_54_1045_3 <- image_read(\"../input/test-png/2016_54_1045_3.png\")\np2016_54_1045_4 <- image_read(\"../input/test-png/2016_54_1045_4.png\")\nimg <- c(p2016_54_1045_1, p2016_54_1045_2, p2016_54_1045_3, p2016_54_1045_4)\nimg <- image_scale(img, \"600x600\")\nimage_animate(image_scale(img, \"600x600\"), fps = 0.8, dispose = \"previous\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"127d7fc647fd4677409f4bbf57835a7d2167c6f6"},"cell_type":"markdown","source":" - Change entry GameKey == 585, PlayID == 733 into helmet-to-helmet with player 33954"},{"metadata":{"trusted":true,"_uuid":"434d8f1dfca240ce022574ad0444ec5800c1b772","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"video_review$Primary_Impact_Type[video_review$GameKey == 585 & video_review$PlayID == 733] <- \"Helmet-to-helmet\"\nvideo_review$Primary_Partner_GSISID[video_review$GameKey == 585 & video_review$PlayID == 733] <- 33954\nvideo_review$Primary_Partner_Activity_Derived[video_review$GameKey == 585 & video_review$PlayID == 733] <- \"Blocking\"\nvideo_review$Friendly_Fire[video_review$GameKey == 585 & video_review$PlayID == 733] <- \"No\"\n\nvideo_review$Primary_Partner_GSISID <- as.numeric(video_review$Primary_Partner_GSISID)\n\np2017_585_733_1 <- image_read(\"../input/test-png/2017_585_733_1.png\")\np2017_585_733_2 <- image_read(\"../input/test-png/2017_585_733_2.png\")\np2017_585_733_3 <- image_read(\"../input/test-png/2017_585_733_3.png\")\nimg <- c(p2017_585_733_1, p2017_585_733_2, p2017_585_733_3)\nimg <- image_scale(img, \"600x600\")\nimage_animate(image_scale(img, \"600x600\"), fps = 0.8, dispose = \"previous\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c71f806adc30303adcc5061364c83d7fd3012bd6"},"cell_type":"markdown","source":"#### Classifying concussion plays\n\nAdd high level classifications for the concussion plays based on watching videos:\n - PR-return - player concussed is either the PR or tackler of PR when PR is running with the ball\n - Upfield - collision when punt team chasing upfield and blocker coming downfield, crackback/pull-back/blindside block\n - FF-TwoDirections - friendly fire, tackling PR from two directions\n - Run into on way down - concussed while running downfield and players moving in same direction\n - PR-catch - player concussed is either the PR or tackler when PR is in the process of catching the ball\n - Block collision - stationary block collides with moving block\n - Line - collision at the line of scrimmage\n - Slip - player slips and hits head\n \n Note: Video for (GameKey == 281, PlayID == 1526) does not match the annotations or NGS data.  We rely on the NGS data and annotations to classify it as run into on the way down"},{"metadata":{"trusted":true,"_uuid":"225454a83921903d8fec40c04bd95576d2b48f33","_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"video_review$Class[c(1,4,9,15,19,24,25,29,33,34,36)] <- \"PR-return\"\nvideo_review$Class[c(5,11,20,21,23,27,30,31,32)] <- \"Upfield\"\nvideo_review$Class[c(16,18,22,28)] <- \"FF-TwoDirections\"\nvideo_review$Class[c(2,6,7,10)] <- \"Run into on way down\"\nvideo_review$Class[c(3,12,13)] <- \"PR-catch\"\nvideo_review$Class[c(8,17)] <- \"BlockCollision\"\nvideo_review$Class[c(14,35)] <- \"Line\"\nvideo_review$Class[c(26)] <- \"Slip\"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b2c24f0442db12baa34f1f4f4a463fa290eedb9e"},"cell_type":"markdown","source":"### Examining the classifications/labels\nFirst, we examine the distribution of the classifications.  We can see that the largest categories occur when tackling the punt returner after the catch (31%) and when a player is turning or moving upfield and a blocker blocks him (25%)"},{"metadata":{"trusted":true,"_uuid":"6d117eaacc41162e25b00c9440d835a4d95eb1ed","_kg_hide-input":true},"cell_type":"code","source":"perc <- video_review %>% \n  group_by(Class) %>% \n  count() %>% \n  ungroup() %>% \n  mutate(per=`n`/sum(`n`)) %>% \n  arrange(desc(Class))\n\nperc$label <- scales::percent(perc$per)\n\nggplot(data=perc)+\n  geom_bar(aes(x=\"\", y=per, fill=Class), stat=\"identity\", width = 1)+\n  coord_polar(\"y\", start=0)+\n  theme_void()+\n  geom_text(aes(x=1, y = cumsum(per) - per/2, label=label))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"79b04107b00a7f2eafbca2beab3df98d42c78067"},"cell_type":"markdown","source":"### Dangerous blocks\n\n#### Illegal blocks\nAs we saw above, 9 of the 36 (25%) concussion plays result from plays where a blocker is running with high speed in the opposite direction of, or perpendicular to, the punt returner and makes contact with an opponent.  By amending some existing restrictions on blocking, we believe that many of these plays can be eliminated.  In the [2018 NFL rule book](https://operations.nfl.com/the-rules/2018-nfl-rulebook/), the following types of blocks are currently prohibited:\n\n*Rule 12.1.1 A player of either team may block (obstruct or impede) an opponent at any time, provided that the act is not:*\n- *an illegal crackback block;*\n- *an illegal block in the back above the waist*\n- *illegal peel back block; *\n- *illegal blindside block*\n\nAn illegal peel back block is defined as follows in the [2018 NFL rule book](https://operations.nfl.com/the-rules/2018-nfl-rulebook/) (see also NFL rules video [here](https://operations.nfl.com/the-rules/nfl-video-rulebook/illegal-peel-back-block/)): \n\n*Rule 12.2.4 An offensive player cannot initiate contact on the side and below the waist against an opponent if:*\n- *the blocker is moving toward his own end line; and*\n- *he approaches the opponent from behind or from the side.*\n*Note: If the near shoulder of the blocker contacts the front of his opponent’s body, the “peel back” block is legal.*\n\nWe also have the following restrictions on blocking a defenseless player. \n\n*Rule 12.2.7 It is a foul if a player initiates unnecessary contact against a player who is in a defenseless posture.*\n- *Players in a defenseless posture are: A player who receives a “blindside” block when the path of the blocker is toward or parallel to his own end line.*\n\n#### Recommendation 1: Update Peel Back Blocking\n\nWe believe that expanding the wording of peel back block restrictions to mimic the defenseless player rule to the following:\n\n*Rule 12.2.4 An offensive player cannot initiate contact on the side and below the waist **or to the head/neck area** against an opponent if:*\n- *the blocker is moving toward **or parallel to** his own end line; and*\n- *he approaches the opponent from behind or from the side.*\n\ncan help to mitigate these types of plays.  Under this new wording, 6 out of the 9 concussion plays involving contact of a blocker running opposite the returner would fall into this category, namely:"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"4af16e9ccf6a9d18a3a1d5290782e174e5128516"},"cell_type":"code","source":"tribble(\n    ~Season, ~GameKey, ~PlayID,\n    2016, 54, 1045,\n    2017, 364, 2489,\n    2017, 364, 2764,\n    2017, 392, 1088, \n    2017, 553, 1683,\n    2017, 585, 733)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5082cf198d163295489c93db09a6a643828fff84"},"cell_type":"markdown","source":"The animation below shows an instance where a penalty was not called, but would be called under this rule"},{"metadata":{"trusted":true,"_uuid":"a9e8ec3eea0c32834510961564a673fa10c2662f"},"cell_type":"code","source":"img <- c(p2017_585_733_1, p2017_585_733_2, p2017_585_733_3)\nimg <- image_scale(img, \"600x600\")\nimage_animate(image_scale(img, \"600x600\"), fps = 0.8, dispose = \"previous\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fd1bf36418b21de440de0abf62ea82d766f5e25f"},"cell_type":"markdown","source":"Unfortunately, this new amendment would not apply to the play below.  We can see that the blocker legally initiates contact with the shoulder into the chest of the opponent, and the concussion results from the player's head hitting a teammate behind them.  This is, in our opinion, within the scope of a legal football play and should not be addressed via a rule change.  Rather, we attempt to minimize these types of plays through other means."},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true,"_uuid":"82ec7538f412f42895eb46b8f35e63edd33f3899"},"cell_type":"code","source":"p2016_231_1976_1 <- image_read(\"../input/test-png/2016_231_1976_1.png\")\np2016_231_1976_2 <- image_read(\"../input/test-png/2016_231_1976_2.png\")\np2016_231_1976_3 <- image_read(\"../input/test-png/2016_231_1976_3.png\")\nimg <- c(p2016_231_1976_1, p2016_231_1976_2, p2016_231_1976_3)\nimg <- image_scale(img, \"600x600\")\nimage_animate(image_scale(img, \"600x600\"), fps = 0.8, dispose = \"previous\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"727524f4c94f5b8a0adb05a4a1b8384712c2e4ad"},"cell_type":"markdown","source":"#### Helmet-Led Contact plays\nThe use Use of Helmet rule was created in 2018 to help address concussions caused by helmet-led contact.  It is stated as follows:\n\n*12.2.8 USE OF THE HELMET. It is a foul if a player lowers his head to initiate and make contact with his helmet against an opponent.*\n\nWe hand-label the following concussion plays where Use of Helmet Rule would apply "},{"metadata":{"trusted":true,"_uuid":"80fb157538963423a2544f71066775edfedfcead","_kg_hide-input":false},"cell_type":"code","source":"video_review$UOH <- FALSE\nvideo_review$UOH[c(1,3,11,12,14,17,18,29,31,33)] <- TRUE","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ecc787b6b1ef6a1f7ef3eb1f33398414e14aea9b"},"cell_type":"markdown","source":"We see that the Use of Helmet rule would apply to 10 out of the 36 (28%) of the concussion plays.  Moreover, all the concussion plays where the returner is in the process of catching the ball fall under the category of a Use of Helmet violation."},{"metadata":{"trusted":true,"_uuid":"15520e35a2a626ace5f8b925b978868eefb94c8f","_kg_hide-input":true},"cell_type":"code","source":"perc <- video_review %>%\n  filter(UOH != TRUE) %>%\n  group_by(Class) %>% \n  count() %>% \n  ungroup() %>% \n  mutate(per=`n`/sum(`n`)) %>% \n  arrange(desc(Class))\n\nperc$label <- scales::percent(perc$per)\n\nggplot(data=perc)+\n  geom_bar(aes(x=\"\", y=per, fill=Class), stat=\"identity\", width = 1)+\n  coord_polar(\"y\", start=0)+\n  theme_void()+\n  geom_text(aes(x=1, y = cumsum(per) - per/2, label=label))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"bfc1d0136dab1bcb9e8197fcd7aef547b3bc8d67"},"cell_type":"markdown","source":"#### Recommendation 2: Emphasize the Use of Helmet Rule on Punt Plays\nFrom above, we can see that it is paramount to deter players from using their helmets when making a tackle or block, especially when high-speed punt plays are involved as they account for almost a third of the concussion plays.  We believe that re-remphasizing the Use of Helmet Rule particularly on punt plays will help protect both players involved in any collisions."},{"metadata":{"_uuid":"d94e479b09e63441557371eda37447eeda1feafd"},"cell_type":"markdown","source":"### Decreasing Return and Tackle Probability\n\nIn this section, we show how we can decrease the return probability (and subsequently concussions) by restricting the formations on both sides of the ball.\n\nWe setup our analysis via the following steps\n1. We first extract the formations for each play looking at the players on the field when Event == ball_snap in the NGS data.  Then, for each play, we count the number of player roles that fall into the categories: receiving lineman, linebacker, V, PFB, PR, punting lineman, G, PC, PP, P.\n2. Construct datatable *ngs_return* which contains all plays which resulted in a fair_catch, touchback, downed punt, received punt, or fumble.\n3. Join role count and game/play details to concussion samples datatable *video_review*"},{"metadata":{"trusted":true,"_uuid":"d0345bbd08f46896cf7083579b9ba819c91e0a02","_kg_hide-output":true,"_kg_hide-input":true},"cell_type":"code","source":"## Step 1\nreceive_line <- c(\"PDL1\", \"PDL2\", \"PDL3\", \"PDL4\", \"PDL5\", \"PDL6\", \"PDM\", \"PDR1\", \"PDR2\", \"PDR3\", \"PDR4\", \"PDR5\", \"PDR6\")\nreceive_lb <- c(\"PLL\", \"PLL1\", \"PLL2\", \"PLL3\", \"PLM\", \"PLM1\", \"PLR\", \"PLR1\", \"PLR2\", \"PLR3\")\nreceive_v <- c(\"VL\", \"VLi\", \"VLo\", \"VR\", \"VRi\", \"VRo\")\nreceive_pfb <- c(\"PFB\")\nreceive_pr <- c(\"PR\")\npunt_line <- c(\"PLG\", \"PLS\", \"PLT\", \"PLW\", \"PRG\", \"PRT\", \"PRW\")\npunt_g <- c(\"GL\", \"GLi\", \"GLo\", \"GR\", \"GRi\", \"GRo\")\npunt_pc <- c(\"PC\")\npunt_pp <- c(\"PPL\", \"PPLi\", \"PPLo\", \"PPR\", \"PPRi\", \"PPRo\")\npunt_p <- c(\"P\")\n\nrole_count <- ngs_all %>% \n  filter(Event == \"ball_snap\") %>%\n  left_join(play_player_role, by=c(\"Season_Year\"=\"Season\", \"GameKey\",\"PlayID\", \"GSISID\")) %>%\n  mutate(rec_line = (Role %in% receive_line), lb = (Role %in% receive_lb),\n         v = (Role %in% receive_v), pfb = (Role %in% receive_pfb),\n         pr = (Role %in% receive_pr), punt_line = (Role %in% punt_line),\n         g = (Role %in% punt_g), pc = (Role %in% punt_pc),\n         pp = (Role %in% punt_pp), p = (Role %in% punt_p)) %>%\n  group_by(Season_Year, GameKey, PlayID) %>%\n  summarise(rec_line=sum(rec_line == TRUE), lb = sum(lb == TRUE), v = sum(v == TRUE), \n            pfb = sum(pfb == TRUE), pr = sum(pr == TRUE), punt_line = sum(punt_line == TRUE),\n            g = sum(g == TRUE), pc = sum(pc == TRUE), \n            pp = sum(pp == TRUE), p = sum(p == TRUE))\n\n## Step 2\nngs_return <- ngs_all %>%\n  select(Season_Year, GameKey, PlayID, Time, Event) %>%\n  filter(Event %in% c(\"fair_catch\", \"touchback\", \"punt_downed\", \"punt_received\", \"fumble\")) %>%\n  group_by(Season_Year, GameKey, PlayID) %>%\n  arrange(Time) %>%\n  filter(row_number() == 1) \n\n## Step 3\nvideo_review <- video_review %>%\n  left_join(role_count, by=c(\"Season\"=\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  left_join(video_footage_injury, by=c(\"Season\", \"GameKey\",\"PlayID\")) %>%\n  left_join(play_info, by=c(\"Season\"=\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  left_join(ngs_return, by=c(\"Season\"=\"Season_Year\", \"GameKey\",\"PlayID\"))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"183130602bc0c7e7e21b91b5198346c68544da42"},"cell_type":"markdown","source":"#### Relationship between verts and return and return rate\n\nWe now look at the relationship between the number of verts (players aligned in front of the gunners) and the rate that a punt is fielded.  We can see in the first table that having only 2 gunners decreases the probability that a punt is returned, even when controlling for field position.  The second table gives us a count for each of the elements in the first table.\n"},{"metadata":{"trusted":true,"_uuid":"c57c57dd90ca09f90e32e4ffe6c6f48ff293fd44","_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"event <- \"punt_received\"\nreturn_prob <- play_info %>%\n  left_join(ngs_return, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  left_join(role_count, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  filter(!is.na(Event), g == 2) %>% # , receive_win == \"Lose\", Quarter %in% c(3,4)\n  group_by(v) %>% # rec_line, lb, v, pfb, pr\n  summarise(total = n(),\n            field_prob = sum(Event == event) / n(),\n            r00_09 = sum(between(pos, 0, 9) & Event == event) / sum(between(pos, 0, 9)), \n            r10_19 = sum(between(pos, 10, 19) & Event == event) / sum(between(pos, 10, 19)),\n            r20_29 = sum(between(pos, 20, 29) & Event == event) / sum(between(pos, 20, 29)), \n            r30_39 = sum(between(pos, 30, 39) & Event == event) / sum(between(pos, 30, 39)),\n            r40_49 = sum(between(pos, 40, 49) & Event == event) / sum(between(pos, 40, 49)), \n            r50_59 = sum(between(pos, 50, 59) & Event == event) / sum(between(pos, 50, 59)),\n            r60_69 = sum(between(pos, 60, 69) & Event == event) / sum(between(pos, 60, 69)),\n            r00_09_count = sum(between(pos, 0, 9)), \n            r10_19_count = sum(between(pos, 10, 19)),\n            r20_29_count = sum(between(pos, 20, 29)), \n            r30_39_count = sum(between(pos, 30, 39)),\n            r40_49_count = sum(between(pos, 40, 49)), \n            r50_59_count = sum(between(pos, 50, 59)),\n            r60_69_count = sum(between(pos, 60, 69))) %>%\n  ungroup() %>%\n  filter(total / sum(total) > 0.02) %>%\n  arrange(-total)\n(r_prob <- return_prob %>%\n  select(v, field_prob, r00_09, r10_19, r20_29, r30_39, r40_49))\n(r_count <- return_prob %>%\n  select(v, total, r00_09_count, r10_19_count, r20_29_count, r30_39_count, r40_49_count))\nreturn_prob_after <- sum(r_prob[1, 3:7] * colSums(r_count)[3:7]) / sum(colSums(r_count)[3:7])\nreturn_prob_before <- sum(r_prob$field_prob[] * r_count$total) / sum(colSums(r_count)[3:7])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cdba690179c5b9d798e74d96b4b55670b1520e35"},"cell_type":"markdown","source":"In the first table below, we calculate the p-values for the 3-sample Chi-squared test for each column above.  With the p-value for each column being quite small ( < 0.05), this indicates that there is a statistically significant difference in the rate of returns in relation to the number of verts.\n\nIn the second table, we calculate the p-values for a linear relationship between the number of verts and return probability.  We see that there is still a statistically significant linear relationship between the two."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"4707507a7f25cae51363e382df32b64173c47946"},"cell_type":"code","source":"# Conduct proportions tests\np <- prop.test(return_prob$field_prob * return_prob$total, return_prob$total)\npl <- prop.trend.test(return_prob$field_prob * return_prob$total, return_prob$total)\np00_09 <- prop.test(return_prob$r00_09 * return_prob$r00_09_count, return_prob$r00_09_count)\npl00_09 <- prop.trend.test(return_prob$r00_09 * return_prob$r00_09_count, return_prob$r00_09_count)\np10_19 <- prop.test(return_prob$r10_19 * return_prob$r10_19_count, return_prob$r10_19_count)\npl10_19 <- prop.trend.test(return_prob$r10_19 * return_prob$r10_19_count, return_prob$r10_19_count)\np20_29 <- prop.test(return_prob$r20_29 * return_prob$r20_29_count, return_prob$r20_29_count)\npl20_29 <- prop.trend.test(return_prob$r20_29 * return_prob$r20_29_count, return_prob$r20_29_count)\np30_39 <- prop.test(return_prob$r30_39 * return_prob$r30_39_count, return_prob$r30_39_count)\npl30_39 <- prop.trend.test(return_prob$r30_39 * return_prob$r30_39_count, return_prob$r30_39_count)\np40_49 <- prop.test(return_prob$r40_49 * return_prob$r40_49_count, return_prob$r40_49_count)\npl40_49 <- prop.trend.test(return_prob$r40_49 * return_prob$r40_49_count, return_prob$r40_49_count)\n\ntribble(\n    ~overall, ~r00_09, ~r10_19, ~r20_29, ~r30_39, ~r40_49,\n    p$p.value, p00_09$p.value, p10_19$p.value, p20_29$p.value, p30_39$p.value, p40_49$p.value\n)\n\ntribble(\n    ~overall, ~r00_09, ~r10_19, ~r20_29, ~r30_39, ~r40_49,\n    pl$p.value, pl00_09$p.value, pl10_19$p.value, pl20_29$p.value, pl30_39$p.value, pl40_49$p.value\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f2745221e9f0e17cf5119f2a47dd9ccd21dc7168"},"cell_type":"markdown","source":"From the above analysis, we see that there is a strong relationship between the probability a punt is fielded and the formation used by the return team.  We could theoretically decrease the probability that a punt is fielded\n\nWe would like to now show that this relationship is causal.  There is some room for data to answer this question, but speaking with special teams coordinators and other NFL affiliates will be crucial in understanding whether or not putting restrictions on the formation will ultimately lead to fewer concussions.\n\nFor instance, suppose return teams line up with 8 men at the line and only 2 gunner blockers in our dataset when they are aiming to block the punt and instruct the returner to call a fair catch if the punt is not blocked.  Then, forcing all returns to use this formation may not necessarily lead to fewer concussions.  This line of reasoning shows that we need to examine what the return team's intentions were when employing 2, 3, or 4 gunner blockers.\n\nIn order to glean some more informaton on what the intention of the return team is for each play, we will condition on the number of linemen to see whether the return team is aiming for maximum penetration at the line to block the punt, dropping back additional men into coverage, or employing a [hold up technique](http://insidethepylon.com/football-101/glossary-football-101/2015/10/09/itp-glossary-hold-up-technique/) at the line.  We should note that this analysis is still a proxy for understanding the intentions of the return team.  There are times when players will line up as linebackers behind the defensive linemen in order to attack the gaps in between the tackles.\n\n#### Conditioning on linemen\n\nWe now conduct the same analysis on return probability while conditioning on the number of linemen to be strictly less than 7.  The two tables below are again the return probabilities and the counts.  We can see that while the return probabilites with 2 verts are marginally higher than when not conditioning on the number of linemen, they are still much lower than the return probabilities with 3 or 4 verts."},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":false,"trusted":true,"_uuid":"29b9c56f430a73b81aa0709261c361946829214b"},"cell_type":"code","source":"event <- \"punt_received\"\nreturn_prob <- play_info %>%\n  left_join(ngs_return, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  left_join(role_count, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  filter(!is.na(Event), g == 2, rec_line < 7) %>% # , receive_win == \"Lose\", Quarter %in% c(3,4)\n  group_by(v) %>% # rec_line, lb, v, pfb, pr\n  summarise(total = n(),\n            field_prob = sum(Event == event) / n(),\n            r00_09 = sum(between(pos, 0, 9) & Event == event) / sum(between(pos, 0, 9)), \n            r10_19 = sum(between(pos, 10, 19) & Event == event) / sum(between(pos, 10, 19)),\n            r20_29 = sum(between(pos, 20, 29) & Event == event) / sum(between(pos, 20, 29)), \n            r30_39 = sum(between(pos, 30, 39) & Event == event) / sum(between(pos, 30, 39)),\n            r40_49 = sum(between(pos, 40, 49) & Event == event) / sum(between(pos, 40, 49)), \n            r50_59 = sum(between(pos, 50, 59) & Event == event) / sum(between(pos, 50, 59)),\n            r60_69 = sum(between(pos, 60, 69) & Event == event) / sum(between(pos, 60, 69)),\n            r00_09_count = sum(between(pos, 0, 9)), \n            r10_19_count = sum(between(pos, 10, 19)),\n            r20_29_count = sum(between(pos, 20, 29)), \n            r30_39_count = sum(between(pos, 30, 39)),\n            r40_49_count = sum(between(pos, 40, 49)), \n            r50_59_count = sum(between(pos, 50, 59)),\n            r60_69_count = sum(between(pos, 60, 69))) %>%\n  ungroup() %>%\n  filter(total / sum(total) > 0.02) %>%\n  arrange(-total)\n(r_prob <- return_prob %>%\n  select(v, field_prob, r00_09, r10_19, r20_29, r30_39, r40_49))\n(r_count <- return_prob %>%\n  select(v, total, r00_09_count, r10_19_count, r20_29_count, r30_39_count, r40_49_count))\nreturn_prob_after_cond <- sum(r_prob[1, 3:7] * colSums(r_count)[3:7]) / sum(colSums(r_count)[3:7])\nreturn_prob_before_cond <- sum(r_prob$field_prob[] * r_count$total) / sum(colSums(r_count)[3:7])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"87968ef75a72b04a8a29b8c14e2946a045ba018f"},"cell_type":"markdown","source":"In the first table below, we again calculate the p-values for the 3-sample Chi-squared test for each column above.  With the p-value for each column (aside from the 0 - 9 yard line) being quite small ( < 0.001), this indicates that even when we condition for a return team with only two verts using a return formation, there is a statistically significant difference in the rate of return.\n\nIn the second table, we calculate the p-values for a linear relationship between the number of verts and return probability.  We see that there is still a statistically significant linear relationship between the two."},{"metadata":{"_kg_hide-output":false,"_kg_hide-input":true,"trusted":true,"_uuid":"6ce9db5e51d506bf609cb7c85ca0b7166cee53df"},"cell_type":"code","source":"# Conduct proportions tests\np <- prop.test(return_prob$field_prob * return_prob$total, return_prob$total)\npl <- prop.trend.test(return_prob$field_prob * return_prob$total, return_prob$total)\np00_09 <- prop.test(return_prob$r00_09 * return_prob$r00_09_count, return_prob$r00_09_count)\npl00_09 <- prop.trend.test(return_prob$r00_09 * return_prob$r00_09_count, return_prob$r00_09_count)\np10_19 <- prop.test(return_prob$r10_19 * return_prob$r10_19_count, return_prob$r10_19_count)\npl10_19 <- prop.trend.test(return_prob$r10_19 * return_prob$r10_19_count, return_prob$r10_19_count)\np20_29 <- prop.test(return_prob$r20_29 * return_prob$r20_29_count, return_prob$r20_29_count)\npl20_29 <- prop.trend.test(return_prob$r20_29 * return_prob$r20_29_count, return_prob$r20_29_count)\np30_39 <- prop.test(return_prob$r30_39 * return_prob$r30_39_count, return_prob$r30_39_count)\npl30_39 <- prop.trend.test(return_prob$r30_39 * return_prob$r30_39_count, return_prob$r30_39_count)\np40_49 <- prop.test(return_prob$r40_49 * return_prob$r40_49_count, return_prob$r40_49_count)\npl40_49 <- prop.trend.test(return_prob$r40_49 * return_prob$r40_49_count, return_prob$r40_49_count)\n\ntribble(\n    ~overall, ~r00_09, ~r10_19, ~r20_29, ~r30_39, ~r40_49,\n    p$p.value, p00_09$p.value, p10_19$p.value, p20_29$p.value, p30_39$p.value, p40_49$p.value\n)\n\ntribble(\n    ~overall, ~r00_09, ~r10_19, ~r20_29, ~r30_39, ~r40_49,\n    pl$p.value, pl00_09$p.value, pl10_19$p.value, pl20_29$p.value, pl30_39$p.value, pl40_49$p.value\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d516ff42fa446e4a1219855e94621af30db2de20"},"cell_type":"markdown","source":"#### Relationship between verts and return and concussion rate\n\nWe now look at the concussion rate on punts that are fielded (punt received or fumbled).  The first table below shows the overall concussion rate and concussion rate split by field position.  The second table is the sample sizes for the first table.\n\nWe can see below that for both the overall concussion rate (leftmost column), there is a slight increasing trend in the rate as the number of verts increases.  However, once wesplit across field position, there is no clear relationship between the number of gunner blockers and the rate of concussions on fielded punts.  The concussion event is too rare to get a statistically significant result here."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"49f98a93b623b3cd52a0c6f5bdfc3d337d6a29b1"},"cell_type":"code","source":"concuss_rate <- play_info %>% \n  left_join(ngs_return, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  left_join(role_count, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  #mutate(concussion = (GameKey %in% video_review$GameKey[video_review$UOH == FALSE & video_review$Class != \"Upfield\"] & \n  #         PlayID %in% video_review$PlayID[video_review$UOH == FALSE & video_review$Class != \"Upfield\"])) %>%\n  mutate(concussion = (GameKey %in% video_review$GameKey & PlayID %in% video_review$PlayID)) %>%\n  filter(Event %in% c(\"punt_received\", \"fumble\"), g == 2) %>%\n  group_by(v) %>%\n  summarise(total=n(),\n            overall_concuss_rate = sum(concussion == TRUE) / n(),\n            r00_09 = sum(between(pos, 0, 9) & concussion == TRUE) / sum(between(pos, 0, 9)), \n            r10_19 = sum(between(pos, 10, 19) & concussion == TRUE) / sum(between(pos, 10, 19)),\n            r20_29 = sum(between(pos, 20, 29) & concussion == TRUE) / sum(between(pos, 20, 29)), \n            r30_39 = sum(between(pos, 30, 39) & concussion == TRUE) / sum(between(pos, 30, 39)),\n            r40_49 = sum(between(pos, 40, 49) & concussion == TRUE) / sum(between(pos, 40, 49)), \n            r00_09_count = sum(between(pos, 0, 9)), \n            r10_19_count = sum(between(pos, 10, 19)),\n            r20_29_count = sum(between(pos, 20, 29)), \n            r30_39_count = sum(between(pos, 30, 39)),\n            r40_49_count = sum(between(pos, 40, 49))) %>%\n  ungroup() %>%\n  filter(total / sum(total) > 0.02) %>%\n  arrange(v)\nconcuss_rate %>%\n  select(v, overall_concuss_rate, r00_09, r10_19, r20_29, r30_39, r40_49)\nconcuss_rate %>%\n  select(v, total, r00_09_count, r10_19_count, r20_29_count, r30_39_count, r40_49_count)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2f36f3ee1becd93e747aa28d4268a469cebe7d7a"},"cell_type":"markdown","source":"#### Relationship between verts and return and tackle rate\n\nSince the sample size of concussions is too small to find a clear relationship between the number of verts and concussion rate, we will instead look at the tackle rate as a proxy.  We calculate tackle rate as the number of plays with a tackle event divided by the number of plays where a punt is fielded or fumbled."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"f9520feb73eff3757d2f584cc2cfb9f5e86d1437"},"cell_type":"code","source":"ngs_tackle <- ngs_all %>%\n  filter(Event == \"tackle\") %>%\n  group_by(Season_Year, GameKey, PlayID) %>%\n  filter(row_number() == 1) %>%\n  select(Season_Year, GameKey, PlayID) %>%\n  mutate(UID = paste0(Season_Year, \"_\", GameKey, \"_\", PlayID))\n\nngs_oob <- ngs_all %>%\n  filter(Event == \"out_of_bounds\") %>%\n  group_by(Season_Year, GameKey, PlayID) %>%\n  filter(row_number() == 1) %>%\n  select(Season_Year, GameKey, PlayID) %>%\n  mutate(UID = paste0(Season_Year, \"_\", GameKey, \"_\", PlayID))\n\nngs_field <- ngs_return %>%\n  select(Season_Year, GameKey, PlayID, Event) %>%\n  #filter(Event %in% c(\"punt_received\", \"fumble\")) %>%\n  left_join(role_count, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  left_join(play_info, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  mutate(UID = paste0(Season_Year, \"_\", GameKey, \"_\", PlayID)) %>%\n  mutate(Tackle = UID %in% ngs_tackle$UID) %>%\n  filter(g == 2) %>% # , rec_line < 7 , receive_win == \"Lose\", Quarter %in% c(3,4)\n  group_by(v) %>% # rec_line, lb, v, pfb, pr\n  summarise(total = n(),\n            tackle_prob = sum(Tackle == TRUE) / n(),\n            t00_09 = sum(between(pos, 0, 9) & Tackle == TRUE) / sum(between(pos, 0, 9)), \n            t10_19 = sum(between(pos, 10, 19) & Tackle == TRUE) / sum(between(pos, 10, 19)),\n            t20_29 = sum(between(pos, 20, 29) & Tackle == TRUE) / sum(between(pos, 20, 29)), \n            t30_39 = sum(between(pos, 30, 39) & Tackle == TRUE) / sum(between(pos, 30, 39)),\n            t40_49 = sum(between(pos, 40, 49) & Tackle == TRUE) / sum(between(pos, 40, 49)),\n            r00_09_count = sum(between(pos, 0, 9)), \n            r10_19_count = sum(between(pos, 10, 19)),\n            r20_29_count = sum(between(pos, 20, 29)), \n            r30_39_count = sum(between(pos, 30, 39)),\n            r40_49_count = sum(between(pos, 40, 49))\n            ) %>%\n  ungroup() %>%\n  filter(total / sum(total) > 0.02) %>%\n  arrange(v)\n(r_prob <- ngs_field %>%\n  select(v, tackle_prob, t00_09, t10_19, t20_29, t30_39, t40_49))\n(r_count <- ngs_field %>%\n  select(v, total, r00_09_count, r10_19_count, r20_29_count, r30_39_count, r40_49_count))\ntackle_prob_after <- sum(r_prob[1, 3:7] * colSums(r_count)[3:7]) / sum(colSums(r_count)[3:7])\ntackle_prob_before <- sum(r_prob$tackle_prob[] * r_count$total) / sum(colSums(r_count)[3:7])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"eeacc0bd5fc1adcd36f199938faa02c4973d0799"},"cell_type":"markdown","source":"Again, we have below the 3-sample Chi-squared test for each of the columns above in the first table and the test of a linear relationship in the second.  We can see that again, there is a strong linear relationship between the number of verts and the probability that a tackle is performed during the play. "},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"b462a3a935a2459c4ca7c9e93c4c4738e8cd7db2"},"cell_type":"code","source":"# Conduct proportions tests\np <- prop.test(ngs_field$tackle_prob * ngs_field$total, ngs_field$total)\npl <- prop.trend.test(ngs_field$tackle_prob * ngs_field$total, ngs_field$total)\np00_09 <- prop.test(ngs_field$t00_09 * ngs_field$r00_09_count, ngs_field$r00_09_count)\npl00_09 <- prop.trend.test(ngs_field$t00_09 * ngs_field$r00_09_count, ngs_field$r00_09_count)\np10_19 <- prop.test(ngs_field$t10_19 * ngs_field$r10_19_count, ngs_field$r10_19_count)\npl10_19 <- prop.trend.test(ngs_field$t10_19 * ngs_field$r10_19_count, ngs_field$r10_19_count)\np20_29 <- prop.test(ngs_field$t20_29 * ngs_field$r20_29_count, ngs_field$r20_29_count)\npl20_29 <- prop.trend.test(ngs_field$t20_29 * ngs_field$r20_29_count, ngs_field$r20_29_count)\np30_39 <- prop.test(ngs_field$t30_39 * ngs_field$r30_39_count, ngs_field$r30_39_count)\npl30_39 <- prop.trend.test(ngs_field$t30_39 * ngs_field$r30_39_count, ngs_field$r30_39_count)\np40_49 <- prop.test(ngs_field$t40_49 * ngs_field$r40_49_count, ngs_field$r40_49_count)\npl40_49 <- prop.trend.test(ngs_field$t40_49 * ngs_field$r40_49_count, ngs_field$r40_49_count)\n\ntribble(\n    ~overall, ~t00_09, ~t10_19, ~t20_29, ~t30_39, ~t40_49, \n    p$p.value, p00_09$p.value, p10_19$p.value, p20_29$p.value, p30_39$p.value, p40_49$p.value\n)\n\ntribble(\n    ~overall, ~t00_09, ~t10_19, ~t20_29, ~t30_39, ~t40_49,\n    pl$p.value, pl00_09$p.value, pl10_19$p.value, pl20_29$p.value, pl30_39$p.value, pl40_49$p.value\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d59fd9278a6946803299dead72378585e8fec934"},"cell_type":"markdown","source":"We now examine the tackle probabilities while conditioning on the number of linemen being strictly less than 7.  We can see that the tackle probabilities change minimally from without the conditioning."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"fe62f42387d20b6a39f2fa238cb8d55d5077ddd6"},"cell_type":"code","source":"ngs_field <- ngs_return %>%\n  select(Season_Year, GameKey, PlayID, Event) %>%\n  #filter(Event %in% c(\"punt_received\", \"fumble\")) %>%\n  left_join(role_count, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  left_join(play_info, by=c(\"Season_Year\", \"GameKey\",\"PlayID\")) %>%\n  mutate(UID = paste0(Season_Year, \"_\", GameKey, \"_\", PlayID)) %>%\n  mutate(Tackle = UID %in% ngs_tackle$UID) %>%\n  filter(g == 2, rec_line < 7) %>% #  , receive_win == \"Lose\", Quarter %in% c(3,4)\n  group_by(v) %>% # rec_line, lb, v, pfb, pr\n  summarise(total = n(),\n            tackle_prob = sum(Tackle == TRUE) / n(),\n            t00_09 = sum(between(pos, 0, 9) & Tackle == TRUE) / sum(between(pos, 0, 9)), \n            t10_19 = sum(between(pos, 10, 19) & Tackle == TRUE) / sum(between(pos, 10, 19)),\n            t20_29 = sum(between(pos, 20, 29) & Tackle == TRUE) / sum(between(pos, 20, 29)), \n            t30_39 = sum(between(pos, 30, 39) & Tackle == TRUE) / sum(between(pos, 30, 39)),\n            t40_49 = sum(between(pos, 40, 49) & Tackle == TRUE) / sum(between(pos, 40, 49)),\n            r00_09_count = sum(between(pos, 0, 9)), \n            r10_19_count = sum(between(pos, 10, 19)),\n            r20_29_count = sum(between(pos, 20, 29)), \n            r30_39_count = sum(between(pos, 30, 39)),\n            r40_49_count = sum(between(pos, 40, 49))\n            ) %>%\n  ungroup() %>%\n  filter(total / sum(total) > 0.02) %>%\n  arrange(v)\n(r_prob <- ngs_field %>%\n  select(v, tackle_prob, t00_09, t10_19, t20_29, t30_39, t40_49))\n(r_count <- ngs_field %>%\n  select(v, total, r00_09_count, r10_19_count, r20_29_count, r30_39_count, r40_49_count))\ntackle_prob_after_cond <- sum(r_prob[1, 3:7] * colSums(r_count)[3:7]) / sum(colSums(r_count)[3:7])\ntackle_prob_before_cond <- sum(r_prob$tackle_prob[] * r_count$total) / sum(colSums(r_count)[3:7])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"151c5b6a4dd44b1b308fbb40aeb5cb85fb9fb6ba"},"cell_type":"markdown","source":"Now, we estimate the probability of fielded catches and tackles if we were to only allow to verts when there are two gunners.  We see from our calculations above that if we assume that all punt plays have two verts and condition on the field position, then the overall probability of a return is originally 59.5%, but decreases to 48.4%.  When we condition on formation with less than 7 linemen, then the original return probability is 62.9% and decreases to 51.4% by eliminating double coverages.\n\nMoreover, the overall probability of a tackle on a play is originally 45%, but decreases to 38.6%.  When we condition on formation with less than 7 linemen, then the original tackle probability is 47.0% and decreases to 41.3% by eliminating double coverages.\n\nIn all cases, we can see that the probability of a return could decreased as much as 10% and the probability of a tackle on the play could be decreased by as much as 5-6%.\n"},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true,"_uuid":"4eb335123d796765a86405ea492f8df75e3ff100"},"cell_type":"code","source":"# Calculate the proportion of fair catch plays\nreturn_prob_after \nreturn_prob_before\nreturn_prob_after_cond \nreturn_prob_before_cond \n\n# Calculate the proportion of tackle plays\ntackle_prob_after \ntackle_prob_before\ntackle_prob_after_cond \ntackle_prob_before_cond ","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8d83df69c9ce67a5215fe58d7da2dbdf824b984e"},"cell_type":"markdown","source":"#### Recommendation 3: Return Team Formation Restrictions\n\nIn the above analysis, we examined the effect of having different numbers of verts when the kicking team is using a spread formation with two gunners.  We found that both with and without conditioning for a block return strategy, there is statistical evidence to suggest that when there are only two verts, the fair catch probability is higher and the proportion of plays resulting in a tackle is lower.  This suggests that we can mitigate concussions by eliminating the double-teaming of gunners.  With this in mind, our final recommendation is to implement the following rule change (**in bold**):\n\n*9.1.3 Defensive Team Formation*\n \n *Item 1. Punt Formation. When Team A presents a punt formation:*\n\n1.  *A Team B player, who is within one yard of the line of scrimmage, must have his entire body outside the snapper’s shoulder pads at the snap.*\n\n*Penalty: For illegal formation by the defense: Loss of five yards.*\n\n2.  *Team B players cannot push teammates into the offensive formation.*\n\n3. **Team B players cannot align more than one player to an outside receiver**\n\nThe proposed rule change is similar in spirit to some of the rule changes instituted for kickoffs in the 2018 NFL season.  In particular, by putting more men in the middle of the field, there is less chance that a lineman gets a free release to the punt returner, much in the same vein as the ban on blocking within the first 15 yards of a kickoff.  Furthermore, preventing double teaming on the gunner at the line is akin to disallowing wedge blocks during kickoffs.  These similarities should help coaches, players and officials familiarize themselves with the nature and intent of the new rule."},{"metadata":{"trusted":true,"_uuid":"57b361dec4d977a957109484de273f904c9537f3"},"cell_type":"markdown","source":"### Conclusion\n\nIn this kernel, we demonstrated three ways in which the NFL can make punts safer:\n - Updating the peel back blocking definition\n - Emphasizing the Use of Helmet rule on punt plays\n - Prohibiting double-teaming the gunner in spread formations\n \n These proposed changes are easier to implement, familiar, and maintain the nature of the punt play.\n  \nWe hope that with these recommendations, the NFL can continue to make punt plays and football safer and more exciting.  Much thanks to the NFL and Kaggle for hosting this competition."},{"metadata":{"trusted":true,"_uuid":"ad0103f24695035ddf7b3398545a57feb0564b7d"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"R","language":"R","name":"ir"},"language_info":{"mimetype":"text/x-r-source","name":"R","pygments_lexer":"r","version":"3.4.2","file_extension":".r","codemirror_mode":"r"}},"nbformat":4,"nbformat_minor":1}