Analysis of Crossfit Banned Substances Sanctions

a cartoonized close up picture of a man

2024-04-10

Gabriel Montpetit

I wanted to create a dataset that represents the list of crossfit banned substances to see what is more common amongst tested crossfit athletes.

Note that I do not endorse the use of Performance Enhancing Drugs (PED) in any way.

Using this page https://morningchalkup.com/data/list-of-current-crossfit-games-drug-sanctions/ , I was able to create a small dataset of bans (from 2019 to 2023). I should give an accurate view of that crossfit athletes may be using now.

This post was generated from a jupyter notebook. In order to follow along, create a virtual venv and install jupyter with pip install jupyter. Then you can run jupyter notebook and open this notebook.

You may need to install lxml.

                  
%%capture
!pip install pandas==2.2.1
!pip install matplotlib==3.8.4
!pip install lxml==5.2.1
!pip install beautifulsoup4==4.12.3
                
                  
#
# imports
#

# regex
import re
# read page as string and pass it back to pandas withStringIO
from io import StringIO

# Pandas
import pandas as pd
# Web requests
import requests
# HTML parser
from bs4 import BeautifulSoup
# Plotting the results
import matplotlib.pyplot as plt
%matplotlib inline
                

Dictionary of banned substances

Let's first create a dictionary of banned substances. This will be used to create a regex that can match multiple terms per single string.

Some athletes have been using more than one substance.

                  
#
# Dictionary of substances
#

substances = {
    "gw1516": ("Cardarine", "GW1516"),
    "clomiphene": ("selective estrogen receptor modulator", "Clomiphene"),
    "s-23": ("selective androgen receptor modulator", "S-23"),
    "rad140": ("selective androgen receptor modulator", "RAD140"),
    "turinabol": ("Anabolic Androgenic Steroid", "Turinabol"),
    "ostarine": ("selective androgen receptor modulator", "Ostarine"),
    "oxandrolone": ("Anabolic Androgenic Steroid", "Oxandrolone"),
    "methenolone": ("Anabolic Androgenic Steroid", "Methenolone"),
    "stanozolol": ("Anabolic Androgenic Steroid", "Stanozolol"),
    "anastrozole": ("Antiestrogen", "Arimidex"),
    "19-noretiocholanolone": ("Anabolic Androgenic Steroid", "19-noretiocholanolone"),
    "drostanolone": ("Anabolic Androgenic Steroid", "drostanolone"),
    "3a-hydroxy-1-methylene-5a-androstan-17-one": ("Anabolic Steroid", "3a-hydroxy-1-methylene-5a-androstan-17-one"),
    "meldonium": ("anti-ischemia", "Meldonium"),
    "lgd-4033": ("selective androgen receptor modulator", "LGD-4033"),
    "ibutamoren": ("growth hormone", "ibutamoren"),
    "nandrolone": ("Anabolic Androgenic Steroid", "nandrolone"),
    "bolandione": ("Anabolic Androgenic Steroid", "bolandione"),
    "dehydroepiandrosterone": ("endogenous steroid hormone precursor", "Dehydroepiandrosterone"),
    "exogenous testosterone": ("Anabolic Androgenic Steroid", "exogenous testosterone"),
    "tamoxifen": ("selective androgen receptor modulator", "Tamoxifen")
}

#
# Create the master regex
#

regex = "|".join(
    [f"{a}" for a in substances.keys()]
)
                

Now we can fetch the data online by using BeautifulSoup and Pandas. We create a header which will make it look like the request comes from a valid web browser.

                  
#
# get the data
#

url = "https://morningchalkup.com/data/list-of-current-crossfit-games-drug-sanctions/"
header = {
  "User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36",
  "X-Requested-With": "XMLHttpRequest"
}
r = requests.get(url, headers=header)
soup = BeautifulSoup(r.text, features="lxml")
table = soup.find(class_="responsive display nowrap data-t data-t wpDataTable wpDataTableID-18")

#
# Create the pandas dataframe
#

df = pd.read_html(
    StringIO(str(table)), displayed_only=False
)[0]
df = df[df["Banned Substance"].notna()]
df.head()
                

First Name Last Name Start of Ban Sample From End of Ban Banned Substance Link
1 Trent Williams 05/21/2023 NaN NaN Clomiphene NaN
2 Angelique Connoway 05/21/2023 2023 REBEL Renegade Games 05/21/2027 metabolites of GW1516 https://games.crossfit.com/announcement/14228
3 Danijela Hodges 03/19/2023 out-of-competition 03/19/2027 n/a - failed to submit drug sample https://games.crossfit.com/announcement/14167
4 Jeff Adams 08/06/2022 2022 CrossFit Games 08/06/2026 S-23 https://thebarbellspin.com/crossfit-games/cros...
5 Tommy Tillman 08/06/2022 2022 CrossFit Games 08/06/2026 clomiphene https://games.crossfit.com/announcement/13854

Now that we have the data, we will search the "Banne Substance" column for all terms matching the master regex

                  
#
# Process table
#

def find_all(description: str) -> list[str] | None:
    res = re.findall(f"({regex})", description.lower())
    if len(res) > 0:
        return list(set(res))
    return None

banned_cn = df.assign(**{
    "Banned Substance CN": df["Banned Substance"].apply(
        lambda x: find_all(x)
    ),
})[["First Name", "Last Name", "Banned Substance CN"]]
banned_cn.head()
                

First Name Last Name Banned Substance CN
1 Trent Williams [clomiphene]
2 Angelique Connoway [gw1516]
3 Danijela Hodges None
4 Jeff Adams [s-23]
5 Tommy Tillman [clomiphene]

Here we do a simple plot of the banned substances and number of times it was caught.

                  
fig, ax = plt.subplots(facecolor=(0.125, 0.129, 0.141))
w = 'white'
plt.rcParams.update({
    'text.color': w,
    'axes.labelcolor': w,
    'xtick.color': w,
    'ytick.color': w,
    'font.size': 10,
    'axes.edgecolor': w,
    'axes.facecolor': w,
    'axes.titlecolor': w
})

banned_cn.explode(
    column="Banned Substance CN"
)[["Banned Substance CN"]].value_counts().sort_values().plot(
    kind='barh',
    x='001-crossfit-banned-substances',
    y='fail drug test count',
    ax=ax,
    color=(0.392, 0.573, 0.271),
    linewidth=0,
)
ax.set_facecolor((0.180, 0.184, 0.196))
                

png

Looking what is more common amongst tested crossfit athletes, we can see that the most common substances are: gw1516, ostarine and stanozolol.

gw1516

Commonly known as Cardarine, it is a PPARδ receptor agonist that was developed in the early 1990s. It was developed as a safe alternative for heart and metabolic conditions. It is not approved for human consumption

GW1516 works by forcing skeletal muscle to use fat rather than carbohydrates as an energy source. Used by some for fat loss. In the context of athletic enhancement, it has benefits as an endurance aid.

GW1516 (GW501516) has been linked to a number of positive doping tests in endurance-related sports. After a number of positive tests for GW1516 in 2013, WADA released a warning on its health risks.

In 2015 and 2016, there were less than six positive tests for GW1516 globally each year. In 2017 however, the number of positive tests rose to 31, an increase of 183.33 percent.

In June 2018, the Australian Therapeutic Goods Administration (TGA) included GW1516 in the Poisons Standard under Schedule 10 – a schedule reserved for substances of such danger to health as to warrant the prohibition of sale, supply and use.

Athletes seeking to obtain an “edge” from the use of GW1516 need to be aware that they risk more than a positive test if they choose to take it – they may be risking their life.

ostarine

Ostarine, also known as MK-2866, is a selective androgen receptor modulator (SARM) that is illegally sold worldwide as a performance-enhancing substance. Ostarine is not currently available as a prescription medication in any country, and its unauthorized use may carry serious side effects.

Taking Ostarine can significantly improve lean body mass. This makes it a go-to for people suffering from conditions like cachexia or muscle wasting syndrome due to cancer and other auto-immune disorders. Patients suffering from symptoms of sarcopenia and age-related muscle loss problem can be considerably helped with the use of Ostarine. It has also shown promising results for the treatment of inherited muscle loss or weakness disorders, more commonly known as muscular dystrophy. Although less evidence, it has also shown signs of bettering symptoms of breast cancer, urinary incontinence, or loss of bladder control. While Ostarine is currently being researched by Viking Therapeutics for the treatment of muscle-wasting in cancer patients, many bodybuilders take it to put on muscle mass, enhance their fat loss speed, and increase strength while on bulking and cutting cycles.

Ostarine is known to attach itself to the proteins called androgen receptors in the user’s body. Once it has bound itself, it further denotes these receptors to grow the muscles faster. The process for accentuating muscle growth is by altering the genes, which further enhances protein synthesis, complementing muscle growth.

stanozolol

Stanozolol is a synthetic steroid that is derived from testosterone. It has both anabolic and androgenic properties. It is a controlled substance under the Anabolic Steroids Control Act of 1990 and has been assigned to Schedule III.