Here the loaded data is merged and sorted. This code chunk is perhaps the most important of them all; in qbSneakmerge_2022
, the mutate()
function singles out which plays are a standard QB sneak and which are a tush push.
While some standard qb sneaks feature numerous offense in the backfield (that is, behind the qb), that is a feature that is necessary for a play to be considered a tush push. Additionally, a great number of defense in the box indicates players are lined up against each other (instead of some defense players waiting down the field to stop a long pass or run situation), and certain whole team formations are more common with the tush push than the qb sneak. This is why I have chosen these variables to single out the tush pushes from the standard sneaks.
qbSneakmerge_2022 <- nflplays_2022 %>%
filter(qbSneak == TRUE) %>%
left_join(ftncharting_2022, by = c("playId" = "nflverse_play_id"), relationship = "many-to-many") %>%
distinct(playDescription, .keep_all = TRUE) %>%
mutate(
tushPush = qbSneak &
n_offense_backfield > 1 &
n_defense_box >= n_offense_backfield &
offenseFormation %in% c("I_FORM", "JUMBO", "SINGLEBACK", "WILDCAT")
) %>%
select(where(~ any(!is.na(.) & . != FALSE)))
# ensure when re-merging data that there are no duplicates
nflplays_2022_dedup <- nflplays_2022 %>%
distinct(playDescription, .keep_all = TRUE)
nflPlaysStatus_2022 <- nflplays_2022_dedup %>%
left_join(
qbSneakmerge_2022 %>% select(playDescription, sneak_flag = qbSneak, tushPush, n_offense_backfield, n_defense_box, is_motion, n_blitzers, n_pass_rushers),
by = "playDescription"
) %>%
mutate(
qbSneak_clean = coalesce(sneak_flag, qbSneak, FALSE),
qbSneak_status = case_when(
qbSneak_clean == FALSE ~ "Non-QB Sneak",
tushPush == TRUE ~ "Tush Push",
TRUE ~ "Standard QB Sneak"
),
) %>% select(-sneak_flag)
# sneak factor label
nflPlaysStatus_2022 <- nflPlaysStatus_2022 %>%
mutate(play_lbl = factor(qbSneak_status, levels = c("Standard QB Sneak", "Tush Push")))