{"cells":[{"metadata":{"_uuid":"dbfe02a17cb1ada18bf9d813d1d51fd37fc2c30f"},"cell_type":"markdown","source":"# NFL Punt Analytics Competition: R Code Supporting Analysis & Recommendations Summarized in Accompanying Slide Deck"},{"metadata":{"_uuid":"7f4a735f3d69cde3bf0fb09851855c5344487e07"},"cell_type":"markdown","source":"Prepared by: Marc Vincelli\n\nLast Updated: January 9, 2019\n\nStudy Period: 2016-2017"},{"metadata":{"_uuid":"570cdbb284d642cd7964051734a6f79137e7aa93"},"cell_type":"markdown","source":"## Definitions"},{"metadata":{"_uuid":"cc23ace2fb12818a133174c5baaa4040a14d0304"},"cell_type":"markdown","source":"1) Event of interest: Concussion on an NFL play showing a punt setup\n\n2) Concussion rate basis: Per punt play setup \n\n3) Formation Imbalance: A mismatch between the number of opposing players outside the numbers on either side of the field. For example, a formation with 1 Left Gunner opposed by 2 Right Jammers would constitute an imbalance, whereas a formation with 1 Left/Right Gunner and 1 Right/Left Jammer would not under this definition. Note that imbalances outside the numbers lead to imbalances in the central portion of the field (i.e., between the numbers)."},{"metadata":{"_uuid":"bb44a4887386d40380c15dee6803b97dcc6ea7b2"},"cell_type":"markdown","source":"## Preliminaries"},{"metadata":{"trusted":true,"_uuid":"bc974b40840ccca6a1a1e2bdb2fd1f0a62697efb"},"cell_type":"code","source":"# Install necessary libraries\nlibrary(data.table)\nlibrary(stringr)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"74545a6f72745e5be93d50b4495d9a114276bcbf","_execution_state":"idle","trusted":true},"cell_type":"code","source":"# Read-in play_information data and confirm result as expected\nplay_information <- fread('../input/play_information.csv')\ndim(play_information)\nhead(play_information)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8ba61a9162bde4ae673eb77ae8e84c11b999ff76"},"cell_type":"code","source":"# Read-in punt_position data and confirm result as expected\npunt_position <- fread('../input/play_player_role_data.csv')\ndim(punt_position)\nhead(punt_position)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"62a888c51fd38badef283bec3b2193022a0e5934"},"cell_type":"code","source":"# Read-in concussion_events data and confirm result as expected\nconcussion_events <- fread('../input/video_review.csv')\ndim(concussion_events)\nhead(concussion_events)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"db01690692322e754eccfdb6ffe908a2bb83afc2"},"cell_type":"markdown","source":"Note that we have only 37 concussion events (i.e., events of interest) to work with; consequently, we need to focus only on the most important causal drivers of concussions to derive meaningful insight. While this data limitation likely obviates the need for any sophisticated algorithms, it will require us to leverage our understanding of both the dynamics of the game and of concussions in order to define succinct causal variables."},{"metadata":{"trusted":true,"_uuid":"755072f73cc96929edec3d289d0caf4d4da5f1fe"},"cell_type":"code","source":"# Define PuntPlay as concatenation of GameKey and PlayID to uniquely identify each punt play across seasons\nplay_information$PuntPlay <- paste(play_information$GameKey, play_information$PlayID, sep=\"_\")\npunt_position$PuntPlay <- paste(punt_position$GameKey, punt_position$PlayID, sep=\"_\")\nconcussion_events$PuntPlay <- paste(concussion_events$GameKey, concussion_events$PlayID, sep=\"_\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"dc6c914731208e3e0ce9a30cc4bb118935d334ee"},"cell_type":"markdown","source":"## Examine Exposure File (play_information) and Derive Variables Likely to be Key Determinants of Speed"},{"metadata":{"_uuid":"e093d29485ccbe4265b9fca711cf63df45c71581"},"cell_type":"markdown","source":"Physics would suggest that the risk of concussion is dominated by speed (Kinetic Energy = mvv/2) and mitigated by factors that dissipate this energy away from the brain. Therefore, we decide to focus on deriving variables likely to be key determinants of speed, and in particular on those that could be influenced directly through rule modifications.  "},{"metadata":{"_uuid":"c34dfde43541e6e95fafb7da85a551ed3f69b2c3","trusted":true},"cell_type":"code","source":"# Derive variable PuntDistance from PlayDescription\n# Extract position of first instance of punt distance in PlayDescription using regular expression functions\n# Zero/Null punt distance possible due to penalties stopping play (e.g., \"False Start\", \"Delay of Game\", \"Defensive 12 On-field\", \"Illegal Substitution\", \"Neutral Zone Infraction\"), fake punt plays, fumbles, blocked punts, etc.\nposition <- sapply(\"punts [0-9]+ yards\", regexpr, play_information$PlayDescription)\nposition[position == -1] <- NA      # No punt distance information\nstart <- position + nchar(\"punts \")  # Position start of distance value in expression\nplay_information$PuntDistance <- as.integer(substr(play_information$PlayDescription, start, start+1)) # take two characters as punt distance can be between 0-99 yards and coerce to integer to remove any spaces\nplay_information$PuntDistance[is.na(play_information$PuntDistance)] <- 0  # Treat missing distance records as zero distance punts","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4e7a7ff6980043cdb75cb1c4f829500aa521c0a8"},"cell_type":"code","source":"# Look at distribution of punt distances\ntable(play_information$PuntDistance, useNA=\"ifany\")\nmedian(play_information$PuntDistance)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"27f8dfe94f61e05d171d3d5579a3535ccd86f116"},"cell_type":"markdown","source":"The distribution of punt distances is reasonable. The median punt distance on all punt plays is 45 yards. Zero/null punt distances are possible due to penalties stopping play (e.g., \"False Start\", \"Delay of Game\", \"Defensive 12 On-field\", \"Illegal Substitution\", \"Neutral Zone Infraction\"), fake punt plays, fumbles, blocked punts, etc. Small punt distances are possible due to partially blocked punts."},{"metadata":{"trusted":true,"_uuid":"d7141ca20f196fa85d7f106a1927c23d482915ee"},"cell_type":"code","source":"# Derive variable Team from Role to distinguish punting team from returning team\npunt_position$Team <- punt_position$Role %in% c('GL','GLi','GLo','GR','GRi','GRo','PLT','PLG','PLS','PRG','PRT','PLW','PRW','PC','PPL','PPLi','PPLo','PPR','PPRi','PPRo','P') # If True then on punting team\npunt_position$Team[punt_position$Team == TRUE] <- 'PuntingTeam'\npunt_position$Team[punt_position$Team == FALSE] <- 'ReturningTeam'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"63513536a9f8142386f94c730f09e5a2421fe15d"},"cell_type":"code","source":"# Define PuntPlayTeam as concatenation of GameKey, PlayID, and Team to uniquely identify each punt play and team role across seasons\npunt_position$PuntPlayTeam <- paste(punt_position$GameKey, punt_position$PlayID, punt_position$Team, sep=\"_\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"636827ff0f648aadfd372500a812482d5017781d"},"cell_type":"code","source":"# Collapse punt_position records by PuntPlayTeam to return table of punt formations for each of punting team and returning team\n# Sort formation components in ascending order to ensure consistency and comparability across plays\nPuntingTeamFormation <- punt_position[c(punt_position$Team == 'PuntingTeam'), paste(sort(Role), collapse=\"_\"), by=PuntPlay]\ncolnames(PuntingTeamFormation) <- c('PuntPlay','PuntingTeamFormation')\nReturningTeamFormation <- punt_position[c(punt_position$Team == 'ReturningTeam'), paste(sort(Role), collapse=\"_\"), by=PuntPlay]\ncolnames(ReturningTeamFormation) <- c('PuntPlay','ReturningTeamFormation')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ebed8559bbdac478a0343c29a88f0f55b2b8aed8"},"cell_type":"code","source":"# Append PuntingTeamFormation and ReturningTeamFormation onto play_information\ndim(play_information) # 6681 x 16\nplay_information <- merge(play_information, PuntingTeamFormation, by.x='PuntPlay', by.y='PuntPlay', all.x = TRUE)\ndim(play_information) # 6681 x 17\nplay_information <- merge(play_information, ReturningTeamFormation, by.x='PuntPlay', by.y='PuntPlay', all.x = TRUE)\ndim(play_information) # 6681 x 18","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"598e737233b79752494c2ccb0a515fdb69f2621e"},"cell_type":"code","source":"# Derive variables PuntingTeamPlayerCount and ReturningTeamPlayerCount to store number of players; each well-formed formation should have exactly 11 players\nplay_information$PuntingTeamPlayerCount <- str_count(play_information$PuntingTeamFormation, '_') + 1\nplay_information$ReturningTeamPlayerCount <- str_count(play_information$ReturningTeamFormation, '_') + 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f5808234f824929e6efb4932134627eb31712c0a"},"cell_type":"code","source":"# Look at number of records by player count\ntable(play_information$PuntingTeamPlayerCount, useNA=\"ifany\")\ntable(play_information$ReturningTeamPlayerCount, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0e202bab1d0f0255d15c9c2bc267390d10461600"},"cell_type":"markdown","source":"As expected, almost all plays show 11 players in each team's formation. However, there are a number of outliers for which we need to make a decision. Since it should not be possible for a team to have more than 11 players in a formation, we assume that these plays reflect erroneous formation information and decide to exclude them from further analysis. Similarly, having fewer than 10 players seems so unlikely that we assume these plays too reflect erroneous formation information and decide to exclude them. We also exclude records with no formation information. We opt to preserve plays with exactly 10 players in either formation since (i) there is a small cluster of them, and (ii) it is possible to have only 10 players on the field as a result of disorganization / botched substitutions. In the end, our decisions result in only 33 out of 6681 punt play records being excluded, leaving us with 6648 for further analysis."},{"metadata":{"trusted":true,"_uuid":"162340aead8c8214647ad2a0fb8f95711741074a"},"cell_type":"code","source":"# Exclude records with erroneous formation information (Less than 10 players, More than 11 players, NAs)\n# We allow for the possibility of 10 player formations (e.g., late changes)\nexclusions <- ((play_information$PuntingTeamPlayerCount > 11) | (play_information$ReturningTeamPlayerCount > 11) | (play_information$PuntingTeamPlayerCount < 10) | (play_information$ReturningTeamPlayerCount < 10) | is.na(play_information$PuntingTeamPlayerCount) | is.na(play_information$ReturningTeamPlayerCount))\nerroneous_play_information <- play_information[exclusions,]\ndim(play_information)\ndim(erroneous_play_information) # Only 33 exclusions out of 6681 records - OK\nplay_information <- play_information[!exclusions,]\ndim(play_information)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a83b7b1442f1ebec16c21daf11e5f59c9dc75693"},"cell_type":"code","source":"# Look at resulting formations\nhead(sort(table(play_information$PuntingTeamFormation, useNA=\"ifany\"), decreasing = TRUE))\nlength(table(play_information$PuntingTeamFormation, useNA=\"ifany\"))\nhead(sort(table(play_information$ReturningTeamFormation, useNA=\"ifany\"), decreasing = TRUE))\nlength(table(play_information$ReturningTeamFormation, useNA=\"ifany\"))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6b5cd83f6c37aaa4bf7690d16158c5e5a8bbf740"},"cell_type":"markdown","source":"We see that there are 56 different punting formations, of which two are most commonly used, versus 481 different returning formations. There is too much noise in this multitude of formations, so we need to extract features from these formations that have significantly lower dimensionality and yet are causally meaningful. We decide to focus on the roles outside the numbers (i.e., gunners and jammers), and any resulting imbalances, recognizing that any imbalances outside the numbers lead to imbalances in the central portion of the field (i.e., between the numbers)."},{"metadata":{"trusted":true,"_uuid":"dff12828aed9149cb2abece87c96bfca7b0b99e7"},"cell_type":"code","source":"# Derive variables to capture number of left and right side gunner and jammer roles in punting team formation\nplay_information$NumberOfLeftGunners <- str_count(play_information$PuntingTeamFormation, 'GL')\nplay_information$NumberOfRightGunners <- str_count(play_information$PuntingTeamFormation, 'GR')\nplay_information$NumberOfLeftJammers <- str_count(play_information$ReturningTeamFormation, 'VL')\nplay_information$NumberOfRightJammers <- str_count(play_information$ReturningTeamFormation, 'VR')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"37c68cfecde16c435e5e3abe5ae78912e7424479"},"cell_type":"code","source":"# Derive variable FormationImbalance to flag plays involving returning team formations that do not balance the punting team's formation outside the numbers\nplay_information$FormationImbalance <- as.integer(!((play_information$NumberOfLeftGunners == play_information$NumberOfRightJammers) & (play_information$NumberOfRightGunners == play_information$NumberOfLeftJammers)))\ntable(play_information$FormationImbalance, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"dc4471002ac40247efbeb902bdb9e7de717447c8"},"cell_type":"markdown","source":"We note that there are roughly the same number of balanced and imbalanced punt play formations in aggregate."},{"metadata":{"trusted":true,"_uuid":"2ed5f4ab6ae2981a9f2a4994dc000ab9c46a6274"},"cell_type":"code","source":"# Derive indicator Penalty to flag plays with penalties\nplay_information$Penalty <- as.integer(((str_count(play_information$PlayDescription, 'PENALTY')) > 0) | ((str_count(play_information$PlayDescription, 'Penalty')) > 0) | ((str_count(play_information$PlayDescription, 'penalty')) > 0))\ntable(play_information$Penalty, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ef41b94e76edc0b52456f0e4fb12fb110e644e67"},"cell_type":"markdown","source":"We are interested in considering penalties because they can materially alter the motion dynamics on a punt play (for example, consider the impact of holding). We note that approximately 17% of punt plays (1117/6648) involve at least one penalty."},{"metadata":{"trusted":true,"_uuid":"2411b0e7efafbd54c378cb7fd01a569cf8b77574"},"cell_type":"code","source":"# Derive indicator ReturnAttempt to flag plays with a return attempt\n# Punts resulting in a fair catch, downing, out of bounds, touchback, etc. do not constitute having a return attempt\nReturnAttempt1 <- sapply(\"for [-]?[0-9]+ yards\", regexpr, play_information$PlayDescription)\nReturnAttempt2 <- sapply(\"for no gain\", regexpr, play_information$PlayDescription)\nReturnAttempt1[ReturnAttempt1 == -1] <- 0\nReturnAttempt2[ReturnAttempt2 == -1] <- 0\nplay_information$ReturnAttempt <- as.integer(ReturnAttempt1 | ReturnAttempt2)\ntable(play_information$ReturnAttempt, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a212741215bfb27daeb0abe548d1375631d206e2"},"cell_type":"markdown","source":"Less than half of punt plays involve a return attempt, indicating that more than half of punt plays result in a fair catch, downing, out of bounds, touchback, or other similar outcome."},{"metadata":{"trusted":true,"_uuid":"5ef1df195bdbb2979f3464516f1c94991408b92e"},"cell_type":"code","source":"# Derive variable DistanceToEndzone (i.e., distance from punting team's line of scrimmage to opposing team's endzone)\nright = function(string, num_char) {\n  substr(string, nchar(string) - (num_char-1), nchar(string))\n}\nplay_information$DistanceToEndzone <- abs((as.integer(sub(\" \", \"\", substr(play_information$YardLine, 1, 3)) == play_information$Poss_Team) * 100) - as.integer(sub(\" \", \"\", right(play_information$YardLine, 2))))\ntable(play_information$DistanceToEndzone, useNA=\"ifany\")\nmedian(play_information$DistanceToEndzone)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0a00a8eb31ba1adcf3f9ccca1f84c69511f83c81"},"cell_type":"markdown","source":"The distribution of distances to the opposing team's endzone on punt decisions is reasonable. The median distance to endzone on all punt plays is 67 yards."},{"metadata":{"_uuid":"5f3a24d92c30f4206523a75d3b837b6542af6828"},"cell_type":"markdown","source":"## Examine Event File (concussion_events) with Corresponding Exposure Information Appended"},{"metadata":{"trusted":true,"_uuid":"0bda33b606a2eb988d5dd920cfc4161dee0150e7"},"cell_type":"code","source":"# Define PuntPlayGSISID and PuntPlayPrimaryPartnerGSISID to link concussion events with player role\nconcussion_events$PuntPlayGSISID <- paste(concussion_events$GameKey, concussion_events$PlayID, concussion_events$GSISID, sep=\"_\")\nconcussion_events$PuntPlayPrimaryPartnerGSISID <- paste(concussion_events$GameKey, concussion_events$PlayID, concussion_events$Primary_Partner_GSISID, sep=\"_\")\npunt_position$PuntPlayGSISID <- paste(punt_position$GameKey, punt_position$PlayID, punt_position$GSISID, sep=\"_\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"eea1cbe8fd15d9ffb5c8f8aad944d3365e9c1644"},"cell_type":"code","source":"# Append player role information onto concussion_events\ndim(concussion_events) # 37 x 13\nconcussion_events <- merge(concussion_events, punt_position[,c(\"PuntPlayGSISID\", \"Role\")], by.x='PuntPlayGSISID', by.y='PuntPlayGSISID', all.x = TRUE)\nnames(concussion_events)[length(names(concussion_events))] <- \"PlayerRole\"\ndim(concussion_events) # 37 x 14\nconcussion_events <- merge(concussion_events, punt_position[,c(\"PuntPlayGSISID\", \"Role\")], by.x='PuntPlayPrimaryPartnerGSISID', by.y='PuntPlayGSISID', all.x = TRUE)\nnames(concussion_events)[length(names(concussion_events))] <- \"PrimaryPartnerRole\"\ndim(concussion_events) # 37 x 15","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f5a708959c40e0f34d757778e67182e49e40b625"},"cell_type":"code","source":"# Look at PlayerRole\ntable(concussion_events$PlayerRole, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"54f51aedc2af03dee4d5fcee9d8abbe711cbd1bc"},"cell_type":"markdown","source":"We note that 73% (27/37) of the concussions were incurred by players on the punting team. We also note that 84% (31/37) of the concussions were incurred by players starting between the numbers (including the punter and punt returner)."},{"metadata":{"trusted":true,"_uuid":"24d5a3d81b45acd78e5d5428cbfca4b62af4c935"},"cell_type":"code","source":"# Look at PrimaryPartnerRole\ntable(concussion_events$PrimaryPartnerRole, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a542709b99a2d4be82b10c959d165e71585f75d0"},"cell_type":"markdown","source":"We note that 49% (18/37) of the concussions were delivered by players on the returning team. We also note that 76% (28/37) of the concussions were delivered by players starting between the numbers (including the punter and punt returner)."},{"metadata":{"trusted":true,"_uuid":"b638ebb155ee9e8279b2b3c753dbe6ccb988d879"},"cell_type":"code","source":"# Look at Player_Activity_Derived (i.e., activities of concussed player)\ntable(concussion_events$Player_Activity_Derived, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"18abdbd456f53d3472ca9179abb42efdc5de691b"},"cell_type":"markdown","source":"We note that more concussions resulted from contact initiation (Blocking + Tackling = 8 + 13 = 21) than from contact receipt (Blocked + Tackled = 10 + 6 = 16). This finding suggests that blindsiding or any potential visibility limitations resulting from one's equipment is not a key driver. We decide to remove Player_Activity_Derived from further analysis."},{"metadata":{"trusted":true,"_uuid":"2e13d9b2adc6334f743e99cb91ea56eb90f2be97"},"cell_type":"code","source":"# Look at Primary_Partner_Activity_Derived (i.e., activities of player primarily responsible for delivering concussive impact)\ntable(concussion_events$Primary_Partner_Activity_Derived, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f2e5a8e9954a7973d3c8a77bc2254c2d8dbaf1d2"},"cell_type":"markdown","source":"We do not observe any obvious trends within the small category counts. We decide to remove Primary_Partner_Activity_Derived from further analysis."},{"metadata":{"trusted":true,"_uuid":"a6443029ab2f6239f2e2fa7c3b021aa1b4512ecc"},"cell_type":"code","source":"# Look at Turnover_Related\ntable(concussion_events$Turnover_Related, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3048ac03005c44ed0d8f27bd3483f2906f17f12b"},"cell_type":"markdown","source":"This variable does not provide any additional information and as such we decide to remove it from further analysis."},{"metadata":{"trusted":true,"_uuid":"e8dd9ed5d827b036a1b5da2ffa1e8d40dbda7a32"},"cell_type":"code","source":"# Look at Primary_Impact_Type\ntable(concussion_events$Primary_Impact_Type, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"88836f997d9f32c8a0b096c746887659e3afbfde"},"cell_type":"markdown","source":"As expected, we note that Helmet-to-body and Helmet-to-helmet impacts account for almost all concussions (34/37). Since there is little new insight offered by this observation, we decide to remove Primary_Impact_Type from further analysis."},{"metadata":{"trusted":true,"_uuid":"ae67414ae4ed6cce6a3d9f54f3a91592491f73d0"},"cell_type":"code","source":"# Look at Friendly_Fire\ntable(concussion_events$Friendly_Fire, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"838aa493c929a874381b8dc2681a838916976824"},"cell_type":"markdown","source":"As expected, we note that most concussions result from impacts with opposing team members (28/37). Since there is little new insight offered by this observation, we decide to remove Friendly_Fire from further analysis."},{"metadata":{"trusted":true,"_uuid":"260898443fa12b69f3f884f5f667f00f26bb8fbe"},"cell_type":"code","source":"# Append return attempt information onto concussion_events\ndim(concussion_events) # 37 x 15\nconcussion_events <- merge(concussion_events, play_information[,c(\"PuntPlay\", \"ReturnAttempt\")], by.x='PuntPlay', by.y='PuntPlay', all.x = TRUE)\ndim(concussion_events) # 37 x 16","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"35ff607a3e200a4599b70f342fb861bad75ed2f3"},"cell_type":"code","source":"# Look at ReturnAttempt\ntable(concussion_events$ReturnAttempt, useNA=\"ifany\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f3ee88c1ca256b804d521fe6e84439b87a4410e4"},"cell_type":"markdown","source":"As expected, we note that the vast majority (32/37) of punt-related concussions occurred during plays involving a return attempt. While this observation suggests that the risk of concussion could be significantly lowered by reducing/eliminating return attempts (for example, by mandating a fair catch), such a change would adversely affect the integrity and appeal of the game. Consequently, we decide to remove ReturnAttempt from further analysis."},{"metadata":{"trusted":true,"_uuid":"226b5fe948213f05223d07cb3cc259514eb026a3"},"cell_type":"code","source":"# Append exposure information from play_information onto concussion_events\ndim(concussion_events) # 37 x 16\nconcussion_events_summary <- merge(concussion_events[,c(\"PuntPlay\",\"PlayerRole\",\"PrimaryPartnerRole\")],\n                           play_information[, c(\"PuntPlay\",\"PuntingTeamFormation\",\"ReturningTeamFormation\",\"FormationImbalance\",\"Penalty\",\"PuntDistance\",\"DistanceToEndzone\")],\n                           by.x='PuntPlay', by.y='PuntPlay', all.x = TRUE)\ndim(concussion_events_summary) # 37 x 9","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"68ec66a9fce2ae3aee1c7c301b74a74b43bf431f"},"cell_type":"code","source":"# Look at concussion events with derived variables\nconcussion_events_summary\npaste(\"Number of Concussion Events Occurring on Punt Plays with Formation Imbalances: \", sum(concussion_events_summary$FormationImbalance))\npaste(\"Number of Concussion Events Occurring on Punt Plays with Penalties: \", sum(concussion_events_summary$Penalty))\npaste(\"Median Punt Return on Punt Plays with Concussions: \", median(concussion_events_summary$PuntDistance))\npaste(\"Median Distance to Opposing Team's Endzone on Punt Plays with Concussions: \", median(concussion_events_summary$DistanceToEndzone))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"212868466444d91dcce5ae92e0f6693895040914"},"cell_type":"markdown","source":"Based on this summary table of the 37 observed concussions, we make the following observations:\n* FormationImbalance appears to be the most powerful single predictor of concussions within the derived set (to be confirmed by examining rates below), being associated with 24 of the 37 concussion events (84%). We decide to proceed with this variable, which is one that can also be influenced through specific rule modifications.\n* Penalties were recorded on 10 punt plays involving concussions. The interaction between FormationImbalance and Penalty is likely complex and we do not have enough data to appropriately model it explicitly(e.g., depending on who is - say - holding, the penalty can either amplify or mitigate formation imbalances). Consequently, we decide to only use Penalty to isolate the \"clean\" plays when calculating the probability of concussion by FormationImbalance (see next section).\n* The median punt distance on punt plays with concussions (46 yards) is similar to the median punt distance on all punt plays (45 yards). Since there is not an obvious relationship between punt distance and the observed concussion events, we decide to remove it from further analysis.\n* The median distance to the opposing team's endzone is greater on punt plays with concussions (73 yards) than on all punt plays (67 yards). This observation is consistent with the view that the more room one has to run and manoeuvre, the more speed one can gather, and thus the higher the risk of injury one presents to himself and others. However, since there is not an obvious relationship between distance to the opposing team's endzone and the observed concussion events, we decide to remove it from further analysis.\n"},{"metadata":{"_uuid":"e3be2146466489f90dd0e1c04b8a54c4e32fca20"},"cell_type":"markdown","source":"## Probability of Concussion on Plays with Formation Imbalances vs Plays without Formation Imbalances"},{"metadata":{"trusted":true,"_uuid":"e70672e9c24e9ebbdaf59f0d196d413026fa69da"},"cell_type":"code","source":"# Calculate probability of concussion on plays with/without formation imbalances regardless of whether penalty was called on the play\nprobability_concussion_imbalanced <- sum(concussion_events_summary$FormationImbalance == 1) / sum(play_information$FormationImbalance == 1)\nprobability_concussion_balanced <- sum(concussion_events_summary$FormationImbalance == 0) / sum(play_information$FormationImbalance == 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8091b6ce9c2c7fb4b080ce70b329943401604ce1"},"cell_type":"code","source":"# Calculate probability of concussion on plays with/without formation imbalances and without any penalties\nprobability_concussion_imbalanced_nopenalty <- sum((concussion_events_summary$FormationImbalance == 1) & (concussion_events_summary$Penalty == 0)) / sum((play_information$FormationImbalance == 1) & (play_information$Penalty == 0))\nprobability_concussion_balanced_no_penalty <- sum((concussion_events_summary$FormationImbalance == 0) & (concussion_events_summary$Penalty == 0)) / sum((play_information$FormationImbalance == 0) & (play_information$Penalty == 0)) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e7482ab292ec81bc9e37c2e4dcf1f6cdaa089595"},"cell_type":"code","source":"# Output counts\npaste(\"Number of concussion events on plays with formation imbalances: \", sum(concussion_events_summary$FormationImbalance == 1))\npaste(\"Number of total punt play setups with formation imbalances: \", sum(play_information$FormationImbalance == 1))\npaste(\"Number of concussion events on plays without formation imbalances: \", sum(concussion_events_summary$FormationImbalance == 0))\npaste(\"Number of total punt play setups without formation imbalances: \", sum(play_information$FormationImbalance == 0))\npaste(\"Number of concussion events on plays with formation imbalances and no penalties: \", sum((concussion_events_summary$FormationImbalance == 1) & (concussion_events_summary$Penalty == 0)))\npaste(\"Number of total punt play setups with formation imbalances and no penalties: \", sum((play_information$FormationImbalance == 1) & (play_information$Penalty == 0)))\npaste(\"Number of concussion events on plays without formation imbalances and no penalties: \", sum((concussion_events_summary$FormationImbalance == 0) & (concussion_events_summary$Penalty == 0)))\npaste(\"Number of total punt play setups without formation imbalances and no penalties: \", sum((play_information$FormationImbalance == 0) & (play_information$Penalty == 0)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"aa7f39ca76a779eb80f28ce2ca7fa1add29eddf2"},"cell_type":"code","source":"# Output results\npaste(\"Probability of concussion on plays with formation imbalances: \", probability_concussion_imbalanced)\npaste(\"Probability of concussion on plays without formation imbalances: \", probability_concussion_balanced)\npaste(\"Probability of concussion on plays with formation imbalances and no penalties: \", probability_concussion_imbalanced_nopenalty)\npaste(\"Probability of concussion on plays without formation imbalances and no penalties: \", probability_concussion_balanced_no_penalty)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"13314260967038311ba9130d5f14f9cff3e71dfd"},"cell_type":"markdown","source":"Based on these results, we find that the probability of concussion (aka \"risk of concussion\") is 1.94 times higher (~ 7.40 per thousand /  3.82 per thousand) on plays with formation imbalances than on plays without formation imbalances. The differential is even more stark when we look at only \"clean\" plays, that is plays without any penalties. On plays without penalties, we find that the probability of concussion is 2.7 times higher (~ 7.36 per thousand / 2.71 per thousand) on plays with formation imbalances than on plays without."},{"metadata":{"_uuid":"4668ee37c3ba6551573b71636007752c1d606972"},"cell_type":"markdown","source":"## Recommendations"},{"metadata":{"_uuid":"62e96735901d14c31c57dc901e7f84ec8a9f8e16"},"cell_type":"markdown","source":"Based on the totality of the aforementioned findings, the author recommends that the NFL require balance between the opposing teams’ initial formations during punt plays to mitigate the likelihood of players gathering speed unimpeded and, as a result, causing concussion injuries either to themselves or others. The rule modification would ideally be of the nature \"All punt formations at the time of the snap must have exactly one player outside the numbers on each side of the field,\" with any violations being assessed at the time of the snap and penalized as an illegal formation (5 yards).\n"}],"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}