Super Bowl LVIII

Para el análisis de este Super Bowl 58, se usará la librería de nflfastR para recopilar los datos de Play-by-Play de la NFL. En este análisis se buscará determinar estadísticas de los jugadores, se buscará determinar el ganador del Super Bowl y el marcador. Todo esto será utilizando modelos de Machine Learning. Esto es con el objetivo de apostar un total de $200 pesos. La mitad será utilizado en la plataforma Bet365 y la otra mitad en Caliente.

Comparando ambos equipos

EPA/jugada Ofensiva y Defensiva en el 2023

ggplot(combined, aes(x = off_epa, y = def_epa)) +
  geom_abline(slope = -1.5, intercept = seq(0.4, -0.3, -0.1), alpha = .2) +
  geom_mean_lines(aes(x0 = off_epa , y0 = def_epa)) +
  geom_nfl_logos(aes(team_abbr = team), width = 0.065, alpha = 0.7) +
  labs(
    x = "EPA/jugada Ofensiva",
    y = "EPA/jugada Defensiva",
    caption = "Datos: @nflfastR",
    title = "EPA/jugada Ofensiva y Defensiva en el 2023"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold"),
    plot.title.position = "plot"
  ) +
  scale_y_reverse()

Ofensiva Terrestre

po_kc_rush <- 
  postseason %>% 
  filter(posteam == "KC") %>% 
  group_by(week) %>% 
  summarise(rush_pct_kc = sum(play_type == "run") / (sum(play_type == "run") + sum(play_type == "pass"))) %>% 
  arrange(desc(week))


po_sf_rush <- 
  postseason %>% 
  filter(posteam == "SF") %>% 
  group_by(week) %>% 
  summarise(rush_pct_sf = sum(play_type == "run") / (sum(play_type == "run") + sum(play_type == "pass"))) %>% 
  arrange(desc(week))

sf_vs_kc_rpct <- left_join(po_kc_rush,po_sf_rush)
## Joining with `by = join_by(week)`
sf_vs_kc_rpct
## # A tibble: 3 × 3
##    week rush_pct_kc rush_pct_sf
##   <int>       <dbl>       <dbl>
## 1    21       0.414       0.484
## 2    20       0.465       0.371
## 3    19       0.453      NA
ggplot(sf_vs_kc_rpct, aes(x = week)) +
  geom_line(aes(y = rush_pct_kc), color = "red") +
  geom_line(aes(y = rush_pct_sf), color = "gold") +
  labs(
    x = "Semana",
    y = "Rushing EPA per Play",
    caption = "Datos: @nflfastR",
    title = "%Acarreos en los Playoffs"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold"),
    plot.title.position = "plot"
  ) +
  scale_y_continuous(
    name = "Rushing EPA per Play",
    sec.axis = sec_axis(trans = ~ ., name = "Some Other Variable")
  )
## Warning: Removed 1 row containing missing values (`geom_line()`).

po_kc_rush_2h <- 
  postseason %>% 
  filter(posteam == "KC") %>% 
  filter(game_half=="Half2") %>%
  group_by(week) %>% 
  summarise(rush_pct_kc_h2 = sum(play_type == "run") / (sum(play_type == "run") + sum(play_type == "pass"))) %>% 
  arrange(desc(week))


po_sf_rush_2h <- 
  postseason %>% 
  filter(posteam == "SF") %>% 
  filter(game_half=="Half2") %>%
  group_by(week) %>% 
  summarise(rush_pct_sf_h2 = sum(play_type == "run") / (sum(play_type == "run") + sum(play_type == "pass"))) %>% 
  arrange(desc(week))

po_kc_rush_1h <- 
  postseason %>% 
  filter(posteam == "KC") %>% 
  filter(game_half=="Half1") %>%
  group_by(week) %>% 
  summarise(rush_pct_kc_h1 = sum(play_type == "run") / (sum(play_type == "run") + sum(play_type == "pass"))) %>% 
  arrange(desc(week))


po_sf_rush_1h <- 
  postseason %>% 
  filter(posteam == "SF") %>% 
  filter(game_half=="Half1") %>%
  group_by(week) %>% 
  summarise(rush_pct_sf_h1 = sum(play_type == "run") / (sum(play_type == "run") + sum(play_type == "pass"))) %>% 
  arrange(desc(week))

sf_vs_kc_rpct_h1vh2 <- left_join(po_kc_rush_1h, po_kc_rush_2h, by = "week") %>%
                      left_join(po_sf_rush_1h, by = "week") %>%
                      left_join(po_sf_rush_2h, by = "week")
sf_vs_kc_rpct_h1vh2
## # A tibble: 3 × 5
##    week rush_pct_kc_h1 rush_pct_kc_h2 rush_pct_sf_h1 rush_pct_sf_h2
##   <int>          <dbl>          <dbl>          <dbl>          <dbl>
## 1    21          0.419          0.407          0.444          0.514
## 2    20          0.35           0.565          0.385          0.361
## 3    19          0.366          0.559         NA             NA

Aquí podemos observar algo sumamente interesante de la estrategia de ambos equipos. Empecemos con San Francsico, en la primera mitad de su partido contra Green Bay (Semana 20), corrieron un 38% de las jugadas, mientras que en la segunda mitad corrieron un 36% de las veces. Ese ha sido el partido en el que han estado más cerca de perder y de una manera muy convincente. Después, en el partido contra Detroit (Semana 21), aunque estuvieran perdiendo 24-7, la ofensiva de San Francisco corrió el 51% de las veces. Parece contraintuitivo, pero por las tendencias de pase de Purdy tiene mucho sentido. A continuación, el mapa de calor de Brock Purdy.

Lo que sucede es que Purdy busca mucho el Checkdown dentro de las 5 yardas al lado derecho del campo. También, busca mucho el flat izquierdo, también un checkdown. El juego terrestre ayuda a que Purdy pase mejor el balón. Otro punto interesante es que, Purdy creó muchas oportunidades al correr cuando eran situaciones de pase.

Ahora, hablaremos de como Kansas City ha utilizado el juego terrestre. En la temporada regular, KC no era el equipo que corría el balón tanto como lo hemos visto en la postemporada. Según PFF, los Chiefs corrían el balón 32.3% de las veces, esto siendo el #28 en la liga. Sin embargo, eran de los equipos más eficientes corriendo el balón. En yardas por acarreo tenían 4.4, esto siendo #8 en la liga. Tenían la séptima ofensiva terrestre más explosiva en la liga ya que 13.9% de sus acarreos eran explosivos. Y corrían excelente entre los Tackles, ya que las yardas antes del contacto en inside zone eran 2.0 Yardas. Esto significa que sus corredores ganaban en promedio 2 yardas antes de ser tocados.

Los Chiefs en los últimos partidos de postemporada no solamente han corrido más, sino que corren más cuando van perdiendo o el partido está cerrado.

epa_kc_rush_2h <- 
  postseason %>% 
  filter(posteam == "KC") %>% 
  filter(game_half=="Half2") %>%
  filter(play_type =="run") %>%
  group_by(week) %>% 
  summarise(rush_epa_kc_h2 = mean(epa)) %>% 
  arrange(desc(week))


epa_sf_rush_2h <- 
  postseason %>% 
  filter(posteam == "SF") %>% 
  filter(game_half=="Half2") %>%
  filter(play_type =="run") %>%
  group_by(week) %>% 
  summarise(rush_epa_sf_h2 = mean(epa)) %>% 
  arrange(desc(week))

epa_kc_rush_1h <- 
  postseason %>% 
  filter(posteam == "KC") %>% 
  filter(game_half=="Half1") %>%
  filter(play_type =="run") %>%
  group_by(week) %>% 
  summarise(rush_epa_kc_h1 = mean(epa)) %>% 
  arrange(desc(week))


epa_sf_rush_1h <- 
  postseason %>% 
  filter(posteam == "SF") %>% 
  filter(game_half=="Half1") %>%
  filter(play_type =="run") %>%
  group_by(week) %>% 
  summarise(rush_epa_sf_h1 = mean(epa)) %>% 
  arrange(desc(week))

sf_vs_kc_repa_h1vh2 <- left_join(epa_kc_rush_1h, epa_kc_rush_2h, by = "week") %>%
                      left_join(epa_sf_rush_1h, by = "week") %>%
                      left_join(epa_sf_rush_2h, by = "week")
sf_vs_kc_repa_h1vh2
## # A tibble: 3 × 5
##    week rush_epa_kc_h1 rush_epa_kc_h2 rush_epa_sf_h1 rush_epa_sf_h2
##   <int>          <dbl>          <dbl>          <dbl>          <dbl>
## 1    21        -0.113          -0.347      0.105              0.324
## 2    20         0.251           0.113     -0.0000918          0.253
## 3    19         0.0877         -0.293     NA                 NA
sf_vs_kc_rpct_h1vh2
## # A tibble: 3 × 5
##    week rush_pct_kc_h1 rush_pct_kc_h2 rush_pct_sf_h1 rush_pct_sf_h2
##   <int>          <dbl>          <dbl>          <dbl>          <dbl>
## 1    21          0.419          0.407          0.444          0.514
## 2    20          0.35           0.565          0.385          0.361
## 3    19          0.366          0.559         NA             NA

En estas últimas tablas, vemos tanto la eficiencia como el porcentaje de acarreos que tienen los equipos en cada mitad de sus partidos.

Algo que podemos ver es que los Chiefs, a pesar de que corren el balón más en la segunda mitad de los partidos, su eficiencia se ve afectada negativamente. Puede ser porque los equipos ya esperan que corran en la segunda mitad. Sin embargo, esto puede mejorar su eficiencia de pase. Ya que si mantienen a los Linebackers del equipo contrario cerca de la linea de golpeo, esto puede abrir oportunidades de pase y mejorar el espaciado en la defensiva.

Una cosa que destaca de los 49ers es que aunque corren menos en la segunda mitad, son mucho más eficientes que los Chiefs. Esto se puede atribuir a 2 cosas. La primera es simplemente Christian McCaffrey y como los 49ers han bloqueado, tanto los WRs como la OL. La segunda es que en la segunda mitad de su partido contra Detroit, Brock Purdy escapó de la bolsa varias veces avanzando grandes porciones del campo.

Juego Terrestre vs. Juego Aéreo

sbpass <- postseason %>%
  filter(posteam %in% c("KC", "SF"), play_type == "pass") %>%
  group_by(team = posteam) %>%
  summarise(pass_epa = mean(epa, na.rm = TRUE))


sbrush <- postseason %>%
  filter(posteam %in% c("KC", "SF"), play_type == "run") %>%
  group_by(team = posteam) %>%
  summarise(rush_epa = mean(epa, na.rm = TRUE))

sbcombined <- sbpass %>%
  inner_join(sbrush, by = "team")

ggplot(sbcombined, aes(x = pass_epa, y = rush_epa)) +
  geom_abline(slope = -1.5, intercept = seq(0.4, -0.3, -0.1), alpha = .2) +
  geom_mean_lines(aes(x0 = pass_epa , y0 = rush_epa)) +
  geom_nfl_logos(aes(team_abbr = team), width = 0.065, alpha = 0.7) +
  labs(
    x = "EPA/Pase",
    y = "EPA/Carrera",
    caption = "Datos: @nflfastR",
    title = "EPA/Pase y Carrera en Playoffs"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold"),
    plot.title.position = "plot"
  ) 

Ofensiva vs. Defensiva en Playoffs

postoffense <- postseason %>%
  group_by(team = posteam) %>%
  summarise(off_epa = mean(epa, na.rm = TRUE))

postdefense <- postseason %>%
  group_by(team = defteam) %>%
  summarise(def_epa = mean(epa, na.rm = TRUE))

postcombined <- postoffense %>%
  inner_join(postdefense, by = "team")

ggplot(postcombined, aes(x = off_epa, y = def_epa)) +
  geom_abline(slope = -1.5, intercept = seq(0.4, -0.3, -0.1), alpha = .2) +
  geom_mean_lines(aes(x0 = off_epa , y0 = def_epa)) +
  geom_nfl_logos(aes(team_abbr = team), width = 0.065, alpha = 0.7) +
  labs(
    x = "EPA/jugada Ofensiva",
    y = "EPA/jugada Defensiva",
    caption = "Datos: @nflfastR",
    title = "EPA/jugada Ofensiva y Defensiva en Playoffs"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold"),
    plot.title.position = "plot"
  ) +
  scale_y_reverse()

Ofensiva Terrestre

rush_pacheco <- 
  pbp %>% 
  filter(rusher_player_name == "I.Pacheco") %>% 
  group_by(week) %>% 
  summarise(rushing_epa = mean(epa), rushing_plays=n()) %>% 
  arrange(desc(week))
rush_pacheco
## # A tibble: 17 × 3
##     week rushing_epa rushing_plays
##    <int>       <dbl>         <int>
##  1    21     -0.330             24
##  2    20      0.110             15
##  3    19     -0.173             24
##  4    17      0.0836            18
##  5    16     -0.956             11
##  6    13      0.210             19
##  7    12      0.181             15
##  8    11      0.0400            19
##  9     9     -0.0227            16
## 10     8     -0.0275             8
## 11     7     -0.316             13
## 12     6     -0.168             16
## 13     5     -0.153             16
## 14     4      0.108             20
## 15     3      0.162             15
## 16     2      0.282             12
## 17     1     -0.167              8
ggplot(rush_pacheco, aes(x = week, y = rushing_epa)) +
  geom_line() +
  labs(
    x = "Semana",
    y = "Rushing EPA per Play",
    caption = "Datos: @nflfastR",
    title = "Rushing EPA de Isiah Pacheco en el 2023"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold"),
    plot.title.position = "plot"
  )

bet365

Vamos a hablar de cada apuesta individualmente.

Anytime TD de Christian McCaffrey. Ha sido la apuesta más confiable de toda la temporada y el juego terrestre de CMC ha sido la identidad ofensiva de este equipo.

Chiefs ML. La tendencia estos playoffs ha sido que el QB más clutch con la mejor defensiva ha ganado los partidos. Darle a Mahomes la mejor defensiva en los Playoffs, un Kelce rejuvenecido, y un juego terrestre existente es una gran formula para ganar.

Patrick Mahomes 200+ Yardas por pase. El perímetro de SF se ha visto afectado en estos últimos partidos de Playoffs, se notaron más las debilidades del perímetro contra Green Bay donde jugaron de manera pasiva y permitieron que WRs jóvenes ganaran sus enfrentamientos.

Isiah Pacheco 15+ intentos de carrera. En los últimos partidos de Playoffs, Pacheco ha promediado 21 carreras por partido. Puede que no sean todas eficientes, pero ha sido una parte vital de esta ofensiva en la postemporada.

Fred Warner 6+ Tackleadas y asistencias. Misma lógica que con Pacheco, los Chiefs están corriendo más lo cual significa que corren hacia el interior de la defensiva. Súmale que los Chiefs han tenido la ofensiva menos explosiva en los últimos años, lo cual permite más pases cortos, perfectos para Warner.

Más de 44.5 puntos. Caliente tiene la línea en 47.5 puntos y por como han actuado ambas ofensivas, esto parece ser un over.

En este segundo ticket cambiamos unas cosas.

Brock Purdy 1+ Intercepciones. Aunque ha sido “algo” seguro con el balón esta postemporada, a diferencia del perímetro de los Leones, estos CBs de los Chiefs no tiran intercepciones. Súmale que la defensiva de Steve Spagnuolo va a disfrazar varias coberturas, esto va a perjudicar a Purdy extremadamente. Él procesa mucho mejor antes de la jugada que después de la jugada.

Travis Kelce 5+ Recepciones. En los últimos 6/7 partidos, Kelce ha obtenido más de 5 Recepciones. Su uso en la postemporada indica que va en una tendencia positiva de acuerdo a una regresión lineal.