f1pits-intro

library(f1pits)

Vignette Info. Introduction:

The f1pits package provides datasets of Formula 1 race pit stops (since 2019), extracted from DHL website and a function to visualize pit stop data.

This package can be considered complementary to the f1dataR package, which provides Formula 1 race data. You can download f1pits package in GitHub.

Exemple to use:

Step 1: Pit Stops data

To extract the pit stop data for a specific race or an entire season, use the pits() function. Check the documentation for the different arguments of the function.

# Accessing the data, for example, round 1, Australian GP 2025:

pits(1,2026) -> pitdata
#> Australian Grand Prix 2026 / Round: 1

pitdata
#> # A tibble: 30 × 8
#>     Pos. Team         Driver     `Time (sec)`   Lap Points Round  Year
#>    <dbl> <chr>        <chr>             <dbl> <dbl>  <dbl> <int> <dbl>
#>  1     1 Mercedes     Russell            2.17    12     25     1  2026
#>  2     2 Ferrari      Leclerc            2.22    25     18     1  2026
#>  3     3 Red Bull     Verstappen         2.24    41     15     1  2026
#>  4     4 Ferrari      Hamilton           2.26    28     12     1  2026
#>  5     5 Red Bull     Verstappen         2.4     18      0     1  2026
#>  6     6 Racing Bulls Lindblad           2.42    18     10     1  2026
#>  7     7 Mercedes     Antonelli          2.49    12      8     1  2026
#>  8     8 McLaren      Norris             2.52    34      6     1  2026
#>  9     9 Racing Bulls Lawson             2.59    33      4     1  2026
#> 10    10 Williams     Albon              2.63    33      2     1  2026
#> # ℹ 20 more rows

The output generated is a tibble containing the columns:

Pos. (position according to pit stop time), Team, Driver, Time (sec) is the time (in seconds) of each pitstop, Lap (lap of the race; does NOT include sprint sessions), and Points (DHL points. If a driver makes more than one pit stop among the top 10 fastest, the second and subsequent pit stops by that driver do not receive points).

Step 2: ELO team calculations

You can calculate ELO ratings of each team from a pit stop dataset, using a single race or multiple races from the one or different seasons with pitelo() function.

pitelo(pitdata)
#> Using default median stats
#> Team family mode enabled
#> elo_data is missing or is not a data.frame 
#> Using ELO default value (1000)
#>            Team    Rating
#> 1       Ferrari 1092.5354
#> 2      Red Bull 1070.0620
#> 3      Mercedes 1053.1016
#> 4  Racing Bulls 1033.2371
#> 5       McLaren 1016.4279
#> 6          Haas  998.7274
#> 7        Alpine  979.5180
#> 8          Audi  966.8880
#> 9      Williams  945.2336
#> 10     Cadillac  931.5880
#> 11 Aston Martin  912.6810

The ELO calculation is the mean, median, or minimum pit stop position of the teams in each race (see stat_fun argument). For the calculation, you can adjust the magnitude of the ELO change per race (k) and the scaling factor (d).

pitelo(pitdata, stat_fun = 2)
#> Using mean stats
#> Team family mode enabled
#> elo_data is missing or is not a data.frame 
#> Using ELO default value (1000)
#>            Team    Rating
#> 1       Ferrari 1092.5655
#> 2      Red Bull 1070.0805
#> 3      Mercedes 1053.1240
#> 4  Racing Bulls 1033.2574
#> 5       McLaren 1016.4526
#> 6          Haas  998.7547
#> 7          Audi  982.1864
#> 8        Alpine  963.6702
#> 9      Williams  945.2559
#> 10     Cadillac  931.6185
#> 11 Aston Martin  913.0343
pitelo(pitdata, stat_fun = 3, k = 40, d = 1000)
#> Using min stats
#> Team family mode enabled
#> elo_data is missing or is not a data.frame 
#> Using ELO default value (1000)
#>            Team    Rating
#> 1      Mercedes 1185.9488
#> 2       Ferrari 1152.5310
#> 3      Red Bull 1107.8539
#> 4  Racing Bulls 1070.5393
#> 5       McLaren 1037.6279
#> 6      Williams  991.5233
#> 7          Haas  960.5303
#> 8          Audi  924.5083
#> 9        Alpine  885.9003
#> 10     Cadillac  860.8500
#> 11 Aston Martin  822.1869

The different names that the same F1 team has had over the years will be collapsed into the last used in the dataset, for example: Toro Rosso (2019) AlphaTauri (2020-2023) RB (2024) Racing Bulls(2025-2026).

pits(1,2024) -> pitdata24
#> Bahrain Grand Prix 2024 / Round: 1
pits(1,2025) -> pitdata25
#> Australian Grand Prix 2025 / Round: 1
# Join datasets
pitdata_multiple <- dplyr::bind_rows(pitdata, pitdata24, pitdata25)
# Show all teams in dataset
unique(pitdata_multiple$Team)
#>  [1] "Mercedes"     "Ferrari"      "Red Bull"     "Racing Bulls" "McLaren"     
#>  [6] "Williams"     "Haas"         "Audi"         "Alpine"       "Cadillac"    
#> [11] "Aston Martin" "RB"           "Sauber"

pitelo(pitdata_multiple, fml = TRUE)
#> Using default median stats
#> Team family mode enabled
#> elo_data is missing or is not a data.frame 
#> Using ELO default value (1000)
#>            Team    Rating
#> 1       Ferrari 1202.3457
#> 2      Red Bull 1139.3996
#> 3  Racing Bulls 1106.6496
#> 4      Mercedes 1077.6128
#> 5          Haas 1018.9840
#> 6       McLaren  968.1043
#> 7      Cadillac  930.0429
#> 8  Aston Martin  900.3260
#> 9      Williams  897.1572
#> 10       Alpine  887.4393
#> 11         Audi  871.9386

pitelo(pitdata_multiple, fml = FALSE)
#> Using default median stats
#> Team family mode disabled
#> elo_data is missing or is not a data.frame 
#> Using ELO default value (1000)
#>            Team    Rating
#> 1       Ferrari 1201.0865
#> 2      Red Bull 1138.5623
#> 3  Racing Bulls 1081.3016
#> 4      Mercedes 1078.7708
#> 5            RB 1043.5214
#> 6          Haas 1020.5531
#> 7       McLaren  970.8831
#> 8          Audi  968.2777
#> 9      Cadillac  932.6551
#> 10 Aston Martin  904.4772
#> 11     Williams  901.5337
#> 12       Alpine  890.7532
#> 13       Sauber  867.6243

Additionally, you can provide your own ELO rating to initialize the calculations in the function (MUST have the same structure type as in this example).

# Create an ELO tibble with a starting value of 1000 for all teams, except for Cadillac; as a new team it will be slightly penalized (because its team structure is completely new!)

elo_data <- tibble::tibble(
    Team = c("Ferrari", "Red Bull", "Mercedes", "Racing Bulls", "McLaren",
             "Haas", "Alpine", "Williams", "Audi", "Aston Martin", "Cadillac"),
    Rating = c(1000, 1000, 1000, 1000, 1000,
               1000, 1000, 1000, 1000, 1000, 950))

elo_data
#> # A tibble: 11 × 2
#>    Team         Rating
#>    <chr>         <dbl>
#>  1 Ferrari        1000
#>  2 Red Bull       1000
#>  3 Mercedes       1000
#>  4 Racing Bulls   1000
#>  5 McLaren        1000
#>  6 Haas           1000
#>  7 Alpine         1000
#>  8 Williams       1000
#>  9 Audi           1000
#> 10 Aston Martin   1000
#> 11 Cadillac        950
str(elo_data)
#> tibble [11 × 2] (S3: tbl_df/tbl/data.frame)
#>  $ Team  : chr [1:11] "Ferrari" "Red Bull" "Mercedes" "Racing Bulls" ...
#>  $ Rating: num [1:11] 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 ...

pitelo(pitdata, elo = elo_data)
#> Using default median stats
#> Team family mode enabled
#> # A tibble: 11 × 2
#>    Team         Rating
#>    <chr>         <dbl>
#>  1 Ferrari       1091.
#>  2 Red Bull      1069.
#>  3 Mercedes      1052.
#>  4 Racing Bulls  1032.
#>  5 McLaren       1015.
#>  6 Haas           997.
#>  7 Alpine         978.
#>  8 Audi           966.
#>  9 Williams       944.
#> 10 Aston Martin   912.
#> 11 Cadillac       894.

Step 3 (if you want): Plotting

The f1pits package includes the pitplot() function, which takes the data obtained from pits() and produces a ggplot object to visualize pit stop performance. Remember that if you want to provide your own data, the input must be a tibble (see the documentation of pits()). Check the documentation for the different arguments of pitplot() before using it.

# Plotting the data:

pitplot(pitdata,1) -> pitplot_pitdata
#> Processing...
#>   O    _________    O
#> /|\>  _\=..o..=/_  </|\ 
#>  / \ |_|-// \\-|_| / \

pitplot_pitdata

Finally, if you want a fun text for your plot, run the pitart() function in the title_text argument. For example,


pitplot(pitdata,1,title_text = paste0(pitart(3),"    Pit Stop data")) -> pitplot_pitdata_title_edit
#> Processing...
#>   O    _________    O
#> /|\>  _\=..o..=/_  </|\ 
#>  / \ |_|-// \\-|_| / \ 
#>   O    _________    O
#> /|\>  _\=..o..=/_  </|\ 
#>  / \ |_|-// \\-|_| / \

pitplot_pitdata_title_edit

Citations

This package makes extensive use of ‘dplyr’ for data manipulation and ‘ggplot2’ for plotting the data. ‘httr’ and ‘jsonlite’ also to access my repository data. ‘f1dataR’ has inspired me to create this package as a complement.


To cite this package in publications use:, Jordán-Soria J (2025). f1pits: F1 Pit Stop Datasets. Formula 1 pit stop data. The package provides information on teams and drivers across seasons (2019 or higher). It also includes a function to visualize pit stop performance., https://github.com/Jordan-Soria/f1pits.

A BibTeX entry for LaTeX users is

@Manual{, title = {f1pits: F1 Pit Stop Datasets}, author = {José Jordán-Soria}, year = {2025}, note = {Formula 1 pit stop data. The package provides information on teams and drivers across seasons (2019 or higher). It also includes a function to visualize pit stop performance.}, url = {https://github.com/Jordan-Soria/f1pits}, },