tb_lv_p<-data.frame(
  Stat=c("CMP","ATT","YDS (Tens)",
         "CMP%","AVG","TD","INT","LNG","SACK","RTG","QBR"),
  Value=c(21    ,29 ,201/10 ,72.4,  6.9 ,3  ,0  ,31 ,1  ,125.8  ,76.7)
)

tb_lv_r<-data.frame(
  Stat=c("CAR","YDS","AVG","TD","LNG"),
  Value=c(4 ,-2 ,-0.5   ,0  ,0)
)
pm_lv_p<-data.frame(
  Stat=c("CMP","ATT","YDS (Tens)",
         "CMP%","AVG","TD","INT","LNG","SACK","RTG","QBR"),
  Value=c(26    ,49,    270/10  ,53.1   ,5.5    ,0, 2   ,33,    3,52.3, 42.2    )
)

pm_lv_r<-data.frame(
  Stat=c("CAR","YDS","AVG","TD","LNG"),
  Value=c(5 ,33,    6.6 ,0  ,11)
)

pm_lv_d<-data.frame(
  
)

PBP Data

pbp_data <- load_pbp(seq(2001,2024))
pbp_data<-pbp_data%>%
  filter(passer == "T.Brady" | passer == "P.Mahomes")

Introduction

In the sport of American football, the quarterback is king. He handles the ball almost every play, has to have one of the sharpest minds on the team, and is often the primary driver towards a win or a loss for the team. Thus, the quarterback alone often represents the team as a whole and is the most analyzed position on the field. So, the age-old question is: who is the best? The most commonly accepted answer is Tom Brady, who spent 20 years with the New England Patriots and 3 years with the Tampa Bay Buccaneers. Brady has more Super Bowl wins in 23 years as a player than any other team has had in the history of the NFL, not to mention scores of other accolades and impressive statistics. However, many NFL fans say that a new generational quarterback is on the rise, claiming he is on track to surpass Brady’s unrivaled career statistics and possibly become the greatest of all time. This quarterback, who is currently in his 8th season with the Kansas City Chiefs, is Patrick Mahomes. Mahomes has already made a name for himself with three super bowl wins and two NFL MVPs, and this year, the Chiefs are indubitably one of the three strongest teams in the league. So, the question we want to answer is: will Patrick Mahomes surpass Tom Brady to become the greatest quarterback of all time? To initially visualize Brady’s greatness and Mahomes’ progress, let’s look at a side-by-side chart of each quarterback’s notable NFL accolades, as mentioned above.

We see that Brady obviously has more accolades than Mahomes in every category, for he has played in many more seasons. However, the shape of Mahomes’ accolades graph is eerily similar to that of Brady’s, which is promising for Mahomes’ future. The exception is that Mahomes has been the MVP in every Super Bowl he has won, which is not true for Brady. Only time will tell if Mahomes will be able to maintain this fact. Also, despite playing in 15 less seasons, Mahomes only has one less first team all-pro and one less NFL MVP than Brady. First team all-pro means you are the best in the league at your position, and quarterback is the most important position in football, so first team all-pro and NFL MVP are usually a package deal for quarterbacks. This means that, despite whether or not he goes to the super bowl, Mahomes only needs one more standout season to match Brady and only tow more to pass him, and Mahomes is still young and hungry. But of course, accolades do not tell the full story.

Perhaps the easiest comprehensive way to compare Brady and Mahomes is through their performance statistics; of course, just by having played in 15 less seasons than Brady, almost all of Mahomes’ aggregate statistics, statistics which are often used to explain Brady’s greatness, are nowhere close to being as great to the New Englander’s. Below is a bar chart that represents Mahomes’ career statistics as a proportion of Brady’s. Because some statistics are better when larger, such as passing yards (call these “positive” statistics), and some are better when smaller, such as interceptions (call these “negative” statistics), the bars are colored green and red to indicate whether Mahomes is winning or losing, respectively.

We see that Mahomes is currently winning in all negative statistics and losing in all positive statistics except for rushing yards, in which he blows Brady out of the water already despite having played less than half of Brady’s number of seasons. In theory, Mahomes’ positive statistics should be above .304 (7/23) of Brady’s to be on track to surpass him, and his negative statistics should be below .304. His positive statistics, especially rushing yards, meet the mark, but only one of his negative statistics, rushing fumbles lost, does. At the very least, from this graph where Mahomes has such strong proportions of rushing yards and rushing fumbles lost, we can see that Mahomes will almost certainly go down as a better rusher than Brady. However, some important statistics such as passing yards per game obviously cannot be told in an aggregate manner, since they are represented per game. Below is a line chart showing the evolution of Brady’s and Mahomes’ mean average passing yards per game, mean average rushing yards per game, and mean passer rating for each of their seasons. In order to be able to directly compare the metrics, the seasons are labeled by number, not by year.

First of all, I’ll note that I left out the first season for each player, for they each only played one game, and those averages would not be representative of the potential ups and downs of a whole season. Here, we see a more broken down story of key statistics between Brady and Mahomes. Mahomes certainly stands out more in passing yards in his 2nd-4th seasons, even having more average passing yards per game in his second season than Brady ever did (even though they only played one game each, I left the first season in the graph because it represents their first ); Mahomes’ passing yards start to falter after his fourth season, with Brady taking the lead on his fifth and eighth seasons, but overall, Mahomes emerges as the more prolific young player in terms of yards. If Mahomes can rebound in his passing yards and maintain an average passing yards statistic around or above 8 yards per season, he could be very well on track to look better than Brady. For rushing yards per game, Mahomes obviously dominates. Mahomes essentially doubles Brady’s average rushing yards per game in each season; he is clearly the better rusher by far. Even with a significant dip in his normal performance, Mahomes is still likely to outperform Brady in terms of rushing.

How about statistics as a team? After all, the quarterback is the primary driver behind a team’s performance. He hands the ball off, sets up kicking drives, and even plays the biggest role in team intimidation. Obviously, a team’s points represent success in these areas. A quarterback’s statistics do not quantify such things as field goals, but a team’s points might. We will be looking at the points scored by Brady’s and Mahomes’ respective teams per game for each of the quarterback’s second through seventh seasons. We will disregard their first seasons, for they only played one game. Not only do we want to look at total points, we also want to look at how those points are added up over the season? Are these quarterbacks getting points consistently for their teams across the season, or are there quick halts and jumps in their cumulative point totals?

We see that while the Patriots take the lead for a few games in the quarterbacks’ seasons 3, 5, and 7, they only end up with the lead in total points for the seventh season, despite the Chiefs playing seventeen games that season after the NFL game number increase in 2021 (I checked the data to make sure that the extra game does not put the Chiefs over the Patriots for one of the numbered seasons where it otherwise would not have). The Chiefs are dominant in cumulative points scored, and they hold the lead in cumulative points during a season for most of each season, including the 7th season, which means that the Patriots had a strong comeback in their last few games of Brady’s 7th season. The Chiefs appear as the better point scorers, which makes another case for Mahomes being on track to surpass Brady.

In addition to their physical prowess and offensive efficiency, quarterbacks have to have a sharp mind. It is also a hallmark of great quarterbacks that they make special efforts and put their body on the line for their teams because, after all, they are the team leader. Therefore, quarterbacks have to be adaptable, not only on offense

We have seen all these statistics over Brady’s and Mahomes’ respective careers, but how about examples of direct competition? Fortunately, we have one - when Brady’s Tampa Bay Buccaneers faced Mahomes’ Kansas City Chiefs in Super Bowl LV. This is a direct competition between two great quarterbacks at the highest level of NFL play, the league championship; the odds couldn’t be any higher, and Brady and Mahomes were putting forth their best effort. Let’s explore some key passing statistics from this game.

comb_data_pass<-rbind(pm_lv_p,tb_lv_p)
comb_data_pass$Player<-c(rep("Mahomes",11),rep("Brady",11))

comb_data_rush<-rbind(pm_lv_r,tb_lv_r)
comb_data_rush$Player<-c(rep("Mahomes",5),rep("Brady",5))

ggplot(comb_data_pass, aes(x = Value, y = Stat, fill = Player)) +
  geom_bar_pattern(stat = "identity",position = "identity",
    aes(x = ifelse(Player=="Brady", -Value, Value),
        pattern_angle = ifelse(Player == "Brady", -75, 75)),
    pattern="stripe",pattern_fill = "black",
    pattern_density = 0.01,pattern_spacing = 0.025,
    show.legend = c(fill = TRUE, pattern_angle = FALSE)) +
  scale_x_continuous(limits = c(-150, 150),labels = function(x) abs(x)) +
  scale_fill_manual(values = c("Brady" = "blue", "Mahomes" = "red"),
    labels = c("Brady", "Mahomes"),name = "Quarterback") +
  labs(title = "Brady vs. Mahomes Passing Statistics",
    subtitle = "in Super Bowl LV",x = "Value",y = NULL) +
  geom_text(aes(label = Value, x = ifelse(Player == "Brady",
      -(Value+(nchar(as.character(Value))*4)),
       (Value+(nchar(as.character(Value))*4)))),
   size = 3,color = "black") +
  theme(plot.title=element_text(hjust=.5,face='bold'),
    plot.subtitle = element_text(hjust = 0.5),
        plot.background = element_rect(fill="#fafaf5"),
    legend.title=element_text(hjust=.5),
    legend.background = element_rect(fill = "#fafaf5", color = "black"))

Key: YDS (Tens) - Tens of Passing Yards | TD - Touchdowns | SACK - Sacks | RTG - Passer Rating | QBR - QB Rating | LNG - Longest Pass | INT - Interceptions | CMP% - Completion Percentage | CMP - Completions | AVG - Average Passing Yards | ATT - Attempts

We see that Brady beats Mahomes in the most important statistics, which are passer rating, QB rating, and completion percentage. He also beats Mahomes in average passing yards, meaning his passes generally took the team further on each play. Brady also has 3 touchdowns, while Mahomes has none. Mahomes wins in total yards, but this makes sense when we see that he had more completions, despite a lower completion rating. He unfortunately also wins on sacks and interceptions, which are a detriment to his performance. His only real win is longest pass, but it is only by two yards. In the direct matchup in the highest stakes game of the year, Brady dominates the passing game. Now, let’s look at rushing statistics.

ggplot(comb_data_rush, aes(x = Value, y = Stat, fill = Player)) +
  geom_bar_pattern(stat = "identity",position = "identity",
    aes(x = ifelse(Player=="Brady", -Value, Value),
        pattern_angle = ifelse(Player == "Brady", -75, 75)),
    pattern="stripe",pattern_fill = "black",
    pattern_density = 0.01,pattern_spacing = 0.03,
    show.legend = c(fill = TRUE, pattern_angle = FALSE)) +
  scale_x_continuous(limits = c(-150, 150),labels = function(x) abs(x)) +
  scale_fill_manual(values = c("Brady" = "blue", "Mahomes" = "red"),
    labels = c("Brady", "Mahomes"),name = "Quarterback") +
  labs(title = "Brady vs. Mahomes Rushing Statistics",
    subtitle = "in Super Bowl LV",x = "Value",y = NULL) +
  geom_text(aes(label = Value, x = ifelse(Player == "Brady",
      -(Value+(nchar(as.character(Value))*4)),
       (Value+(nchar(as.character(Value))*4)))),
   size = 3,color = "black") +
  theme(plot.title=element_text(hjust=.5,face='bold'),
    plot.subtitle = element_text(hjust = 0.5),
        plot.background = element_rect(fill="#fafaf5"),
    legend.title=element_text(hjust=.5),
    legend.background = element_rect(fill = "#fafaf5", color = "black"))

Key: YDS - Total Yards | TD - Touchdowns | LNG - Longest Carry | CAR - Number of Carries | AVG - Average Rushing Yards

This is a rather trivial visualization, but it reinforces a core idea: Mahomes is clearly the better rusher over Brady. Despite an almost equal number of rushes, Brady never gained a single yard on those rushes, which is why he has negative yards and average yards. Mahomes has 33 rushing yards and a decent 11-yard carry, not his best rushing showing but much better than Brady.

Now, how about analyzing the quarterbacks not through themselves or their teams as a whole, but through their teammates? We have already shown that Mahomes is a much stronger rusher, so we will switch to analyzing passing for this next graph. Specifically, we want to analyze the distribution of receivers that our quarterbacks throw passes to on the field. Over a season or a total career, if quarterbacks throw to a much wider variety of receivers, it generally speaks to a more varied and perhaps trickier pass game. This is because if certain receivers dominate receptions by a quarterback, it might say that these receivers are better at getting wide open on the field than the quarterback is at making tricky passes crowded by defenders. Below is a shiny app that visualizes this distribution for each quarterback, filtered by year, down, and distance to the end zone.

Shiny applications not supported in static R Markdown documents

We see that over their careers, for several individual seasons, and most configurations of downs and distances from the end zone, Mahomes throws to a less varied distribution of receivers. In particular, he loves Travis Kelce and Tyreek Hill, at least overall or in years where Hill was still on the chiefs. There are a few exception to this interpretation, such as in 2008, when Brady’s passing was dominated by Randy Moss and Wes Welker, or that Brady’s career-wide passing gets less varied on 3rd and 4th down specifically, which might signal that he is specifically looking for his most trusted receivers to get the job done. However, it appears that Brady is the more dynamic passer overall and might be better and getting the ball to tough spots with lesser known receivers. We will now look at another important metric of their passing, which is their pass efficiency. Below is a shiny app that explores pass efficiency through a scatterplot of yards until first down versus yards gained on the play

DELETE

data <- pbp_data

data <- data %>%
  filter(passer %in% c("P.Mahomes", "T.Brady")) %>%
  select(passer, down, ydstogo, yardline_100, yards_gained, season, posteam_type, qtr)%>%
  drop_na(down, ydstogo, yardline_100, yards_gained, season, posteam_type, qtr)

ui <- fluidPage(
  titlePanel(tags$h1("Quarterback Passing Efficiency", style = "text-align: center; font-weight: bold;")),
  sidebarLayout(sidebarPanel(checkboxGroupInput(
        "down_filter", "Filter by Down Number:",choices = c(1, 2, 3, 4),
        selected = c(1, 2, 3, 4)),
      sliderInput("yard_filter", "Yards Until End Zone:",
        min = 0, max = 100, value = c(0, 100)),
      selectInput("year_filter", "Select Season:",
        choices = c("All", sort(unique(data$season))),
        selected = "All"),
      checkboxGroupInput("quarter_filter", "Filter by Quarter:",
        choices = c(1, 2, 3, 4),
        selected = c(1, 2, 3, 4))),
    mainPanel(tabsetPanel(
        tabPanel("Patrick Mahomes", plotOutput("mahomes_plot"),
                 tableOutput("mahomes_summary")),
        tabPanel("Tom Brady", plotOutput("brady_plot"),
                 tableOutput("brady_summary"))))))

server <- function(input, output) {
  mahomes_data <- reactive({
    filtered_data <- data %>%
      filter(passer == "P.Mahomes",down %in% input$down_filter,
             yardline_100 >= input$yard_filter[1],
             yardline_100 <= input$yard_filter[2],
             qtr %in% input$quarter_filter)
  if (input$year_filter != "All") {
      filtered_data <- filtered_data %>% filter(season == as.numeric(input$year_filter))
    }
    filtered_data
    })
  brady_data <- reactive({
    filtered_data <- data %>%
      filter(passer == "T.Brady",
             down %in% input$down_filter,yardline_100 >= input$yard_filter[1],
        yardline_100 <= input$yard_filter[2],qtr %in% input$quarter_filter)
    if (input$year_filter != "All") {
      filtered_data <- filtered_data %>% 
        filter(season == as.numeric(input$year_filter))
      }
    filtered_data
  })
  output$mahomes_plot <- renderPlot({
    ggplot(mahomes_data(), aes(x = yardline_100, y = yards_gained)) +
      geom_point(alpha = 0.5, color = "red") +
      labs(title = "Patrick Mahomes Passing Efficiency",
           x = "Yards to End Zone",y = "Yards Gained") +
      theme_minimal() +
      theme(plot.title = element_text(hjust = 0.5, face = "bold"))
  })

  output$mahomes_summary <- renderTable({
    mahomes_data() %>%
      summarise(Average_Yards_Gained = mean(yards_gained, na.rm = TRUE),
        Completion_Percentage = sum(yards_gained > 0, na.rm = TRUE) / n())})

  output$brady_plot <- renderPlot({
    ggplot(brady_data(), aes(x = yardline_100, y = yards_gained)) +
      geom_point(alpha = 0.5, color = "blue") +
      labs(title = "Tom Brady Passing Efficiency",
           x = "Yards to End Zone",y = "Yards Gained") +
      theme_minimal() +
      theme(plot.title = element_text(hjust = 0.5, face = "bold"))
  })

  output$brady_summary <- renderTable({
    brady_data() %>%
      summarise(
        Average_Yards_Gained = mean(yards_gained, na.rm = TRUE),
        Completion_Percentage = sum(yards_gained > 0, na.rm = TRUE) / n())
  })}

shinyApp(ui=ui, server=server)
Shiny applications not supported in static R Markdown documents
data <- pbp_data

data <- data %>%
  filter(passer %in% c("P.Mahomes", "T.Brady")) %>%
  select(passer, down, ydstogo, yardline_100, yards_gained, season, posteam_type, qtr) %>%
  drop_na(down, ydstogo, yardline_100, yards_gained, season, posteam_type, qtr)

ui <- fluidPage(
  titlePanel(tags$h1("Quarterback Passing Efficiency", style = "text-align: center; font-weight: bold;")),
  sidebarLayout(sidebarPanel(
      checkboxGroupInput(
        "down_filter", "Filter by Down Number:",
        choices = c(1, 2, 3, 4),
        selected = c(1, 2, 3, 4)),
      sliderInput(
        "yard_filter", "Yards Until First Down:",
        min = 0, max = max(data$ydstogo, na.rm = TRUE), value = c(0, max(data$ydstogo, na.rm = TRUE))),
      selectInput(
        "year_filter", "Select Season:",
        choices = c("All", sort(unique(data$season))),
        selected = "All"),
      checkboxGroupInput(
        "quarter_filter", "Filter by Quarter:",
        choices = c(1, 2, 3, 4),
        selected = c(1, 2, 3, 4))),
    mainPanel(tabsetPanel(
        tabPanel("Patrick Mahomes", plotOutput("mahomes_plot"), tableOutput("mahomes_summary")),
        tabPanel("Tom Brady", plotOutput("brady_plot"), tableOutput("brady_summary"))))))

server <- function(input, output) {
  mahomes_data <- reactive({
    filtered_data <- data %>%
      filter(
        passer == "P.Mahomes",
        down %in% input$down_filter,
        ydstogo >= input$yard_filter[1],
        ydstogo <= input$yard_filter[2],
        qtr %in% input$quarter_filter)
    if (input$year_filter != "All") {
      filtered_data <- filtered_data %>% filter(season == as.numeric(input$year_filter))
    }
    filtered_data
  })
  
  brady_data <- reactive({
    filtered_data <- data %>%
      filter(passer == "T.Brady",down %in% input$down_filter,
        ydstogo >= input$yard_filter[1],
        ydstogo <= input$yard_filter[2],
        qtr %in% input$quarter_filter
      )
    if (input$year_filter != "All") {
      filtered_data <- filtered_data %>% filter(season == as.numeric(input$year_filter))
    }
    filtered_data
  })
  
  output$mahomes_plot <- renderPlot({
    ggplot(mahomes_data(), aes(x = ydstogo, y = yards_gained)) +
      geom_point(alpha = 0.5, color = "red") +
      labs(title = "Patrick Mahomes Passing Efficiency", x = "Yards to First Down", y = "Yards Gained") +
      theme_minimal() +
      theme(plot.title = element_text(hjust = 0.5, face = "bold"))
  })
  
  output$mahomes_summary <- renderTable({
    mahomes_data() %>%
      summarise(
        Average_Yards_Gained = mean(yards_gained, na.rm = TRUE),
        Completion_Percentage = sum(yards_gained > 0, na.rm = TRUE) / n()
      )
  })
  
  output$brady_plot <- renderPlot({
    ggplot(brady_data(), aes(x = ydstogo, y = yards_gained)) +
      geom_point(alpha = 0.5, color = "blue") +
      labs(title = "Tom Brady Passing Efficiency", x = "Yards to First Down", y = "Yards Gained") +
      theme_minimal() +
      theme(plot.title = element_text(hjust = 0.5, face = "bold"))
  })
  output$brady_summary <- renderTable({
    brady_data() %>%
      summarise(Average_Yards_Gained = mean(yards_gained, na.rm = TRUE),
        Completion_Percentage = sum(yards_gained > 0, na.rm = TRUE) / n())
  })
}

shinyApp(ui = ui, server = server)
Shiny applications not supported in static R Markdown documents

From these interactive scatter plots, we note a few key trends. First, Mahomes has a higher pass efficiency rating overall. His average yards gained and average completion percentage are higher than Brady’s overall. These are statistics less affected by number of seasons played, and yet, by individual season, both comparing seasons where Mahomes and Brady both played and the 2nd or 4th, for example, seasons played by each quarterback, Mahomes still wins out.

We’ve shown some key comparisons between Brady and Mahomes, both in terms of passing and rushing, as well as their respective teams. Mahomes seems to be on track to surpass Brady, and he is the better rusher already by far. However, Brady won a high-stakes direct matchup against Mahomes at age 43, which doesn’t predict Mahomes’ journey to surpass his statistics but perhaps might cement him as the better quarterback in many people’s minds. In terms of points,

How about special cases? A quarterback has to be adaptable - defense, kicks, receiving, shit like that.

Plans for a couple of the next plots

Planning to possibly include in the story other star quarterbacks, value given to their teams by Brady and Mahomes due to their success, NFL players getting faster and stronger over time, and the social media craze on the Chiefs due to Travis Kelce dating Taylor Swift.

Football players are bigger, stronger, and faster. However, many star quarterbacks of the past two decades have expressed disappointment with the caliber of NFL players today.