Scraping USADA sanctions
scraping-usada-sanctions.RmdPackages:
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.
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")