Skip to contents

Packages:

library(dopingdata)
library(robotstxt)
options(robotstxt_warn = FALSE)

USADA sanction data

The data comes from the USADA sanctions page, which hosts two tables:

  • the sanctions table (Athlete, Sport, Substance/Reason, Sanction Terms, Sanction Announced)
  • the prohibited association table, listing athlete support personnel (coaches, trainers, etc.) currently ineligible under the Prohibited Association rule (Name, Suspension Ends)

Use your manners

Because this package is built on top of the efforts of the fine people who collected, organized, and shared their data, dopingdata uses the polite package to fetch this page, which respects robots.txt and its crawl-delay rules.

Check robots.txt

rtxt <- robotstxt::robotstxt(domain = "https://www.usada.org/")

rtxt$check(
  paths = c("results/", "results/sanctions/"),
  bot   = "*"
)

Getting the data

Rather than scraping the page yourself, dopingdata provides a small cached API modeled on the fightr package: get_*() functions return data from a local cache and refresh it automatically once it’s more than max_age_days old (7 days by default), and update_*() functions force a refresh. Fetching only ever happens when you explicitly call one of these functions — never on package load.

sanctions <- get_sanctions_data()
str(sanctions)
prohibited_association <- get_prohibited_association()
str(prohibited_association)

To force a refresh regardless of cache age:

update_sanctions_data(verbose = TRUE)

update_sanctions_data() makes a single request for the page and refreshes both cached tables, so calling get_sanctions_data() and get_prohibited_association() back to back doesn’t trigger two separate scrapes.

Exporting the data

Some common tasks (like exporting a data frame as a .csv file into a date-stamped folder) have been wrapped in functions:

usada_sanctions_raw <- get_sanctions_data()
str(usada_sanctions_raw)
#> Classes 'tbl_df', 'tbl' and 'data.frame':    1047 obs. of  5 variables:
#>  $ Athlete           : chr  "Miller, Adam" "Zilcosky, Chase" "Trabing, Bert" "Cantwell, Steven" ...
#>  $ Sport             : chr  "Field Hockey" "Weightlifting" "Weightlifting" "Paralympic Snowboarding" ...
#>  $ Substance/Reason  : chr  "Non-Analytical: 3 Whereabouts Failures" "Amphetamine" "Anastrozole; Testosterone" "Dehydrochlormethyltestosterone (DHCMT)" ...
#>  $ Sanction Terms    : chr  "2-Year Suspension; Loss of Results" "2-Year Suspension; Loss of Results" "4-Year Suspension; Loss of Results" "6-Year Suspension; Loss of Results" ...
#>  $ Sanction Announced: chr  "07/31/2026" "07/29/2026" "07/22/2026" "07/16/2026" ...
export_data(
  x = usada_sanctions_raw,
  path = "../dev")

There’s also an export_extdata() function if you’re storing the data in a package:

export_extdata(
  x = usada_sanctions_raw,
  path = "dev")