{"cells":[{"metadata":{"_uuid":"a781329c62aa1cd4e7a551268cec1b97b39107c0"},"cell_type":"markdown","source":"***Rule Proposal: The 'Halo' Rule***\n*The rule would stipulate that:*\n* *Players must allow five (5) yards to the opponent attempting to receive the kick. The five-yards are defined as a circle with a 5-yard radius, with the center point being the ball as it is first touched, or touches the ground.*\n     * *Five (5) yards will be assessed if any players are within the circle at the time the ball is fielded or first contacts the ground*\n     * *Fifteen (15) yards will be assessed for any players within the circle at the time the ball is fielded or lands, who contacts the return man. *"},{"metadata":{"_uuid":"c3174e60283b52fcf9128345aa198089c43cb407","_execution_state":"idle","trusted":true},"cell_type":"code","source":"# Title: NFL Analytics - Punt Rule Change Proposals\n# Author: Nate Weller\n# Date: 1/4/2018\n\n# loading basic info\n\nplayinfo <- read.csv('../input/play_information.csv')\nplayerrole <- read.csv('../input/play_player_role_data.csv')\nplayerpunt <- read.csv('../input/player_punt_data.csv')\ninjuryinfo <- read.csv('../input/video_review.csv')\n\ninjuryinfo$GamePlayKey <- paste(injuryinfo$GameKey, injuryinfo$PlayID)\ninjuryplays <- as.list(injuryinfo$GamePlayKey)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"71a8a1c8cf664bbd40f935c167dadde7010efea3"},"cell_type":"code","source":"library(dplyr)\n\nngs1 <- read.csv('../input/NGS-2017-reg-wk1-6.csv')\nngs1$GamePlayKey <- paste(ngs1$GameKey, ngs1$PlayID)\nngs1_sub <- filter(ngs1, GamePlayKey %in% injuryplays)\nngs1 <- NULL\n\nngs2 <- read.csv('../input/NGS-2017-reg-wk7-12.csv')\nngs2$GamePlayKey <- paste(ngs2$GameKey, ngs2$PlayID)\nngs2_sub <- filter(ngs2, GamePlayKey %in% injuryplays)\nngs2 <- NULL\n\nngs3 <- read.csv('../input/NGS-2017-reg-wk13-17.csv')\nngs3$GamePlayKey <- paste(ngs3$GameKey, ngs3$PlayID)\nngs3_sub <- filter(ngs3, GamePlayKey %in% injuryplays)\nngs3 <- NULL\n\nngs4 <- read.csv('../input/NGS-2016-reg-wk1-6.csv')\nngs4$GamePlayKey <- paste(ngs4$GameKey, ngs4$PlayID)\nngs4_sub <- filter(ngs4, GamePlayKey %in% injuryplays)\nngs4 <- NULL\n\nngs5 <- read.csv('../input/NGS-2016-reg-wk7-12.csv')\nngs5$GamePlayKey <- paste(ngs5$GameKey, ngs5$PlayID)\nngs5_sub <- filter(ngs5, GamePlayKey %in% injuryplays)\nngs5 <- NULL\n\nngs6 <- read.csv('../input/NGS-2016-reg-wk13-17.csv')\nngs6$GamePlayKey <- paste(ngs6$GameKey, ngs6$PlayID)\nngs6_sub <- filter(ngs6, GamePlayKey %in% injuryplays)\nngs6 <- NULL\n\nngs7 <- read.csv('../input/NGS-2016-pre.csv')\nngs7$GamePlayKey <- paste(ngs7$GameKey, ngs7$PlayID)\nngs7_sub <- filter(ngs7, GamePlayKey %in% injuryplays)\nngs7 <- NULL\n\nngs8 <- read.csv('../input/NGS-2017-pre.csv')\nngs8$GamePlayKey <- paste(ngs8$GameKey, ngs8$PlayID)\nngs8_sub <- filter(ngs8, GamePlayKey %in% injuryplays)\nngs8 <- NULL\n\nngs <- rbind(ngs1_sub, ngs2_sub, ngs3_sub, ngs4_sub, ngs5_sub, ngs6_sub, ngs7_sub, ngs8_sub) # combine the three subsets of NGS data\n\nngs.check <- as.list(unique(ngs$GamePlayKey))\nlength(ngs.check) # confirms all 37 plays were loaded","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d2ef9bf54a622e3a91b7d62e4b0e5ac858dcf9d5"},"cell_type":"code","source":"# using the same process, we load a control group of plays where an injury did not occur\n\ncontrol <- read.csv('../input/video_footage-control.csv')\ncontrol$GamePlayKey <- paste(control$gamekey, control$playid)\ncontrol.GamePlayKey <- as.list(unique(control$GamePlayKey))\n\nngs1 <- read.csv('../input/NGS-2017-reg-wk1-6.csv')\nngs1$GamePlayKey <- paste(ngs1$GameKey, ngs1$PlayID)\nngs1_sub <- filter(ngs1, GamePlayKey %in% control.GamePlayKey)\nngs1 <- NULL\n\nngs2 <- read.csv('../input/NGS-2017-reg-wk7-12.csv')\nngs2$GamePlayKey <- paste(ngs2$GameKey, ngs2$PlayID)\nngs2_sub <- filter(ngs2, GamePlayKey %in% control.GamePlayKey)\nngs2 <- NULL\n\nngs3 <- read.csv('../input/NGS-2017-reg-wk13-17.csv')\nngs3$GamePlayKey <- paste(ngs3$GameKey, ngs3$PlayID)\nngs3_sub <- filter(ngs3, GamePlayKey %in% control.GamePlayKey)\nngs3 <- NULL\n\nngs4 <- read.csv('../input/NGS-2016-reg-wk1-6.csv')\nngs4$GamePlayKey <- paste(ngs4$GameKey, ngs4$PlayID)\nngs4_sub <- filter(ngs4, GamePlayKey %in% control.GamePlayKey)\nngs4 <- NULL\n\nngs5 <- read.csv('../input/NGS-2016-reg-wk7-12.csv')\nngs5$GamePlayKey <- paste(ngs5$GameKey, ngs5$PlayID)\nngs5_sub <- filter(ngs5, GamePlayKey %in% control.GamePlayKey)\nngs5 <- NULL\n\nngs6 <- read.csv('../input/NGS-2016-reg-wk13-17.csv')\nngs6$GamePlayKey <- paste(ngs6$GameKey, ngs6$PlayID)\nngs6_sub <- filter(ngs6, GamePlayKey %in% control.GamePlayKey)\nngs6 <- NULL\n\nngs.control <- rbind(ngs1_sub, ngs2_sub, ngs3_sub, ngs4_sub, ngs5_sub, ngs6_sub)\nngs.control.check <- as.list(unique(ngs.control$GamePlayKey))\nlength(ngs.control.check) # number of plays in control group","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c749767990d8bc4f9b60276d5a736f41990ec007"},"cell_type":"markdown","source":"***Concussions by Position:*** *To get to our proposal, we first looked at the position groups most prone to concussions. The plot below indicates that punt returners (PR), and gunners (GL, GR) are among the most dangerous positions on punt plays. With the exepction of interior offensive lineman, (left and right guard have 8 tracked concusssions), the most dangerous positions are those that are often in space, and more prone to large collissions in space, be it a block or a tackle.*"},{"metadata":{"trusted":true,"_uuid":"d9b7324935c6badd940840bff6e524d126b6f0dd"},"cell_type":"code","source":"# Punt returners (PR) were among the most concussed position group (5), as is displayed in the plot below.\n# But of equal note, gunners (GL,GR) are also among the highest totals for position groups (5)\n# Interior offensive lineman pace the group (8)\n\nlibrary(ggplot2)\nlibrary(sqldf)\nlibrary(colorRamps)\nlibrary(RColorBrewer)\n\ninjuryinfo_role <- merge(injuryinfo, playerrole, on = c('GameKey', 'PlayID', 'GSISID'))\n\ncol = colorRampPalette(brewer.pal(9,\"Blues\"))(17) # expanding color pallete do to number of columns\n\n# SQL query to sort the data for plotting\nrole_plot <- sqldf('SELECT \n                   Role,\n                   COUNT(Role) AS Count\n                   FROM injuryinfo_role\n                   GROUP BY Role')\n\nggplot(data = role_plot, aes(x = reorder(role_plot$Role, Count), y = role_plot$Count), fill = role_plot$Role) +\n  geom_bar(fill = col, stat = 'identity') + \n  geom_label(aes(x = 1, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 2, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 3, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 4, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 5, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 6, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 7, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 8, y = 1, label = \"1\"), fill = \"white\") +\n  geom_label(aes(x = 9, y = 2, label = \"2\"), fill = \"white\") +\n  geom_label(aes(x = 10, y = 2, label = \"2\"), fill = \"white\") +\n  geom_label(aes(x = 11, y = 2, label = \"2\"), fill = \"white\") +\n  geom_label(aes(x = 12, y = 2, label = \"2\"), fill = \"white\") +\n  geom_label(aes(x = 13, y = 4, label = \"4\"), fill = \"white\") +\n  geom_label(aes(x = 14, y = 4, label = \"4\"), fill = \"white\") +\n  geom_label(aes(x = 15, y = 4, label = \"4\"), fill = \"white\") +\n  geom_label(aes(x = 16, y = 4, label = \"4\"), fill = \"white\") +\n  geom_label(aes(x = 17, y = 5, label = \"5\"), fill = \"white\") +\n  ggtitle('Concussions by Position') +\n  xlab(\"\") + \n  ylab(\"\") + \n  theme_minimal() +\n  theme(legend.position = 'none',\n       panel.grid = element_blank(),\n       axis.text.y = element_blank())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cb6f9696a7265281a9e01637bf18c29c5b1c28f5"},"cell_type":"markdown","source":"***Average Distance to Returner at Time of Catch:*** *Using NGS tracking data we looked at how close a defender was to the returner at the time the punt is recieved (Event of punt_received, kick_received, fair_catch, punt_landed), and how that may impact the liklihood of a concussion, specifcally as it relates to injuries on the punt returner. Noteworthy findings:*\n* *On plays where the punt returner was injured, the average distance of the closest defender at the time the punt was received was 6.01 yards, versus 9.32 for plays in the control group. *\n* *On 3 of those 5 plays the closest defender was already within 3 yards at the time the ball was received*"},{"metadata":{"trusted":true,"_uuid":"c9593a0470f5c2e8dd93fc35ec9d7ec95451c8e2"},"cell_type":"code","source":"# Looking at average distance to returner at time of catch, plays where injuries occured versus control group\n\n# creates a subset of the main ngs and ngs.control dataframes looking at the moment a punt is either recived\n# or first contacts the ground. Instances not included were either never fielded by the receiving team, kicked out\n# of play, or a fake punt\n\nlibrary(data.table)\n\nngs.TimeOfCatch <- subset(ngs, Event == \"punt_received\" | Event == \"punt_land\" | Event == \"kick_received\" | Event == \"fair_catch\")\nngs.TimeOfCatch <- merge(ngs.TimeOfCatch, playerrole, on  = c('Season_Year', 'GameKey', 'PlayId', 'GSISID'))\nngs.TimeOfCatch$Off.Def <- ifelse(ngs.TimeOfCatch$Role %in% c('VR', 'VRo', 'VRi', 'PDR1', 'PDR2', 'PDR3', 'PDL3',\n                                                  'PDL2', 'PDL1', 'PLR', 'PLM', 'PLL', 'PFB', 'PR', 'VL', 'VLi', 'VLo'), 1, 0)\n\nGamePlayKey.List <- as.list(unique(ngs.TimeOfCatch$GamePlayKey))\n\nngs.TimeOfCatch.control <- subset(ngs.control, Event == \"punt_received\" | Event == \"punt_land\" | Event == \"kick_received\" | Event == \"fair_catch\")\nngs.TimeOfCatch.control <- merge(ngs.TimeOfCatch.control, playerrole, on  = c('Season_Year', 'GameKey', 'PlayId', 'GSISID'))\nngs.TimeOfCatch.control$Off.Def <- ifelse(ngs.TimeOfCatch.control$Role %in% c('VR', 'VRo', 'VRi', 'PDR1', 'PDR2', 'PDR3', 'PDL3',\n                                                              'PDL2', 'PDL1', 'PLR', 'PLM', 'PLL', 'PFB', 'PR', 'VL', 'VLi', 'VLo'), 1, 0)\n\nGamePlayKey.List.control <- as.list(unique(ngs.TimeOfCatch.control$GamePlayKey))\n\n# distance formula\ndistance <- function (x2, x1, y2, y1){\n  distance <- sqrt((x2 - x1)^2 + (y2 - y1)^2)\n  return(distance)\n}\n\n# generates dataframe for average distance of closest defender on plays where no injury occured\ndistance.injured.control <- NULL\ndistances.list.control <- NULL\nfaircatch.list.control <- NULL\nPlayID.list.control <- NULL\nGameKey.list.control <- NULL\n\nfor (i in 1:34){\n  ngs.distance <- subset(ngs.TimeOfCatch.control, GamePlayKey == GamePlayKey.List.control[i])\n  x.return <- ngs.distance[ngs.distance$Role == 'PR', 'x'] \n  y.return <- ngs.distance[ngs.distance$Role == 'PR', 'y'] \n  player.distance <- NULL\n  \n  for (j in 1:11){\n    data <- subset(ngs.distance, Role != 'PR' & Off.Def == 0)\n    x.player <- data$x[j]\n    y.player <- data$y[j]\n    dis <- distance(x.player, x.return, y.player, y.return)\n    player.distance <- rbind(player.distance, dis)\n    faircatch <- ifelse(ngs.distance$Event[1] == 'fair_catch', 1, 0)\n    PlayID <- ngs.distance$PlayID[1]\n    GameKey <- ngs.distance$GameKey[1]\n  }\n  \n  faircatch.list.control <- rbind(faircatch.list.control, faircatch)\n  distances.list.control <- rbind(distances.list.control, min(player.distance))\n  PlayID.list.control <- rbind(PlayID.list.control, PlayID)\n  GameKey.list.control <- rbind(GameKey.list.control, GameKey)\n}\n\ndistance.injured.control <- data.table(GameKey.list.control, PlayID.list.control, distances.list.control, faircatch.list.control)\ncolnames(distance.injured.control) <- c('GameKey', 'PlayID', 'Distance', 'FairCatch')\n\n# filters data to remove plays where there was a fair catch\ndistance.control.sub <- subset(distance.injured.control, FairCatch != 1)\n\n# generates dataframe for plays when the returnman was injured\ndistances.list <- NULL\nfaircatch.list <- NULL\nPlayID.list <- NULL\nGameKey.list <- NULL\n\nfor (i in 1:34){\n  ngs.distance <- subset(ngs.TimeOfCatch, GamePlayKey == GamePlayKey.List[i])\n  x.return <- ngs.distance[ngs.distance$Role == 'PR', 'x'] \n  y.return <- ngs.distance[ngs.distance$Role == 'PR', 'y'] \n  player.distance <- NULL\n  \n  for (j in 1:11){\n    data <- subset(ngs.distance, Role != 'PR' & Off.Def == 0)\n    x.player <- data$x[j]\n    y.player <- data$y[j]\n    dis <- distance(x.player, x.return, y.player, y.return)\n    player.distance <- rbind(player.distance, dis)\n    faircatch <- ifelse(ngs.distance$Event[1] == 'fair_catch', 1, 0)\n    PlayID <- ngs.distance$PlayID[1]\n    GameKey <- ngs.distance$GameKey[1]\n  }\n  \n  faircatch.list <- rbind(faircatch.list, faircatch)\n  distances.list <- rbind(distances.list, min(player.distance))\n  PlayID.list <- rbind(PlayID.list, PlayID)\n  GameKey.list <- rbind(GameKey.list, GameKey)\n}\n\ndistance.injured <- data.table(GameKey.list, PlayID.list, distances.list, faircatch.list)\ncolnames(distance.injured) <- c('GameKey', 'PlayID', 'Distance', 'FairCatch')\n\n# plays where the returnman was injured\nreturner.plays <- subset(injuryinfo_role, Role == 'PR')\nreturner.distance <- merge(returner.plays, distance.injured, on = c('GameKey', 'PlayID', 'GSISID'))\n\ncat('The average distance of the closest defender on a punt where the returner was injured: ',mean(returner.distance$Distance))\ncat('\\nThe average distance of the closest defender on a punt with no injury: ', mean(distance.control.sub$Distance))\n\nreturner.distance <- returner.distance[c('GamePlayKey', 'Role', 'GSISID', 'Distance')]\nhead(returner.distance, 5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f5a452f97e1284f0aaa8ce95fab9e22fdd69e5e0"},"cell_type":"markdown","source":"\n***Speed at the Time of Impact:*** *One of the main goals of implementing this rule would be to reduce the speed at the time of impact. We looked at the speed of a tackler at the split second prior to making a tackle. Some noteworthy findings:*\n* *On the five plays where the returnman was injured, the average speed of the tackler at the time of impact was 13.538. The average speed at time of impact on tackling related injuries overall was 6.34, indicating that the larger high speed collissions are less likely on longer returns.*\n* *In the two most extreme instances (17.59 mph, 17.18 mph), the players were within 5 yards of the return man at the time of the punt being received. These players would not have been able to maintain this speed with the halo rule in place.*\n\n"},{"metadata":{"trusted":true,"_uuid":"4e48f6612166d92b80163bf78ef24c1c7965df0e"},"cell_type":"code","source":"# Looking at speed at time of impact\n# speed at time of impact is looks at a players instantaneous speed one tenth of a second prior to the tackling event\n\nlibrary(data.table)\n\nngs$speed <- (ngs$dis / .10) * 2.04545 # adds speed in mph\nngs.speed <- ngs[c('GameKey', 'PlayID', 'GSISID', 'speed', 'Time')]\ninjuryinfo.tackled <- subset(injuryinfo, Player_Activity_Derived == 'Tackled')\ninjuryinfo.tackled <- injuryinfo.tackled[c('GameKey', 'PlayID', 'Primary_Partner_GSISID')]\ncolnames(injuryinfo.tackled) <- c('GameKey', 'PlayID', 'GSISID')\n\ninjuryinfo.tackling <- subset(injuryinfo, Player_Activity_Derived == 'Tackling')\ninjuryinfo.tackling <- injuryinfo.tackling[c('GameKey', 'PlayID', 'GSISID')]\ntacklers <- rbind(injuryinfo.tackling, injuryinfo.tackled)\ntacklers$tackler <- 1\n\n# loop to generate speed at last instant before tackle is made\ntacklers.gamekey <- as.list(tacklers$GameKey)\ntacklers.play <- as.list(tacklers$PlayID)\ntacklers.gsisid <- as.list(tacklers$GSISID)\n\ntackle.speed <- NULL\n\nfor (i in 1:19){\n  sub <- subset(ngs, GameKey == tacklers.gamekey[i] & PlayID == tacklers.play[i] & GSISID == tacklers.gsisid[i])\n  tackle.index <- which(sub$Event == 'tackle')\n  impact <- tackle.index - 1\n  speed.impact <- sub$speed[impact]\n  tackle.speed <- rbind(tackle.speed, speed.impact)\n}\n\n# includes all injury plays where tackling information was available\ncat('Overall speed at time of impact (all tackling injuries): ', mean(tackle.speed))\n\n# looking at speed at time of impact where injury was to returner, can also be done as loop or function, but was done \n# manually due to small data sample\nlookup1 <- subset(ngs, GameKey == 189 & PlayID == 3509 & GSISID == 31950)\nlookup2 <- subset(ngs, GameKey == 266 & PlayID == 2902 & GSISID == 31844)\nlookup3 <- subset(ngs, GameKey == 399 & PlayID == 3312 & GSISID == 27442)\nlookup4 <- subset(ngs, GameKey == 506 & PlayID == 1988 & GSISID == 31209)\nlookup5 <- subset(ngs, GameKey == 585 & PlayID == 2208 & GSISID == 24535)\n\ncat('\\nOverall speed at time of impact (punt returner injuries): ', mean(return.impactspeed))\n\nreturn.impactspeed <- c(10.43, 17.59, 7.15, 17.18, 15.34)\ndata.table(returner.distance, return.impactspeed)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"642eed879a0fb142e0c80bf070599a3ef69f9839"},"cell_type":"markdown","source":"***Example:*** *Week 14 of the 2016 regular season, Eagles vs Redskins. Returner was concussed on punt return during the 4th quarter. On the play, the closest defender was .09 yards away at the time the ball was received, and was going 17.54 mph at the time of impact. The plot below shows a snap shot of where all players were at the time the punt was received, as well as the speed of the tackling player leading up to the time of impact. With the halo rule in place, the returner not only would have had time to defend himself, but the speed at time of impact would have decreased dramatically.*"},{"metadata":{"_uuid":"c20d419a6924e8cba39095cb44ada847cc087edf"},"cell_type":"markdown","source":"*A link to the play:* http://nfl-vod.cdn.anvato.net/league/5691/18/11/25/284956/284956_12D27120C06E4DB994040750FB43991D_181125_284956_way_punt_3200.mp4"},{"metadata":{"trusted":true,"_uuid":"2949dfcfabdf4ab4f5d55435e4f4742db68ac3e9"},"cell_type":"code","source":"library(zoo)\n\n# filtering data to include only data points between the ball being snapped, and the play ending\nngs <- arrange(ngs, Time)\nngs$speed <- (ngs$dis / .10) * 2.04545\nngs$DuringPlay <- ifelse(ngs$Event == 'ball_snap', 1, ifelse(ngs$Event == 'tackle', 0, \n                  ifelse(ngs$Event == 'fair_catch', 0, ifelse(ngs$Event == 'out_of_bounds', 0,\n                  ifelse(ngs$Event == 'punt_downed', 0, NA)))))\nend_play <- c('tackle', 'fair_catch', 'out_of_bounds', 'punt_downed')\n\nngs$DuringPlay[1] <- 0\n\nngs$DuringPlay <- na.locf(ngs$DuringPlay)\nngs$DuringPlay[ngs$Event %in% end_play] <- 1\nngs.duringplay <- arrange(subset(ngs, DuringPlay == 1 & speed < 25), Time)\n\n# snap shot of where players are at time ball is caught\nngs_halo <- subset(ngs, Event == \"punt_received\" | Event == \"punt_land\" | Event == \"kick_received\")\ninjuryinfo_pr <- subset(injuryinfo_role, Role == 'PR')\n\npr.list.game <- as.list(injuryinfo_pr$GameKey)\npr.list.play <- as.list(injuryinfo_pr$PlayID)\npr.list.player <- as.list(injuryinfo_pr$GameKey)\npr.list.primary <- as.list(injuryinfo_pr$GameKey)\n\n# data for plotting\nplot.halo <- subset(ngs_halo, GameKey == 266 & PlayID == 2902)\nplot.halo <- merge(plot.halo, playerrole, on  = c('Season_Year', 'GameKey', 'PlayId', 'GSISID'))\nplot.halo$Off.Def <- ifelse(plot.halo$Role %in% c('VR', 'VRo', 'VRi', 'PDR1', 'PDR2', 'PDR3', 'PDL3',\n                                                  'PDL2', 'PDL1', 'PLR', 'PLM', 'PLL', 'PFB', 'PR', 'VL'), 1, 0)\nplot_temp <- arrange(subset(ngs.duringplay, PlayID == 2902), Time)\nplot_temp <- subset(plot_temp, GSISID == 31844)\n\n# creates function for plotting of circle around return man\ngg_circle <- function(r, xc, yc, color=\"black\", fill=NA, ...) {\n  x <- xc + r*cos(seq(0, pi, length.out=100))\n  ymax <- yc + r*sin(seq(0, pi, length.out=100))\n  ymin <- yc + r*sin(seq(0, -pi, length.out=100))\n  annotate(\"ribbon\", x=x, ymin=ymin, ymax=ymax, color=color, fill=fill, ...)\n}\n\nggplot(aes(x = x, y = y, group = Off.Def), data = plot.halo) +\n  geom_line(data = plot_temp, aes(x, y, group = GSISID, color = speed), size = 2) +\n  scale_color_gradient2(low = 'blue', high = 'red', midpoint = 9, mid = '#FFCCCC') +\n  geom_vline(xintercept = 0, color = 'grey', size = 1.1) +\n  geom_vline(xintercept = 10, color = 'grey', size = 1.1) +\n  geom_vline(xintercept = 20, color = 'grey') +\n  geom_vline(xintercept = 30, color = 'grey') +\n  geom_vline(xintercept = 40, color = 'grey') +\n  geom_vline(xintercept = 50, color = 'grey') +\n  geom_vline(xintercept = 60, color = 'grey', size = 1.1) +\n  geom_vline(xintercept = 70, color = 'grey') +\n  geom_vline(xintercept = 80, color = 'grey') +\n  geom_vline(xintercept = 90, color = 'grey') +\n  geom_vline(xintercept = 100, color = 'grey') +\n  geom_vline(xintercept = 110, color = 'grey', size = 1.1) +\n  geom_vline(xintercept = 120, color = 'grey', size = 1.1) +\n  geom_hline(yintercept = 0, color = 'grey', size = 1.1) +\n  geom_hline(yintercept = 53, color = 'grey', size = 1.1) +\n  geom_point(color = 'dark gray') +\n  geom_point(x = 85.38, y = 12.29, color = 'red', size  = 3, shape = 17) +\n  gg_circle(r = 5, x= 85.38, y = 12.29) +\n  xlim(0,120) +\n  ylim(0,53) +\n  theme_minimal() +\n  theme(panel.grid = element_blank()) +\n  xlab(\"\") +\n  ylab(\"\") +\n  theme(axis.text = element_blank()) +\ncoord_fixed()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"058e48bb92e28f27ceed55e074126e87b2f82c16"},"cell_type":"markdown","source":"\n"},{"metadata":{"trusted":true,"_uuid":"0f42aeeb33e3e595c446cf4385e319a71813bb09"},"cell_type":"markdown","source":"***Decrease injury, increase excitement:*** *An important consideration when evaluating potential rule changes is how it would effect the quality of the game. With the implementation of the 'halo' rule, it is likely the NFL would see an increase in punt returns, while also seeing a decrease in dangerous punt related plays. A fair catch is called for on 42% of punts where a there is a defender within 5 yards of the returner at the time he is receiving the punt, versus a fair catch being called for 8% of the time where a defender is outside of the 5 yard circle. This indicates a few things:*\n* *This first number should likely be higher, but fielding a punt while also trying to spot where all of the defenders are is both difficult and dangerous. This would theoretically be reduced.*\n* *Adding the halo rule would likely increase the instances where the closest defender is between 5-10 yards, a fair catch is called for on 14% of these instances. This indicates that there would be a drastic increase in the number of returns, upwards of 25%, though the actual number is nearly impossible to quantify*\n"},{"metadata":{"trusted":true,"_uuid":"e1bd6b357dd4ad058cd857e27d471dea72a009aa"},"cell_type":"code","source":"# fair catch analysis\n\nfaircatch <- rbind(distance.injured, distance.injured.control)\n\nfaircatch.inside <- subset(faircatch, Distance <= 5)\nfaircatch.outside <- subset(faircatch, Distance > 5)\nfaircatch.middle <- subset(faircatch, Distance > 5 & Distance < 10)\n\ninside.five <- sum(faircatch.inside$FairCatch) / nrow(faircatch.inside)\noutside.five <- sum(faircatch.outside$FairCatch) / nrow(faircatch.outside)\nfive.ten <- sum(faircatch.middle$FairCatch) / nrow(faircatch.middle)\n\ncat('Percentage of fair catches where defender is within 5 yards: ', inside.five)\ncat('\\nPercentage of fair catches where defender is outside 5 yards: ', outside.five)\ncat('\\nPercentage of fair catches where defender is between 5 and 10 yards: ', five.ten)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"62804055acf3e53d58a5fb8aa8bfe48bbe82e156"},"cell_type":"markdown","source":"***Final Conclusions:*** \n* *Plays where players are closer to the returner at the time he catches the punt are, all else equal, more dangerous. The base of this rule change would be to eliminate the instances where a returner does not even have time to react and defend himself after receiving a punt by requiring space between the returner and defenders.*\n* *Injuries to the returner generally result from high speed colisions. In a lot of instances, defenders wll be forced to slow down in order to avoid the restricted area, reducing their speed at the time of impact. Longer returns also generally result in lower impact tackles as players are usually taking angles, or breaking down to attempt form tackles, and cannot line up the returnman*\n* *Also of importance, the rule change would not reduce the number of exciting plays. It is actually likely to increase the amount of punt returns overall, and potentially increase the number of long punt returns.*\n"},{"metadata":{"_uuid":"ce87b1f9b733451ca0b3337e4c5266c63b955285"},"cell_type":"markdown","source":""}],"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}