F1 Championship Standings Analysis 2021-2025

Author

Cole Tenfelde

Hero or Villain? Duu..du..du…du…Max Verstappen.

Max Verstappen is a Dutch Formula One driver for Redbull Racing. He holds multiple records and his 2023 season stands alone as the most dominant season in Formula One. That season he won 19 of the 22 scheduled races and finished second to his teammate twice. Now formula one is just as much about the driver as it is the car, but tracking points progression, finishing position distributions, and head-to-head comparisons against his closest rivals, we assess how the competitive landscape of Formula 1 shifted around one of its greatest champions.

The Data

The data for this analysis was scraped from f1-fansite.com. This data does not include information from sprint races and covers the 2023-2025 driver standings.

library(gt)
Warning: package 'gt' was built under R version 4.3.3
library(rvest)
library(httr)
library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(tidyr)
library(stringr)
library(ggplot2)

f1_standings_data <- read.csv("https://myxavier-my.sharepoint.com/:x:/g/personal/tenfeldec_xavier_edu/IQB2IQb6aMbIRpaJMAFSv64lAU_S2xU7ajAT6u4YX03xnto?e=MD6UbX&download=1")

The variables used are:
Position — final standing at the end of the season by points
Driver — driver name
Race — Grand Prix abbreviation
Result — final position of each race
Season — championship season (2023-2025)
Fastest Lap — if driver finished the GP with the fastest lap (T/F)
Points Gained — points awarded for position result
Round — GP round number
Cumulative Pts — cumulative points added each round

Data Wrangling

Before analysis, the data required several transformation steps. The raw scraped data was reshaped from wide to long format so that each row represents a single driver-race observation.

glimpse(f1_standings_data)
Rows: 2,279
Columns: 9
$ Position       <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
$ Driver         <chr> "Max Verstappen", "Max Verstappen", "Max Verstappen", "…
$ Race           <chr> "BAH", "EMI", "POR", "SPA", "MON", "AZE", "FRE", "STE",…
$ Result         <chr> "2", "1", "2", "2", "1", "DNF", "1", "1", "1", "DNF", "…
$ Season         <int> 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2…
$ Fastest_Lap    <lgl> FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TR…
$ Points_Gained  <int> 18, 25, 18, 18, 25, 0, 25, 25, 25, 0, 2, 25, 25, 0, 18,…
$ Round          <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, …
$ Cumulative_Pts <int> 18, 43, 61, 79, 104, 104, 129, 154, 179, 179, 181, 206,…
rivals <- c("Max Verstappen", "Lando Norris", "Charles Leclerc",
            "Lewis Hamilton", "Carlos Sainz")

rivals_data <- f1_standings_data %>%
  filter(Driver %in% rivals)

verstappen_data <- f1_standings_data %>%
  filter(Driver == "Max Verstappen")

summary_table <- f1_standings_data %>%
  filter(Driver == "Max Verstappen") %>%
  mutate(
    Win    = Result == "1",
    Podium = Result %in% c("1", "2", "3"),
    DNF    = Result %in% c("Wd", "DSQ", "DNS", "DNF")
  ) %>%
  group_by(Season) %>%
  summarise(
    Races        = n(),
    Wins         = sum(Win,         na.rm = TRUE),
    Podiums      = sum(Podium,      na.rm = TRUE),
    DNFs         = sum(DNF,         na.rm = TRUE),
    Fastest_Laps = sum(Fastest_Lap, na.rm = TRUE),
    Total_Points = max(Cumulative_Pts, na.rm = TRUE)
  ) %>%
  mutate(Points_Possible = Races * 25)

Analysis and Results

summary_table %>%
  gt() %>%
  tab_header(title = "Max Verstappen Season Summary 2023-2025")
Max Verstappen Season Summary 2023-2025
Season Races Wins Podiums DNFs Fastest_Laps Total_Points Points_Possible
2021 22 10 18 3 6 396 550
2022 22 15 17 1 5 428 550
2023 22 19 21 0 9 521 550
2024 24 9 14 1 3 396 600
2025 24 8 15 1 3 389 600

This table highlights the

summary_table %>%
  pivot_longer(
    cols      = c(Total_Points, Points_Possible),
    names_to  = "Type",
    values_to = "Points"
  ) %>%
  ggplot(aes(x = factor(Season), y = Points, fill = Type)) +
  geom_bar(stat = "identity", position = "dodge") +
  scale_fill_manual(values = c("Total_Points"    = "blue",
                               "Points_Possible" = "red")) +
  labs(
    title = "Verstappen: Points Scored vs Points Possible",
    x     = "Season",
    y     = "Points",
    fill  = ""
  ) +
  theme_minimal()

This graph shows how close Max Verstappen was maximizing points every season. He won the championship in 2021-2024 while losing in 2025 to Lando Norris. You can see how dominant he was during the 2023 season with not many points that Max did not capitilize on. He won this season’s drivers championship with 6 races to go.

closest_rival <- f1_standings_data %>%
  filter(Driver != "Max Verstappen") %>%
  group_by(Season, Driver) %>%
  summarise(Total_Points = max(Cumulative_Pts, na.rm = TRUE), .groups = "drop") %>%
  group_by(Season) %>%
  slice_max(Total_Points, n = 1)

verstappen_points <- f1_standings_data %>%
  filter(Driver == "Max Verstappen") %>%
  group_by(Season) %>%
  summarise(Total_Points = max(Cumulative_Pts, na.rm = TRUE)) %>%
  mutate(Driver = "Max Verstappen")

comparison <- bind_rows(verstappen_points, closest_rival)

ggplot(comparison, aes(x = factor(Season), y = Total_Points, fill = Driver)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(
    title = "Verstappen vs Closest Rival - Total Points by Season",
    x     = "Season",
    y     = "Total Points",
    fill  = "Driver"
  ) +
  theme_minimal()

This graph shows who the closest driver to Max Verstappen was at the end of the season. Here we can see the close battle with Lewis Hamilton in 2021 where the championship came down to the last race, this is where Max would win his first of his four drivers championships. His biggest rivals during these seasons were Lewis Hamilton, Sergio Perez (his teammate at Redbull racing), and Lando Norris.

verstappen_data %>%
  ggplot(aes(x = factor(Season), y = Points_Gained, fill = factor(Season))) +
  geom_boxplot() +
  labs(
    title    = "Verstappen Points Per Race Distribution by Season",
    x        = "Season",
    y        = "Points Gained Per Race",
    fill     = "Season"
  ) +
  theme_minimal()

This graph shows distrubution of points for Max Verstappen’s dominant few seasons. The middle line of each box represents his median points haul per race. As you can see in the 2023 season he was untouchable with finishing first, but had a lot more competition in the 2021, 2024, and 2025 season. A big part of his dominance is his consitency and have few races with 0 points scored.

rivals_data %>%
  ggplot(aes(x = Round, y = Cumulative_Pts, color = Driver)) +
  geom_line(linewidth = 1) +
  facet_wrap(~Season) +
  labs(
    title    = "Championship Points Progression Round by Round",
    subtitle = "Verstappen vs Top Rivals (2021-2025)",
    x        = "Round",
    y        = "Cumulative Points",
    color    = "Driver"
  ) +
  theme_minimal()

The line chart above tracks how Max Verstappen and his four closest rivals accumulated championship points round by round across the 2021-2025 seasons. Each line represents a single driver, with the steepness of the slope indicating how quickly they were scoring points at any given point in the season — a steep upward climb means consistent race wins and podiums, while a flat or gradual line indicates a stretch of poor results or retirements.

Conclusion

The data across the 2021-2025 seasons shows the stretch of Max Verstappen’s best seasons in Formula One. In these seasons, he won 4 Driver’s Championships and 3 Constructorss Championships for Redbull Racing. So the question gets asked, just how dominant was Max Verstappen in these seasons? Max Verstappen’s 2023 season was nothing short of complete domination with him winning 19 of 22 races, clinching the championship with six rounds to spare, and scoring a near-perfect percentage of the total points available. The points progression chart from that season shows his cumulative points line pulling away from every rival almost immediately after the opening round, a gap that only grew wider as the season went on. By almost every statistical measure, it was the most dominant individual season Formula One has ever seen.

But the 2024 and 2025 season tell us a different story. The gap between Verstappen’s total points and the maximum points possible widened considerably, rival lines tracked far closer throughout the championship, and his per-race points distribution became noticeably less consistent. Lando Norris, Charles Leclerc, and Lewis Hamilton all mounted genuine championship challenges in ways that simply were not possible in 2023. Ultimately Norris would claim the 2025 drivers championship, ending Verstappen’s four year stranglehold on the title.