Load Packages

library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.4.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(nflreadr)
library(DT)
## Warning: package 'DT' was built under R version 4.4.3

Load Play-by-Play Data

pbp_2021 <- load_pbp(2021:2024)
pbp_2023 <- load_pbp(2023:2024)

Get All Quarterbacks

roster <- load_rosters(2020:2024)

real_qbs_id <- roster %>%
  filter(position == "QB") %>%
  distinct(gsis_id)
qb_id <- real_qbs_id$gsis_id

Create compare_qbs Function

compare_qbs <- function(pbp_data, team_abbr, starter_name) {

  starter <- pbp_data %>%
    filter(posteam == team_abbr,
           passer_player_id %in% qb_id,
           passer_player_name == starter_name) %>%
    group_by(posteam) %>%
    summarize(
      s_db = n(),
      s_mean_epa = round(mean(epa, na.rm = TRUE), 3),
      s_suc_rate = round(mean(success == 1, na.rm = TRUE), 3)
    )

  others <- pbp_data %>%
    filter(posteam == team_abbr,
           passer_player_id %in% qb_id,
           passer_player_name != starter_name) %>%
    group_by(posteam) %>%
    summarize(
      o_db = n(),
      o_mean_epa = round(mean(epa, na.rm = TRUE), 3),
      o_suc_rate = round(mean(success == 1, na.rm = TRUE), 3)
    )

  combined <- starter %>%
    left_join(others, by = "posteam") %>%
    mutate(Starter = starter_name, 
           epa_diff = s_mean_epa - o_mean_epa,
           suc_diff = round(s_suc_rate - o_suc_rate, 3)) %>%
    rename(Team = posteam) %>%
    select(Starter, Team, everything())
  
  return(combined)
}