# Most-reported adverse event terms for ten drug classes

## Question

Which reaction terms are most frequently reported to the US FDA Adverse Event
Reporting System (FAERS) for ten widely used drugs, and which terms recur across
drugs with different mechanisms? This note reports counts only, not risk,
incidence, or causation.

## Method

Source: the openFDA drug event API, which serves FAERS reports.

- Endpoint: `https://api.fda.gov/drug/event.json`
- Query pattern (one per drug):
  `search=patient.drug.medicinalproduct:"<DRUG>"&count=patient.reaction.reactionmeddrapt.exact&limit=5`
- Drugs, one per class: atorvastatin (statin), metformin (biguanide),
  amoxicillin (penicillin), ibuprofen (NSAID), warfarin (vitamin K antagonist),
  insulin glargine (long-acting insulin), levothyroxine (thyroid hormone),
  omeprazole (proton pump inhibitor), sertraline (SSRI), allopurinol
  (xanthine oxidase inhibitor).
- Retrieved 2026-10-30 (UTC); `meta.last_updated` read `2026-07-30` in all ten
  responses.
- Client: Python 3 `urllib`, User-Agent `research-notes/1.0 (public-data
  analysis; python-urllib)`.
- 10 requests, one per drug, 0.4 s apart, against a hard cap of 40. No request
  failed; `raw.json` records an empty failure list and the count.

Each response was saved to `raw.json` before parsing. `data.csv` was then
derived from `raw.json` (50 rows: 10 drugs × 5 ranks). Every result count below
is read from `data.csv`.

## Results

Cells give term and count, left to right.

| Drug | #1 | #2 | #3 | #4 | #5 |
|---|---|---|---|---|---|
| atorvastatin | FATIGUE (20,168) | DIARRHOEA (18,215) | DYSPNOEA (16,893) | NAUSEA (16,886) | DRUG INEFFECTIVE (15,647) |
| metformin | NAUSEA (30,192) | DIARRHOEA (28,015) | BLOOD GLUCOSE INCREASED (27,174) | DRUG INEFFECTIVE (22,501) | FATIGUE (21,325) |
| amoxicillin | DIARRHOEA (6,917) | DRUG INEFFECTIVE (6,048) | DYSPNOEA (6,001) | NAUSEA (5,764) | RASH (5,368) |
| ibuprofen | DRUG INEFFECTIVE (17,135) | PAIN (16,114) | FATIGUE (15,312) | NAUSEA (14,498) | HEADACHE (12,948) |
| warfarin | INTERNATIONAL NORMALISED RATIO INCREASED (11,154) | DYSPNOEA (8,908) | DRUG INTERACTION (6,755) | FATIGUE (6,483) | DIARRHOEA (6,335) |
| insulin glargine | BLOOD GLUCOSE INCREASED (1,895) | HYPOGLYCAEMIA (1,780) | DEVICE MECHANICAL ISSUE (1,216) | NAUSEA (1,100) | DYSPNOEA (1,067) |
| levothyroxine | FATIGUE (23,092) | NAUSEA (19,935) | DIARRHOEA (18,817) | DRUG INEFFECTIVE (16,945) | HEADACHE (16,106) |
| omeprazole | NAUSEA (21,907) | DIARRHOEA (21,738) | FATIGUE (21,707) | DYSPNOEA (17,870) | DRUG INEFFECTIVE (17,634) |
| sertraline | NAUSEA (8,839) | DRUG INEFFECTIVE (8,823) | FATIGUE (7,916) | HEADACHE (7,069) | DIARRHOEA (6,986) |
| allopurinol | DIARRHOEA (8,933) | FATIGUE (8,496) | DYSPNOEA (8,151) | NAUSEA (7,514) | DEATH (7,011) |

**These are counts of reports, not risks.** FAERS accepts voluntary reports with
no denominator, no control group, and no verification that the drug caused the
event.

- Five terms account for 38 of the 50 cells: NAUSEA (9 of 10 drugs), DIARRHOEA
  (8), FATIGUE (8), DRUG INEFFECTIVE (7), DYSPNOEA (6). With HEADACHE (3) and
  BLOOD GLUCOSE INCREASED (2) the table holds 14 distinct terms; seven occur
  on one drug each.
- The top rank is split: NAUSEA leads for metformin, omeprazole and sertraline;
  FATIGUE for atorvastatin and levothyroxine; DIARRHOEA for amoxicillin and
  allopurinol; DRUG INEFFECTIVE for ibuprofen; INTERNATIONAL NORMALISED RATIO
  INCREASED for warfarin; BLOOD GLUCOSE INCREASED for insulin glargine.
- Seven terms appear on exactly one drug: RASH (amoxicillin), PAIN (ibuprofen),
  DRUG INTERACTION and INTERNATIONAL NORMALISED RATIO INCREASED (warfarin),
  HYPOGLYCAEMIA and DEVICE MECHANICAL ISSUE (insulin glargine), and DEATH
  (allopurinol, rank 5, 7,011).
- Cell counts span 1,067 (DYSPNOEA, insulin glargine) to 30,192 (NAUSEA,
  metformin), and the 50 cells total 645,303.

## What this does and does not show

- **No denominator.** Counts cannot be converted to rates. Nothing here compares
  drugs: a larger count does not mean a drug is more hazardous; it may mean the
  drug is prescribed more widely, or reported more actively.
- **Voluntary and unverified.** Anyone may submit a report. Reports are
  suspicions, not adjudicated findings; a report does not establish that the
  drug caused the reaction.
- **Duplicates and stimulated reporting.** The same event can be submitted more
  than once and follow-ups are filed as separate reports. Publicity, litigation,
  and label changes can raise counts for particular terms.
- **No causation, ever.** FAERS is routinely read as if it measured incidence or
  proved harm. It does neither. A count is a tally of what someone chose to
  report.
- **Name matching is literal.** `patient.drug.medicinalproduct` is the product
  name as submitted. Reports filed under a brand name, a misspelling, or a
  non-US name are not counted by a generic-string query, and this analysis did
  not quantify that shortfall.
- **Terms are not exclusive.** One report can carry several reaction terms, so
  counts do not sum to a report total, and overlapping gastrointestinal and
  fatigue terms may reflect reporting habit as much as distinct events.
- **Outcome words are not reactions.** DRUG INEFFECTIVE, DEVICE MECHANICAL
  ISSUE, and DEATH are outcome categories in the terminology, not adverse
  reactions attributable to a drug. DEATH in particular is not evidence that
  allopurinol caused death.
- **A dated snapshot.** The API reported data current to 2026-07-30; later
  submissions will change the numbers.

## Reproduce

```bash
cd /Volumes/Storage/DeepSeek/workspace/pgx-gap-map/research-notes/_scripts/faers-adverse-events
python3 fetch.py      # 10 requests, 0.4 s apart, writes raw.json into the note dir
python3 derive.py     # writes data.csv from raw.json, prints recurrence counts
```

One query, by hand:

```bash
python3 -c 'import urllib.request,json;u="https://api.fda.gov/drug/event.json?search=patient.drug.medicinalproduct%3A%22atorvastatin%22&count=patient.reaction.reactionmeddrapt.exact&limit=5";print(json.dumps(json.loads(urllib.request.urlopen(urllib.request.Request(u,headers={"User-Agent":"research-notes/1.0"})).read())["results"],indent=2))'
```

## Publication status

**Draft.** Auto-generated from public API responses; requires editorial review
before publication.
