Introduction

This project aims to identify the best kickers in feature games from the 2020-21 season by analyzing their performance under pressure. By evaluating both the success rate and the difficulty of each kick, a “wow factor” score was developed to quantify the level of challenge a kicker faced. This score takes into account two key factors: the distance of the kick and the time left in the game, where more difficult kicks under higher pressure situations yield a higher score. Using this method, the program ranks the top kickers based on their wow factor, filtering only those with a success rate of 92% or higher.

Description of Project

To determine the best kickers, I began by collecting data on every attempted field goal during the 2020-21 season. The data includes the kick’s length in yards, the remaining time in the game, and whether the attempt was successful. Kicks were assigned a score based on two criteria: the distance of the kick and the pressure based on the remaining game time. Short kicks and kicks taken early in the game received a low score, while longer kicks or kicks made with little time left on the clock scored higher.

Here’s how the scoring worked:

Kick Length: Kicks were categorized into bins, with scores ranging from 0 for a kick of 33 yards or less, to 4 for kicks over 63 yards. Time Left: A similar approach was used to categorize game pressure based on time left, where kicks in the last 10 seconds of the game earned the highest score. Each player’s kicks were summed up to calculate their overall wow factor score. Finally, only kickers with a success rate of 92% or above were filtered to identify the best performers based on their ability to make difficult kicks under pressure.

Data Visualization

The visualizations created for this project highlight the distribution of wow factor scores across kickers. A bar chart displays the total wow factor for each kicker with a success rate of 92% or above, emphasizing those who consistently performed under pressure. Another plot shows the total wow factor for the players in the top 25% scores. The colors for bothe charts are the players’ team colors.

setwd("C:/Users/Amelia/OneDrive/School/Semester 5/IS 470")

suppressMessages(library(data.table))
suppressMessages(library(dplyr))
suppressMessages(library(lubridate))
suppressMessages(library(httr))
suppressMessages(library(DescTools))
suppressMessages(library(scales))
suppressMessages(library(ggplot2))

plays = fread("Data/NFLBDB2022/NFL2022/plays.csv")
players <- fread("Data/NFLBDB2022/NFL2022/players.csv")
pff <- fread("Data/NFLBDB2022/NFL2022/PFFScoutingData.csv")
games <- fread("Data/NFLBDB2022/NFL2022/games.csv")

df <- games %>%
  left_join(plays, by = c("gameId")) %>%
  left_join(players, by = c("kickerId" = "nflId")) %>%
  left_join(pff, by = c("gameId","playId"))
rm(players)
rm(games) 
rm(plays)
rm(pff)
df <- df[!is.na(df$displayName)]

# create a data frame that has all of the kicks 
kicks <- df%>%
  filter(specialTeamsPlayType %in% c("Field Goal", "Extra Point")) %>%
  mutate(kickLength = ifelse(specialTeamsPlayType == "Extra Point", 33, kickLength),
         success = ifelse(specialTeamsResult == "Kick Attempt Good", 1, 0),
         seconds = as.numeric(substring(gameClock, 4, 5)) + (
                   as.numeric(substring(gameClock, 1, 2))*60),
         timeLeft = seconds_to_period(case_when(
           quarter == 1 ~ seconds + 2700,
           quarter == 2 ~ seconds + 1800,
           quarter == 3 ~ seconds + 900, 
           quarter == 4 ~ seconds)),
         distance = case_when(
           kickLength <= 33 ~ "15 yard line or below",
           kickLength <= 43 ~ "16 to 25 yard line",
           kickLength <= 53 ~ "26 to 35 yard line",
           kickLength <= 63 ~ "36 to 45 yard line",
           kickLength > 63 ~ "46 yard line and beyond",
           TRUE ~ "other")) %>%
  select(displayName, success, timeLeft, kickLength, distance) %>%
  arrange(displayName, -success)%>%
  data.frame()    

# df to see the amount of kicks each player made
most_made <- kicks %>% 
  filter(success == 1) %>%
  select(displayName)%>% 
  group_by(displayName) %>%
  summarise(made_kicks = n(), .groups = "keep")%>%
  data.frame()

# df of each players success rate
percentage <- kicks %>% 
  select(displayName, success)%>%
  group_by(displayName) %>%
  mutate(num_kicks = n())%>%
  filter(success == 1) %>%
  mutate(total_successes= n(),
         success_rate = round((total_successes/num_kicks), digits = 2)*100)%>%
  reframe(success_rate = max(success_rate))%>%
  group_by(displayName) %>%
  data.frame()

# df that adds a score variable for "wow factor" (distance of the kick and time left in game)
by_difficulty <- kicks %>%
  filter(success == 1) %>%
  mutate(dist_rate = case_when(
           kickLength <= 33 ~ 0,
           kickLength <= 43 ~ 1,
           kickLength <= 53 ~ 2,
           kickLength <= 63 ~ 3,
           kickLength > 63 ~4,
           TRUE ~ 0),
         time_rate = case_when(
           timeLeft > 1800 ~ 0,
           timeLeft > 900 ~ 1,
           timeLeft > 450 ~ 2,
           timeLeft > 225 ~ 3,
           timeLeft > 60 ~ 4,
           timeLeft > 10 ~ 5,
           timeLeft >= 0 ~ 6,
           TRUE ~ 0),
         score = dist_rate + time_rate) %>%
  group_by(displayName) %>%
  summarise(totalScore = sum(score), .groups = "keep")%>%
  select(displayName, totalScore) %>%
  arrange(-totalScore)%>%
  data.frame()

# combine the score df and percentage df to find the scores of player with high success rates
df1 <- by_difficulty %>%
  left_join(percentage, by = "displayName")%>%
  filter(success_rate >= 92)%>%
  data.frame()
team_colors <- c("slateblue","lightgoldenrod3","darkgreen", "turquoise","turquoise4", "firebrick","blue3","red3","gold","firebrick1","turquoise4","royalblue")

Visualization 1: A graph that shows Wow Factor Scores of Players with a success rate above 91%.

# horizontal bar chart

ggplot(data = df1, aes(x = reorder(displayName, totalScore), y = totalScore)) +
  geom_bar(stat = "identity", fill = team_colors)+
  labs(x = "Player", y = "Overall Wow Factor Score",
       title = "Wow Factor Scores of Players", size = 200,
       fill = "team color")+
  theme(axis.text=element_text(size=20),
        axis.title=element_text(size=30,face="bold"),
        title=element_text(size=30,face="bold"))+
  coord_flip()+
  geom_text(aes(label = (totalScore)), hjust = -.05, size = 5)


Visualization 2: A graph that shows Players in the Top 15% of Wow Factor Scores

# finding who has the highest scores
df2 <- by_difficulty %>%
  left_join(percentage, by = "displayName")%>%
  filter(totalScore >= 230)%>%
  data.frame()
teams <- c(df2$possessionTeam)
team_colors <- c("slateblue","lightgoldenrod3","chartreuse3","firebrick", "firebrick1","seagreen","darkgreen", "orange2","blue4")

# horizontal bar chart
ggplot(data = df2, aes(x = reorder(displayName, -totalScore), y = totalScore)) +
  geom_bar(stat = "identity", fill = team_colors)+
  labs(x = "Player", y = "Overall Wow Factor Score",
       title = "Players in the Top 15% of Wow Factor Scores")+
  theme(axis.text=element_text(size=20),
        axis.title=element_text(size=30,face="bold"),
        title=element_text(size=30,face="bold"))+
  coord_flip()+
  geom_text(aes(label = (totalScore)), hjust = -.05, size = 5)


Conclusion

  1. Pressure Kicking Matters: Kicks made under high-pressure situations (i.e., late in the game or from long distances) contribute significantly to what makes a kicker good. This measure helped highlight kickers who consistently performed under difficult conditions.

  2. Success Rate vs. Wow Factor: While a high success rate is essential, combining it with a wow factor score provided a more nuanced view of a kicker’s overall impact. Looking at the players Johnny Hekker and Brandon Wright, their success rates are high but they don’t make any kicks under high pressure. Kickers with a high wow factor and a success rate over 92% stood out as the most reliable and impressive performers.

  3. Differentiating Top Kickers: Adding the wow factor revealed that even though some players had really great kicking rates, they were mostly for low stakes kicks. Players with high success rates and wow factors not only excelled in routine kicks but also demonstrated the ability to handle high-stakes situations, making them invaluable to their teams.

If you have any questions, please feel free to email me at abademosi@loyola.edu