Intro

This report is intended to present RB’s and QB’s player statistics using visualizations. All data used in this project is from nflscrapR, which can be found here: https://github.com/ryurko/nflscrapR-data

Expected points added is used often in this report. More information on EPA can be found here: http://www.advancedfootballanalytics.com/index.php/home/stats/stats-explained/expected-points-and-epa-explained

Loading required packages and importing 2018 play-by-play data

#install.packages("tidyverse")
library(tidyverse)
theme_set(theme_bw())

pbp_18 <- readr::read_csv("https://raw.githubusercontent.com/ryurko/nflscrapR-data/master/play_by_play_data/regular_season/reg_pbp_2018.csv")

Running backs

Creating the dataset for running backs in 2018

min_rush_cnt <- 160

rushing <- pbp_18 %>% 
  filter(rush_attempt == 1, !is.na(rusher_player_name),!is.na(epa))%>% 
  group_by(rusher_player_name) %>% 
  summarise(Rush_Attempts= n(),
            Total_Yards = sum(yards_gained),
            Touchdowns = sum(touchdown),
            Average_Yards = round(mean(yards_gained),2),
            Average_EPA = round(mean(epa),2)) %>% 
  filter(Rush_Attempts >= min_rush_cnt)  %>% 
  arrange(desc(Rush_Attempts)) %>% 
  rename(Player = rusher_player_name) 


#Ordered by number of rush attempts
Player Rush_Attempts Total_Yards Touchdowns Average_Yards Average_EPA
E.Elliott 304 1434 6 4.72 0.03
D.Johnson 300 1145 7 3.82 -0.13
S.Barkley 263 1309 11 4.98 -0.01
T.Gurley 260 1255 17 4.83 0.15
A.Peterson 251 1042 7 4.15 -0.06
J.Howard 250 935 9 3.74 -0.07
C.Carson 247 1151 9 4.66 0.04
J.Mixon 237 1168 8 4.93 -0.01
P.Barber 234 871 5 3.72 -0.13
C.McCaffrey 219 1098 7 5.01 0.04
D.Henry 215 1059 12 4.93 0.08
J.Conner 215 973 12 4.53 0.04
L.Miller 210 973 5 4.63 -0.02
S.Michel 209 931 6 4.45 0.02
A.Kamara 197 889 14 4.51 0.13
M.Mack 197 912 9 4.63 0.08
P.Lindsay 193 1037 9 5.37 0.07
N.Chubb 192 996 8 5.19 0.01
K.Hunt 181 824 7 4.55 0.04
M.Gordon 176 887 10 5.04 0.08
C.Hyde 172 571 5 3.32 -0.18
D.Martin 172 723 4 4.20 -0.10
T.Coleman 167 800 4 4.79 -0.03
L.McCoy 161 514 3 3.19 -0.18

In 2018, 24 RBs had over 160 rush attempts.Ezekiel Elliot and Saquon Barkley rushed for 1434 and 1309 yards to top the group.

 rushing %>% 
  ggplot(aes(Rush_Attempts,Average_Yards,alpha = Touchdowns)) +
  geom_point() +
  labs(title ="Average yards per run by running backs in 2018",
       subtitle = "160 Rush Attempt Minimum ",
       x = "2018 Rush Attempts",
       y = "Average Yards Per Run",
       caption= "Data from nflscrapR") +
  guides(fill = guide_legend(reverse=FALSE))+
  scale_fill_discrete(name = "Touchdown")+
  geom_text(aes(label = Player), vjust = 1, hjust = 1, check_overlap = TRUE) 

Todd Gurley led all RBs with 17 touchdowns. Phillip Lindsay, Nick Chubb,Christian McCaffery and Melvin Gordon all hovered over a 5 yard per run average.

 rushing %>% 
  ggplot(aes(Rush_Attempts,Average_EPA)) +
  geom_point() +
  labs(title ="Average expected points added per run by running backs in 2018",
       subtitle = "160 Rush Attempt Minimum ",
       x = "2018 Rush Attempts",
       y = "Average EPA Per Run",
       caption= "Data from nflscrapR") +
  geom_text(aes(label = Player), vjust = 1, hjust = 1, check_overlap = FALSE) 

Todd Gurley and Alvin Kamara lead the pack with 0.153 and 0.126 expected points added per run respectively.

Highest EPA per run attempt

rushing %>% 
  select(Player,Average_EPA) %>% 
  arrange(desc(Average_EPA))%>% 
  head(10) %>% 
  knitr::kable()
Player Average_EPA
T.Gurley 0.15
A.Kamara 0.13
D.Henry 0.08
M.Mack 0.08
M.Gordon 0.08
P.Lindsay 0.07
C.Carson 0.04
C.McCaffrey 0.04
J.Conner 0.04
K.Hunt 0.04

Lowest EPA per run attempt

rushing %>% 
  select(Player,Average_EPA) %>% 
  arrange(Average_EPA)%>% 
  head(10) %>% 
  knitr::kable()
Player Average_EPA
C.Hyde -0.18
L.McCoy -0.18
D.Johnson -0.13
P.Barber -0.13
D.Martin -0.10
J.Howard -0.07
A.Peterson -0.06
T.Coleman -0.03
L.Miller -0.02
S.Barkley -0.01

Quarterbacks

Creating the dataset for 2018 Quarterbacks

passingepa <- pbp_18  %>% 
  filter( !is.na(air_yards), !is.na(epa),qb_dropback == 1) %>% 
  group_by(passer_player_name) %>% 
  summarise(Avg_AirYards= round(mean(air_yards),2),
            Avg_EPA = round(mean(epa),2),
            Touchdowns = sum(touchdown),
            Total_Dropbacks = n()) %>% 
  filter(Total_Dropbacks >= 300) %>% 
  arrange(desc(Avg_AirYards)) %>% 
  rename(Player = passer_player_name)

Air yards is the distance the ball is thrown past the line of scrimmage

passingepa %>% 
  ggplot(aes(Total_Dropbacks,Avg_AirYards)) +
  geom_point() +
  geom_text(aes(label = Player, vjust = 1, hjust = 1, check_overlap = FALSE)) +
  labs(title = 'Average Air Yards by Quarterbacks in 2018',
       subtitle = "300 Droback Minimum",
       x = 'Total QB Dropbacks',
       y = 'Average Airyards per Dropback ',
       caption = 'Data from nflscrapR')

Highest air yards average

passingepa  %>% 
  arrange(desc(Avg_AirYards))%>% 
  head(10) %>% 
  knitr::kable()
Player Avg_AirYards Avg_EPA Touchdowns Total_Dropbacks
J.Allen 10.91 -0.05 11 316
J.Winston 10.82 0.26 20 376
B.Mayfield 9.37 0.16 29 482
S.Darnold 9.22 0.06 19 409
R.Wilson 9.06 0.37 37 413
P.Mahomes 8.98 0.46 51 576
A.Rodgers 8.81 0.25 25 590
M.Trubisky 8.74 0.21 24 431
J.Goff 8.68 0.34 32 556
J.Flacco 8.61 0.10 12 374

Lowest air yards average

passingepa %>% 
  arrange(Avg_AirYards)%>% 
  head(10) %>% 
  knitr::kable()
Player Avg_AirYards Avg_EPA Touchdowns Total_Dropbacks
D.Carr 6.95 0.18 21 541
M.Stafford 6.95 0.18 23 552
B.Bortles 7.06 0.01 13 398
D.Brees 7.18 0.38 32 488
C.Newton 7.19 0.20 25 463
K.Cousins 7.28 0.15 33 600
E.Manning 7.35 0.19 22 573
A.Luck 7.42 0.23 42 632
C.Keenum 7.45 0.09 18 577
D.Prescott 7.54 0.23 22 524

Patrick Mahomes led the league in passing touchdowns and yards gained per dropback.

passingepa %>% 
  ggplot(aes(Total_Dropbacks,Avg_EPA)) +
  geom_point() +
  geom_text(aes(label = Player, vjust = 1, hjust = 1, check_overlap = TRUE)) +
  labs(title = 'Expected Points Added by Quarterbacks in 2018',
       subtitle = "300 Droback Minimum",
       x = 'Total QB Dropbacks',
       y = 'Average EPA per Pass ',
       caption = 'Data from nflscrapR')

Patrick Mahomes was also the leader of EPA per dropback

Highest EPA per Dropback

passingepa %>% 
  select(Player,Avg_EPA) %>% 
  arrange(desc(Avg_EPA))%>% 
  head(10) %>% 
  knitr::kable()
Player Avg_EPA
P.Mahomes 0.46
P.Rivers 0.38
D.Brees 0.38
R.Wilson 0.37
J.Goff 0.34
M.Ryan 0.34
D.Watson 0.30
C.Wentz 0.29
J.Winston 0.26
B.Roethlisberger 0.26

Lowest EPA per Dropback

passingepa %>% 
  select(Player,Avg_EPA) %>% 
  arrange(Avg_EPA)%>% 
  head(10) %>% 
  knitr::kable()
Player Avg_EPA
J.Rosen -0.15
J.Allen -0.05
B.Bortles 0.01
S.Darnold 0.06
A.Smith 0.09
C.Keenum 0.09
J.Flacco 0.10
K.Cousins 0.15
B.Mayfield 0.16
D.Carr 0.18

Focusing on returning AFC South Quarterbacks and their pass locations

First step is to create a data set that filters for all QB dropbacks excluding penalties

 afc_qbdropbacks <- pbp_18 %>% 
  filter(passer_player_name == "D.Watson" | passer_player_name == "A.Luck" | passer_player_name == "M.Mariota",!is.na(pass_location), qb_dropback == 1,penalty == 0) %>% 
  mutate_at(vars(incomplete_pass),factor) 

Counting completed passes by pass location

afc_qbdropbacks %>% 
  group_by(passer_player_name,pass_location) %>% 
  count(incomplete_pass)%>% 
  knitr::kable()
passer_player_name pass_location incomplete_pass n
A.Luck left 0 164
A.Luck left 1 63
A.Luck middle 0 105
A.Luck middle 1 48
A.Luck right 0 168
A.Luck right 1 78
D.Watson left 0 125
D.Watson left 1 57
D.Watson middle 0 95
D.Watson middle 1 26
D.Watson right 0 131
D.Watson right 1 62
M.Mariota left 0 95
M.Mariota left 1 37
M.Mariota middle 0 66
M.Mariota middle 1 23
M.Mariota right 0 73
M.Mariota right 1 35

Visualizing the data

afc_qbdropbacks %>%
  filter(qb_dropback == 1,penalty == 0 ) %>% 
ggplot(aes(passer_player_name,fill= incomplete_pass)) +
  geom_bar()  +
  facet_wrap(~pass_location) +
  labs(title = "Returning AFC South Quarterbacks Pass Attempt Locations 2018  ",
       x = "Pass Location",
       y = "Pass Attempts",
       caption= "Data from nflscrapR") +
  guides(fill = guide_legend(reverse=FALSE))+ 
  scale_fill_discrete(name = "Pass Result", labels = c("Completed", "Incompleted"))

pbp_18 %>% 
  filter(passer_player_name == "A.Luck", !is.na(pass_location), !is.na(air_yards)) %>% 
  ggplot(aes(pass_location,air_yards)) +
  geom_boxplot()+
  coord_flip()+
  labs(title= 'Air Yards by Pass Location from Andrew Luck in 2018' , 
       x = 'Pass Location',
       y = 'Air Yards',
       caption= 'Data from nflscrapR')