Analyzing Week 1 Quarterback Performances with R

Sam Bradford

Week 1 Recap

The first week of the NFL season was full of surprises. Beginning with a shocking Patriots defeat at the hands of resurgent Alex Smith and finishing up with the Saints struggling to put up points against the Vikings, not much played out as expected. Quarterback play, in particular, seemed especially suspect. A short list of high-profile passers who had statistically disappointing Week 1’s includes Cam Newton, Tom Brady, and Russell Wilson, who threw a combined two touchdowns and recorded only one win between them.

Certainly, some quarterbacks played about as we could expect, and still others had particularly good performances (we’re looking at you Sam Bradford and Alex Smith). But watching one slow game after another, I wanted to dig into the numbers and see if the data bore out what I was thinking - was Week 1 of the 2017 season a particularly bad week for quarterback play?

The Approach

To build an appropriate dataset for this question, I turned to Pro Football Reference, which maintains a huge database of NFL statistics. I created a query which grabbed each passing performance recorded in Week 1 of an NFL season since 2007, and filtered by players registered as Quarterbacks (to cut out the odd Wide Receiver or Punter) and players attempting more than one pass attempt. Once the results came through, I dumped them into an Excel file and fired up RStudio to do my analysis.

The Analysis

Importing the Data

First, I imported my data set into RStudio and imported the Tidyverse and Lubridate packages.

passing <- read_excel("YOUR_PATH/NFL Week 1 Passing Statistics 2007-2017.xlsx")

Refining the Passing Dataframe

With all of the statistics now loaded into an R dataframe called “passing”, I did a little manipulation of the data set to create a column for “Year” and filter by quarterbacks attempting more than 10 passes.

passing <- mutate(passing, Year = lubridate::year(Date))
passing$Year <- as.factor(passing$Year)
passing <- filter(passing, Att >= 10)

Grouping Statistics by Year

To analyze Week 1 quarterback performance as a whole from year to year across the league, I needed to condense each week into a single set of statistics. To do this, I used R’s “group_by” and “summarise” functions, which return

g_year <- passing %>% group_by(Year) %>% summarise(tds = sum(TD), ints = sum(Int), cmps = sum(Cmp), atts = sum(Att), yds = sum(Yds), count = n(), rating = mean(Rate, na.rm = TRUE), ya = mean(Yds_Att, na.rm = TRUE), aya = mean(Adj_Yds_Att, na.rm = TRUE))

Table Output

Year tds ints cmps atts yds count rating ya aya
1 2007 40 28 610 983 6635 34 81.34706 6.774706 6.237941
2 2008 38 17 580 944 6559 34 90.60294 7.245588 7.303529
3 2009 42 35 653 1063 7537 34 81.37059 6.916765 6.117059
4 2010 39 27 666 1093 7029 34 81.53235 6.355882 6.016176
5 2011 54 23 683 1107 8391 33 92.59394 7.440909 7.567879
6 2012 47 35 697 1113 8153 33 89.07576 7.442121 7.048182
7 2013 63 34 745 1176 8674 32 91.80625 7.398125 7.225937
8 2014 48 25 746 1161 8272 33 90.81515 7.230606 7.060909
9 2015 49 31 705 1083 7631 33 90.07576 7.204242 7.037576
10 2016 48 19 728 1139 8267 32 91.6375 7.23125 7.267812
11 2017 38 25 640 1003 7074 31 86.09355 7.047097 6.635161

Plotting QB Performance Over Time

Now that our data is grouped by year, we can chart it over time to see how our key statistics such as Passer Rating and Adjusted Yard per Attempt are changing.

Passer Rating (2007-2017)

Adjusted Yards per Attempt (2007-2017)

It’s interesting to see that the plots of each statistic are almost identical - Passer Rating has come under a lot of fire recently, but we see it returning similar results to Adjusted Yards per Attempt, a more modern passing statistic. In either case, it’s clear that this season’s Week 1 passing performance has taken a significant nosedive versus the average quarterback performance over the past six years. Indeed, 2017’s average passer rating of 86.09 has much more in common with the three year average from 2007-2009, where quarterbacks scored and average rating of 84.33.

So Should We Panic?

Long story short - I don’t think so. Some of the worst performances of the week were by quarterbacks filling in for injury, such as Scott Tolzien. Andrew Luck returning to the field and proven quarterbacks such as Cam Newton and Joe Flacco continuing to get healthier will nudge the numbers back upwards. Furthermore, it’s tough to read too much into disappointing games from Brees and Brady, who seem just as likely to throw for 4 touchdowns each next game as have a disappointing Week 2.

What we may see, however, is that the passing “boom” from 2011-2016 is slowing down as defenses adapt and the quarterbacks from that era begin to age of of the league. It wouldn’t shock me if offensive production returns to a level more on the order of the mid-2000s as opposed to the early-2010s. Indeed, the scatter plot shows that while passer rating may have been on the decline in Week 1 versus the past few years, it is still well within the standard band of production.

plot_rating_box <- ggplot(passing, aes(x = Year, y = Rate)) + geom_boxplot(fill = dodgerblue4, color = grey22, alpha = 0.7) + scale_x_discrete(name = "Year") + scale_y_continuous(name = "Passer Rating", breaks = seq(0, 175, 25), limits=c(0, 175)) + ggtitle("Boxplot of Mean Week 1 Passer Rating in the NFL (2017)") + theme_bw()

Adjusted Yards per Attempt (2007-2017)


All told, Week 1 did show some interesting signs that quarterback play across the NFL may be primed to slip this season. With that said, I’m still betting that play improves over the course of next week as injured quarterbacks heal up and proven commodities return to their career performance baselines. The lofty heights of 2011-2013, where Drew Brees and Peyton Manning dominated the league through the air may be gone, but today’s passers are still no joke - let’s hope they bounce back.