arframe TFL Gallery
  1. Tables
  2. Adverse Events with Event Counts
  • Getting Started
    • Installation

  • Tables
    • Study Conduct
    • Enrollment by Country and Site

    • Study Population
    • Demographics Summary
    • Medical History
    • Prior Medication
    • Disposition Summary
    • Analysis Populations

    • Extent of Exposure
    • Concomitant Medications
    • Extent of Exposure

    • Safety
    • Adverse Events by System Organ Class and Preferred Term
    • AEs Related to Study Drug
    • Common Adverse Events
    • Adverse Events by Grade / Intensity
    • Overall Safety Summary
    • Adverse Events with Event Counts
    • Exposure-Adjusted Adverse Events
    • Adverse Events by Subgroup
    • Serious Adverse Events by SOC and PT
    • AEs Leading to Study Drug Discontinuation
    • Death Summary
    • Vital Signs
    • Laboratory Results - Chemistry
    • Laboratory Shift Table
    • Laboratory Worst Toxicity Grade
    • Laboratory Marked Abnormalities
    • Electrocardiogram Summary

    • Efficacy
    • Time to Event Summary
    • Best Overall Response

  • Listings
    • Adverse Event Listing
    • Demographic Characteristics Listing
    • Medical History Listing
    • Vital Signs Listing
    • Laboratory Test Results Listing
    • Concomitant Medications Listing

  • Figures
    • Kaplan-Meier Plot
    • Swimmer Plot
    • Waterfall Plot

On this page

  • Setup
  • Data Preparation
  • arframe Pipeline
  • Rendered Table
  1. Tables
  2. Adverse Events with Event Counts

Adverse Events with Event Counts

Summary of Treatment-Emergent Adverse Events with Event Counts

Setup

See Prerequisites for installation instructions.

library(arframe)
library(pharmaverseadam)
library(dplyr, warn.conflicts = FALSE)
library(tidyr)
library(cards)

adsl_saf <- pharmaverseadam::adsl |>
  blank_to_na() |>
  filter(SAFFL == "Y", TRT01A != "Screen Failure")

adae_teae <- pharmaverseadam::adae |>
  blank_to_na() |>
  filter(TRTEMFL == "Y", TRT01A != "Screen Failure")

arm_levels <- c("Placebo", "Xanomeline Low Dose", "Xanomeline High Dose")

arm_n <- adsl_saf |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A) |>
  pull(n, name = TRT01A)
arm_n <- arm_n[arm_levels]

N_total <- nrow(adsl_saf)
n_vec <- c(arm_n, Total = N_total)

Data Preparation

  • dplyr
  • cards
# Format: "n_subjects (n_events)"
subj_events <- function(n_subj, n_events) {
  sprintf("%d (%d)", n_subj, n_events)
}

# ── Any TEAE (overall row) ──
any_subj_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A) |>
  count(TRT01A, name = "n_subj")

any_events_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A, name = "n_events")

any_arm <- left_join(any_subj_arm, any_events_arm, by = "TRT01A") |>
  mutate(value = mapply(subj_events, n_subj, n_events)) |>
  select(TRT01A, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

any_total <- tibble(
  Total = subj_events(
    n_distinct(adae_teae$USUBJID),
    nrow(adae_teae)
  )
)

any_row <- bind_cols(
  tibble(soc = "Any TEAE", pt = "Any TEAE", row_type = "overall"),
  any_arm,
  any_total
)

# ── SOC-level: subjects and events ──
soc_subj_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS) |>
  count(TRT01A, AEBODSYS, name = "n_subj")

soc_events_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A, AEBODSYS, name = "n_events")

soc_arm <- left_join(soc_subj_arm, soc_events_arm, by = c("TRT01A", "AEBODSYS")) |>
  mutate(value = mapply(subj_events, n_subj, n_events)) |>
  select(TRT01A, AEBODSYS, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

soc_subj_total <- adae_teae |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "n_subj")

soc_events_total <- adae_teae |>
  count(AEBODSYS, name = "n_events")

soc_total <- left_join(soc_subj_total, soc_events_total, by = "AEBODSYS") |>
  mutate(Total = mapply(subj_events, n_subj, n_events)) |>
  select(AEBODSYS, Total)

soc_wide <- left_join(soc_arm, soc_total, by = "AEBODSYS") |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEBODSYS,
    row_type = "soc",
    .before  = 1
  ) |>
  select(-AEBODSYS)

# ── PT-level: subjects and events ──
pt_subj_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS, AEDECOD) |>
  count(TRT01A, AEBODSYS, AEDECOD, name = "n_subj")

pt_events_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A, AEBODSYS, AEDECOD, name = "n_events")

pt_arm <- left_join(pt_subj_arm, pt_events_arm, by = c("TRT01A", "AEBODSYS", "AEDECOD")) |>
  mutate(value = mapply(subj_events, n_subj, n_events)) |>
  select(TRT01A, AEBODSYS, AEDECOD, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

pt_subj_total <- adae_teae |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "n_subj")

pt_events_total <- adae_teae |>
  count(AEBODSYS, AEDECOD, name = "n_events")

pt_total <- left_join(pt_subj_total, pt_events_total, by = c("AEBODSYS", "AEDECOD")) |>
  mutate(Total = mapply(subj_events, n_subj, n_events)) |>
  select(AEBODSYS, AEDECOD, Total)

pt_wide <- left_join(pt_arm, pt_total, by = c("AEBODSYS", "AEDECOD")) |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEDECOD,
    row_type = "pt",
    .before  = 1
  ) |>
  select(-AEBODSYS, -AEDECOD)

# ── Sort by descending subject frequency ──
soc_order <- adae_teae |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "soc_n") |>
  arrange(desc(soc_n)) |>
  pull(AEBODSYS)

pt_sorted <- adae_teae |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "pt_n") |>
  arrange(match(AEBODSYS, soc_order), desc(pt_n))

pt_wide <- pt_sorted |>
  select(soc = AEBODSYS, pt = AEDECOD) |>
  left_join(pt_wide, by = c("soc", "pt"))

# ── Interleave ──
ae_events_wide <- bind_rows(
  any_row,
  bind_rows(
    lapply(soc_order, function(s) {
      bind_rows(
        filter(soc_wide, soc == s),
        filter(pt_wide, soc == s)
      )
    })
  )
) |>
  mutate(across(
    where(is.character) & !c(soc, pt, row_type),
    ~ replace_na(.x, "0 (0)")
  ))
# cards ard_stack_hierarchical provides subject counts
# We supplement with event counts via manual aggregation
ae_subj_ard <- ard_stack_hierarchical(
  data        = adae_teae |> filter(TRT01A %in% arm_levels),
  variables   = c(AEBODSYS, AEDECOD),
  by          = TRT01A,
  denominator = adsl_saf,
  id          = USUBJID,
  overall     = TRUE,
  over_variables = FALSE
) |>
  sort_ard_hierarchical(sort = "descending")

# Note: cards output has subject counts only (no event counts)
# Use a separate variable to avoid overwriting the dplyr output
ae_events_cards <- fr_wide_ard(
  ae_subj_ard,
  statistic = "{n}",
  label     = c(
    AEBODSYS = "System Organ Class",
    AEDECOD  = "Preferred Term"
  )
)

arframe Pipeline

The rendered table below uses the dplyr data prep (ae_events_wide, with subject + event counts). The cards tab produces ae_events_cards (subject counts only) — swap it in to use the cards path instead.

ae_events_wide |>
  fr_table() |>
  fr_titles(
    "Table 14.3.2",
    "Summary of Treatment-Emergent Adverse Events with Event Counts",
    "Safety Population"
  ) |>
  fr_cols(
    soc      = fr_col(visible = FALSE),
    pt       = fr_col("System Organ Class\n  Preferred Term", width = 3.5),
    row_type = fr_col(visible = FALSE),
    !!!setNames(
      lapply(arm_levels, function(a) fr_col(a, align = "decimal")),
      arm_levels
    ),
    Total = fr_col("Total", align = "decimal"),
    .n = n_vec
  ) |>
  fr_header(bold = TRUE, align = "center") |>
  fr_rows(
    group_by  = "soc",
    indent_by = "pt"
  ) |>
  fr_styles(
    fr_row_style(rows = fr_rows_matches("row_type", value = "soc"), bold = TRUE),
    fr_row_style(rows = fr_rows_matches("row_type", value = "overall"), bold = TRUE)
  ) |>
  fr_footnotes(
    "TEAE = Treatment-Emergent Adverse Event.",
    "Values displayed as: n_subjects (n_events).",
    "Subjects are counted once per SOC and once per PT; events are total occurrences.",
    "Percentages not shown \u2014 denominators differ for subjects vs events.",
    "SOC and PT sorted by descending subject frequency."
  )

Rendered Table

Table 14.3.2
Summary of Treatment-Emergent Adverse Events with Event Counts
Safety Population
System Organ Class
Preferred Term
Placebo
(N=86)
Xanomeline High Dose
(N=72)
Xanomeline Low Dose
(N=96)
Total
(N=254)
Any TEAE65 (281)68 (414)84 (427)217 (1122)
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS21 ( 46)36 (118)51 (124)108 ( 288)
APPLICATION SITE PRURITUS 6 ( 10)21 ( 34)23 ( 33) 50 ( 77)
APPLICATION SITE ERYTHEMA 3 ( 3)14 ( 22)13 ( 21) 30 ( 46)
APPLICATION SITE DERMATITIS 5 ( 9) 7 ( 12) 9 ( 15) 21 ( 36)
APPLICATION SITE IRRITATION 3 ( 7) 9 ( 16) 9 ( 18) 21 ( 41)
APPLICATION SITE VESICLES 1 ( 2) 5 ( 5) 5 ( 6) 11 ( 13)
FATIGUE 1 ( 2) 5 ( 5) 5 ( 5) 11 ( 12)
OEDEMA PERIPHERAL 2 ( 3) 2 ( 3) 1 ( 1) 5 ( 7)
APPLICATION SITE SWELLING 0 2 ( 3) 1 ( 1) 3 ( 4)
APPLICATION SITE URTICARIA 0 1 ( 1) 2 ( 2) 3 ( 3)
CHILLS 1 ( 3) 1 ( 1) 1 ( 2) 3 ( 6)
MALAISE 0 2 ( 3) 1 ( 2) 3 ( 5)
PYREXIA 2 ( 2) 0 1 ( 1) 3 ( 3)
APPLICATION SITE PAIN 0 2 ( 2) 0 2 ( 2)
APPLICATION SITE PERSPIRATION 0 2 ( 3) 0 2 ( 3)
APPLICATION SITE REACTION 1 ( 2) 1 ( 1) 0 2 ( 3)
ASTHENIA 1 ( 2) 0 1 ( 1) 2 ( 3)
CHEST DISCOMFORT 0 1 ( 1) 1 ( 1) 2 ( 2)
CHEST PAIN 0 2 ( 2) 0 2 ( 2)
OEDEMA 0 0 2 ( 2) 2 ( 2)
PAIN 0 1 ( 1) 1 ( 2) 2 ( 3)
APPLICATION SITE BLEEDING 0 0 1 ( 1) 1 ( 1)
APPLICATION SITE DESQUAMATION 0 0 1 ( 1) 1 ( 1)
APPLICATION SITE DISCHARGE 0 1 ( 1) 0 1 ( 1)
APPLICATION SITE DISCOLOURATION 0 0 1 ( 1) 1 ( 1)
APPLICATION SITE INDURATION 1 ( 1) 0 0 1 ( 1)
APPLICATION SITE WARMTH 0 0 1 ( 2) 1 ( 2)
FEELING ABNORMAL 0 1 ( 1) 0 1 ( 1)
FEELING COLD 0 1 ( 1) 0 1 ( 1)
INFLAMMATION 0 0 1 ( 1) 1 ( 1)
SECRETION DISCHARGE 0 0 1 ( 2) 1 ( 2)
SUDDEN DEATH 0 0 1 ( 1) 1 ( 1)
SWELLING 0 0 1 ( 1) 1 ( 1)
ULCER 0 0 1 ( 1) 1 ( 1)
SKIN AND SUBCUTANEOUS TISSUE DISORDERS20 ( 45)39 (100)39 (111) 98 ( 256)
PRURITUS 8 ( 11)25 ( 36)21 ( 31) 54 ( 78)
ERYTHEMA 8 ( 12)14 ( 22)14 ( 22) 36 ( 56)
RASH 5 ( 9) 8 ( 13)13 ( 18) 26 ( 40)
HYPERHIDROSIS 2 ( 2) 8 ( 10) 4 ( 5) 14 ( 17)
SKIN IRRITATION 3 ( 4) 5 ( 8) 6 ( 13) 14 ( 25)
BLISTER 0 1 ( 2) 5 ( 8) 6 ( 10)
RASH PRURITIC 0 2 ( 3) 1 ( 2) 3 ( 5)
PRURITUS GENERALISED 0 1 ( 1) 1 ( 4) 2 ( 5)
URTICARIA 0 1 ( 2) 1 ( 3) 2 ( 5)
ACTINIC KERATOSIS 0 1 ( 1) 0 1 ( 1)
ALOPECIA 1 ( 1) 0 0 1 ( 1)
COLD SWEAT 1 ( 3) 0 0 1 ( 3)
DERMATITIS CONTACT 0 0 1 ( 2) 1 ( 2)
DRUG ERUPTION 1 ( 1) 0 0 1 ( 1)
RASH ERYTHEMATOUS 0 0 1 ( 1) 1 ( 1)
RASH MACULO-PAPULAR 0 1 ( 1) 0 1 ( 1)
SKIN EXFOLIATION 0 0 1 ( 2) 1 ( 2)
SKIN ODOUR ABNORMAL 0 1 ( 1) 0 1 ( 1)
SKIN ULCER 1 ( 2) 0 0 1 ( 2)
NERVOUS SYSTEM DISORDERS 8 ( 11)23 ( 39)22 ( 42) 53 ( 92)
DIZZINESS 2 ( 3)10 ( 14) 9 ( 14) 21 ( 31)
HEADACHE 3 ( 3) 5 ( 8) 3 ( 4) 11 ( 15)
SYNCOPE 0 2 ( 3) 5 ( 7) 7 ( 10)
SOMNOLENCE 2 ( 3) 1 ( 1) 3 ( 5) 6 ( 9)
TRANSIENT ISCHAEMIC ATTACK 0 1 ( 1) 2 ( 3) 3 ( 4)
BURNING SENSATION 0 2 ( 2) 0 2 ( 2)
LETHARGY 0 1 ( 1) 1 ( 1) 2 ( 2)
AMNESIA 0 1 ( 2) 0 1 ( 2)
BALANCE DISORDER 0 0 1 ( 3) 1 ( 3)
COGNITIVE DISORDER 0 1 ( 1) 0 1 ( 1)
COMPLEX PARTIAL SEIZURES 0 0 1 ( 1) 1 ( 1)
COORDINATION ABNORMAL 0 0 1 ( 1) 1 ( 1)
HEMIANOPIA HOMONYMOUS 0 0 1 ( 1) 1 ( 1)
HYPERSOMNIA 0 1 ( 1) 0 1 ( 1)
PARAESTHESIA 0 1 ( 1) 0 1 ( 1)
PARAESTHESIA ORAL 0 0 1 ( 1) 1 ( 1)
PARKINSON'S DISEASE 1 ( 1) 0 0 1 ( 1)
PAROSMIA 0 1 ( 2) 0 1 ( 2)
PARTIAL SEIZURES WITH SECONDARY GENERALISATION 0 1 ( 1) 0 1 ( 1)
PSYCHOMOTOR HYPERACTIVITY 1 ( 1) 0 0 1 ( 1)
STUPOR 0 0 1 ( 1) 1 ( 1)
SYNCOPE VASOVAGAL 0 1 ( 1) 0 1 ( 1)
GASTROINTESTINAL DISORDERS17 ( 26)19 ( 34)15 ( 24) 51 ( 84)
DIARRHOEA 9 ( 10) 3 ( 3) 5 ( 6) 17 ( 19)
VOMITING 3 ( 3) 6 ( 8) 4 ( 5) 13 ( 16)
NAUSEA 3 ( 3) 6 ( 13) 3 ( 5) 12 ( 21)
ABDOMINAL PAIN 1 ( 1) 1 ( 2) 3 ( 3) 5 ( 6)
SALIVARY HYPERSECRETION 0 4 ( 5) 0 4 ( 5)
DYSPEPSIA 1 ( 2) 0 1 ( 2) 2 ( 4)
ABDOMINAL DISCOMFORT 0 1 ( 1) 0 1 ( 1)
CONSTIPATION 1 ( 1) 0 0 1 ( 1)
DYSPHAGIA 0 0 1 ( 1) 1 ( 1)
FLATULENCE 1 ( 2) 0 0 1 ( 2)
GASTROINTESTINAL HAEMORRHAGE 0 1 ( 1) 0 1 ( 1)
GASTROOESOPHAGEAL REFLUX DISEASE 1 ( 1) 0 0 1 ( 1)
GLOSSITIS 1 ( 1) 0 0 1 ( 1)
HIATUS HERNIA 1 ( 2) 0 0 1 ( 2)
RECTAL HAEMORRHAGE 0 0 1 ( 2) 1 ( 2)
STOMACH DISCOMFORT 0 1 ( 1) 0 1 ( 1)
CARDIAC DISORDERS12 ( 26)14 ( 28)14 ( 32) 40 ( 86)
SINUS BRADYCARDIA 2 ( 2) 8 ( 12) 7 ( 10) 17 ( 24)
MYOCARDIAL INFARCTION 4 ( 4) 4 ( 8) 2 ( 4) 10 ( 16)
ATRIAL FIBRILLATION 1 ( 1) 2 ( 3) 2 ( 3) 5 ( 7)
SUPRAVENTRICULAR EXTRASYSTOLES 1 ( 2) 1 ( 1) 1 ( 2) 3 ( 5)
VENTRICULAR EXTRASYSTOLES 0 1 ( 1) 2 ( 4) 3 ( 5)
ATRIAL FLUTTER 0 1 ( 2) 1 ( 1) 2 ( 3)
ATRIOVENTRICULAR BLOCK FIRST DEGREE 1 ( 1) 0 1 ( 1) 2 ( 2)
BUNDLE BRANCH BLOCK RIGHT 1 ( 2) 0 1 ( 1) 2 ( 3)
PALPITATIONS 0 0 2 ( 2) 2 ( 2)
ATRIAL HYPERTROPHY 1 ( 2) 0 0 1 ( 2)
ATRIOVENTRICULAR BLOCK SECOND DEGREE 1 ( 1) 0 0 1 ( 1)
BRADYCARDIA 1 ( 4) 0 0 1 ( 4)
BUNDLE BRANCH BLOCK LEFT 1 ( 1) 0 0 1 ( 1)
CARDIAC DISORDER 0 1 ( 1) 0 1 ( 1)
CARDIAC FAILURE CONGESTIVE 1 ( 1) 0 0 1 ( 1)
SINUS ARRHYTHMIA 1 ( 2) 0 0 1 ( 2)
SUPRAVENTRICULAR TACHYCARDIA 0 0 1 ( 2) 1 ( 2)
TACHYCARDIA 1 ( 2) 0 0 1 ( 2)
VENTRICULAR HYPERTROPHY 1 ( 1) 0 0 1 ( 1)
WOLFF-PARKINSON-WHITE SYNDROME 0 0 1 ( 2) 1 ( 2)
INFECTIONS AND INFESTATIONS16 ( 35)13 ( 20) 9 ( 16) 38 ( 71)
NASOPHARYNGITIS 2 ( 4) 6 ( 8) 4 ( 9) 12 ( 21)
UPPER RESPIRATORY TRACT INFECTION 6 ( 12) 3 ( 5) 1 ( 2) 10 ( 19)
INFLUENZA 1 ( 2) 1 ( 1) 1 ( 1) 3 ( 4)
URINARY TRACT INFECTION 2 ( 4) 1 ( 1) 0 3 ( 5)
CYSTITIS 1 ( 1) 1 ( 1) 0 2 ( 2)
EAR INFECTION 2 ( 4) 0 0 2 ( 4)
BRONCHITIS 1 ( 1) 0 0 1 ( 1)
CELLULITIS 0 0 1 ( 1) 1 ( 1)
CERVICITIS 1 ( 2) 0 0 1 ( 2)
GASTROENTERITIS VIRAL 1 ( 1) 0 0 1 ( 1)
HORDEOLUM 0 1 ( 1) 0 1 ( 1)
LOCALISED INFECTION 1 ( 2) 0 0 1 ( 2)
LOWER RESPIRATORY TRACT INFECTION 0 1 ( 2) 0 1 ( 2)
PNEUMONIA 0 0 1 ( 2) 1 ( 2)
RHINITIS 0 1 ( 1) 0 1 ( 1)
VAGINAL MYCOSIS 1 ( 2) 0 0 1 ( 2)
VIRAL INFECTION 0 0 1 ( 1) 1 ( 1)
PSYCHIATRIC DISORDERS10 ( 12) 7 ( 10)11 ( 15) 28 ( 37)
CONFUSIONAL STATE 2 ( 2) 1 ( 1) 3 ( 3) 6 ( 6)
AGITATION 2 ( 2) 0 3 ( 3) 5 ( 5)
INSOMNIA 2 ( 3) 2 ( 2) 0 4 ( 5)
ANXIETY 0 0 3 ( 4) 3 ( 4)
DELUSION 1 ( 1) 1 ( 1) 0 2 ( 2)
IRRITABILITY 1 ( 2) 0 1 ( 1) 2 ( 3)
COMPLETED SUICIDE 1 ( 1) 0 0 1 ( 1)
DELIRIUM 0 1 ( 1) 0 1 ( 1)
DEPRESSED MOOD 0 0 1 ( 2) 1 ( 2)
DISORIENTATION 1 ( 1) 0 0 1 ( 1)
HALLUCINATION 0 1 ( 1) 0 1 ( 1)
HALLUCINATION, VISUAL 0 1 ( 1) 0 1 ( 1)
LIBIDO DECREASED 0 1 ( 1) 0 1 ( 1)
LISTLESS 0 1 ( 1) 0 1 ( 1)
NIGHTMARE 0 1 ( 1) 0 1 ( 1)
RESTLESSNESS 0 0 1 ( 2) 1 ( 2)
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS 8 ( 12)10 ( 22) 9 ( 14) 27 ( 48)
COUGH 1 ( 1) 5 ( 7) 5 ( 7) 11 ( 15)
NASAL CONGESTION 3 ( 3) 3 ( 4) 1 ( 1) 7 ( 8)
DYSPNOEA 1 ( 1) 1 ( 1) 1 ( 1) 3 ( 3)
EPISTAXIS 0 2 ( 2) 1 ( 1) 3 ( 3)
PHARYNGOLARYNGEAL PAIN 0 1 ( 1) 1 ( 1) 2 ( 2)
RHINORRHOEA 0 1 ( 2) 1 ( 2) 2 ( 4)
ALLERGIC GRANULOMATOUS ANGIITIS 0 1 ( 1) 0 1 ( 1)
DYSPHONIA 0 0 1 ( 1) 1 ( 1)
EMPHYSEMA 1 ( 1) 0 0 1 ( 1)
HAEMOPTYSIS 1 ( 2) 0 0 1 ( 2)
PHARYNGEAL ERYTHEMA 0 1 ( 2) 0 1 ( 2)
POSTNASAL DRIP 1 ( 2) 0 0 1 ( 2)
PRODUCTIVE COUGH 0 1 ( 1) 0 1 ( 1)
RALES 1 ( 2) 0 0 1 ( 2)
RESPIRATORY TRACT CONGESTION 0 1 ( 1) 0 1 ( 1)
INVESTIGATIONS10 ( 19) 5 ( 6) 7 ( 9) 22 ( 34)
ELECTROCARDIOGRAM ST SEGMENT DEPRESSION 4 ( 4) 0 1 ( 2) 5 ( 6)
ELECTROCARDIOGRAM T WAVE INVERSION 2 ( 3) 1 ( 1) 1 ( 1) 4 ( 5)
BLOOD GLUCOSE INCREASED 0 1 ( 2) 1 ( 1) 2 ( 3)
ELECTROCARDIOGRAM T WAVE AMPLITUDE DECREASED 1 ( 1) 0 1 ( 1) 2 ( 2)
BIOPSY 0 1 ( 1) 0 1 ( 1)
BIOPSY PROSTATE 0 1 ( 1) 0 1 ( 1)
BLOOD ALKALINE PHOSPHATASE INCREASED 1 ( 1) 0 0 1 ( 1)
BLOOD CHOLESTEROL INCREASED 0 1 ( 1) 0 1 ( 1)
BLOOD CREATINE PHOSPHOKINASE INCREASED 1 ( 2) 0 0 1 ( 2)
BLOOD URINE PRESENT 1 ( 1) 0 0 1 ( 1)
BODY TEMPERATURE INCREASED 0 0 1 ( 1) 1 ( 1)
CYSTOSCOPY 1 ( 1) 0 0 1 ( 1)
HEART RATE INCREASED 1 ( 2) 0 0 1 ( 2)
HEART RATE IRREGULAR 1 ( 4) 0 0 1 ( 4)
NASAL MUCOSA BIOPSY 0 0 1 ( 1) 1 ( 1)
WEIGHT DECREASED 0 0 1 ( 2) 1 ( 2)
MUSCULOSKELETAL AND CONNECTIVE TISSUE DISORDERS 4 ( 6) 7 ( 10) 7 ( 10) 18 ( 26)
BACK PAIN 1 ( 2) 3 ( 4) 1 ( 1) 5 ( 7)
ARTHRALGIA 1 ( 1) 1 ( 1) 2 ( 4) 4 ( 6)
SHOULDER PAIN 1 ( 2) 0 2 ( 2) 3 ( 4)
MUSCLE SPASMS 0 1 ( 2) 1 ( 1) 2 ( 3)
ARTHRITIS 0 1 ( 1) 0 1 ( 1)
FLANK PAIN 0 1 ( 1) 0 1 ( 1)
MUSCULAR WEAKNESS 0 0 1 ( 2) 1 ( 2)
MYALGIA 0 1 ( 1) 0 1 ( 1)
PAIN IN EXTREMITY 1 ( 1) 0 0 1 ( 1)
INJURY, POISONING AND PROCEDURAL COMPLICATIONS 4 ( 9) 5 ( 8) 5 ( 12) 14 ( 29)
CONTUSION 1 ( 1) 2 ( 3) 1 ( 3) 4 ( 7)
EXCORIATION 2 ( 3) 1 ( 1) 1 ( 2) 4 ( 6)
FALL 1 ( 2) 1 ( 1) 2 ( 2) 4 ( 5)
HIP FRACTURE 1 ( 2) 2 ( 2) 0 3 ( 4)
SKIN LACERATION 1 ( 1) 0 2 ( 2) 3 ( 3)
FACIAL BONES FRACTURE 0 1 ( 1) 0 1 ( 1)
JOINT DISLOCATION 0 0 1 ( 1) 1 ( 1)
WOUND 0 0 1 ( 2) 1 ( 2)
RENAL AND URINARY DISORDERS 4 ( 5) 3 ( 4) 3 ( 3) 10 ( 12)
MICTURITION URGENCY 1 ( 1) 1 ( 2) 1 ( 1) 3 ( 4)
DYSURIA 1 ( 1) 0 1 ( 1) 2 ( 2)
NEPHROLITHIASIS 1 ( 1) 1 ( 1) 0 2 ( 2)
CALCULUS URETHRAL 0 1 ( 1) 0 1 ( 1)
INCONTINENCE 0 0 1 ( 1) 1 ( 1)
POLLAKIURIA 1 ( 2) 0 0 1 ( 2)
METABOLISM AND NUTRITION DISORDERS 6 ( 8) 2 ( 4) 1 ( 1) 9 ( 13)
DECREASED APPETITE 1 ( 2) 1 ( 2) 0 2 ( 4)
FOOD CRAVING 1 ( 1) 0 1 ( 1) 2 ( 2)
INCREASED APPETITE 1 ( 2) 1 ( 2) 0 2 ( 4)
DEHYDRATION 1 ( 1) 0 0 1 ( 1)
DIABETES MELLITUS 1 ( 1) 0 0 1 ( 1)
HYPONATRAEMIA 1 ( 1) 0 0 1 ( 1)
VASCULAR DISORDERS 3 ( 7) 1 ( 1) 3 ( 3) 7 ( 11)
HYPOTENSION 2 ( 3) 0 1 ( 1) 3 ( 4)
HYPERTENSION 1 ( 2) 0 1 ( 1) 2 ( 3)
HOT FLUSH 0 0 1 ( 1) 1 ( 1)
ORTHOSTATIC HYPOTENSION 1 ( 2) 0 0 1 ( 2)
WOUND HAEMORRHAGE 0 1 ( 1) 0 1 ( 1)
EYE DISORDERS 2 ( 5) 1 ( 2) 2 ( 2) 5 ( 9)
VISION BLURRED 0 1 ( 2) 1 ( 1) 2 ( 3)
CONJUNCTIVAL HAEMORRHAGE 0 0 1 ( 1) 1 ( 1)
CONJUNCTIVITIS 1 ( 2) 0 0 1 ( 2)
EYE ALLERGY 1 ( 1) 0 0 1 ( 1)
EYE PRURITUS 1 ( 1) 0 0 1 ( 1)
EYE SWELLING 1 ( 1) 0 0 1 ( 1)
SURGICAL AND MEDICAL PROCEDURES 2 ( 2) 2 ( 2) 1 ( 1) 5 ( 5)
CATARACT OPERATION 1 ( 1) 0 1 ( 1) 2 ( 2)
ACROCHORDON EXCISION 0 1 ( 1) 0 1 ( 1)
EYE LASER SURGERY 1 ( 1) 0 0 1 ( 1)
SKIN LESION EXCISION 0 1 ( 1) 0 1 ( 1)
EAR AND LABYRINTH DISORDERS 1 ( 2) 1 ( 1) 2 ( 2) 4 ( 5)
VERTIGO 0 1 ( 1) 1 ( 1) 2 ( 2)
CERUMEN IMPACTION 0 0 1 ( 1) 1 ( 1)
EAR PAIN 1 ( 2) 0 0 1 ( 2)
CONGENITAL, FAMILIAL AND GENETIC DISORDERS 0 2 ( 2) 1 ( 1) 3 ( 3)
VENTRICULAR SEPTAL DEFECT 0 2 ( 2) 1 ( 1) 3 ( 3)
NEOPLASMS BENIGN, MALIGNANT AND UNSPECIFIED (INCL CYSTS AND POLYPS) 0 1 ( 1) 2 ( 3) 3 ( 4)
COLON CANCER 0 0 1 ( 1) 1 ( 1)
MALIGNANT FIBROUS HISTIOCYTOMA 0 0 1 ( 2) 1 ( 2)
PROSTATE CANCER 0 1 ( 1) 0 1 ( 1)
REPRODUCTIVE SYSTEM AND BREAST DISORDERS 2 ( 4) 1 ( 1) 0 3 ( 5)
BENIGN PROSTATIC HYPERPLASIA 1 ( 2) 1 ( 1) 0 2 ( 3)
PELVIC PAIN 1 ( 2) 0 0 1 ( 2)
HEPATOBILIARY DISORDERS 1 ( 1) 0 0 1 ( 1)
HYPERBILIRUBINAEMIA 1 ( 1) 0 0 1 ( 1)
IMMUNE SYSTEM DISORDERS 0 0 1 ( 2) 1 ( 2)
HYPERSENSITIVITY 0 0 1 ( 2) 1 ( 2)
SOCIAL CIRCUMSTANCES 0 1 ( 1) 0 1 ( 1)
ALCOHOL USE 0 1 ( 1) 0 1 ( 1)
TEAE = Treatment-Emergent Adverse Event.
Values displayed as: n_subjects (n_events).
Subjects are counted once per SOC and once per PT; events are total occurrences.
Percentages not shown — denominators differ for subjects vs events.
SOC and PT sorted by descending subject frequency.
/opt/quarto/share/rmd/rmd.R 01APR2026 09:51:55
Source Code
---
title: "Adverse Events with Event Counts"
subtitle: "Summary of Treatment-Emergent Adverse Events with Event Counts"
execute:
  echo: true
  eval: true
---


```{r}
#| label: prereqs
#| include: false
library(arframe)
fr_theme(hlines = "header", font_family = "Courier New")
blank_to_na <- function(df) {
  df[] <- lapply(df, function(x) {
    if (is.character(x)) x[x == ""] <- NA_character_
    x
  })
  df
}
```

## Setup

See [Prerequisites](../install.qmd) for installation instructions.

```{r}
#| label: setup
library(arframe)
library(pharmaverseadam)
library(dplyr, warn.conflicts = FALSE)
library(tidyr)
library(cards)

adsl_saf <- pharmaverseadam::adsl |>
  blank_to_na() |>
  filter(SAFFL == "Y", TRT01A != "Screen Failure")

adae_teae <- pharmaverseadam::adae |>
  blank_to_na() |>
  filter(TRTEMFL == "Y", TRT01A != "Screen Failure")

arm_levels <- c("Placebo", "Xanomeline Low Dose", "Xanomeline High Dose")

arm_n <- adsl_saf |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A) |>
  pull(n, name = TRT01A)
arm_n <- arm_n[arm_levels]

N_total <- nrow(adsl_saf)
n_vec <- c(arm_n, Total = N_total)
```


## Data Preparation

::: {.panel-tabset}

### dplyr

```{r}
#| label: dplyr-code

# Format: "n_subjects (n_events)"
subj_events <- function(n_subj, n_events) {
  sprintf("%d (%d)", n_subj, n_events)
}

# ── Any TEAE (overall row) ──
any_subj_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A) |>
  count(TRT01A, name = "n_subj")

any_events_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A, name = "n_events")

any_arm <- left_join(any_subj_arm, any_events_arm, by = "TRT01A") |>
  mutate(value = mapply(subj_events, n_subj, n_events)) |>
  select(TRT01A, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

any_total <- tibble(
  Total = subj_events(
    n_distinct(adae_teae$USUBJID),
    nrow(adae_teae)
  )
)

any_row <- bind_cols(
  tibble(soc = "Any TEAE", pt = "Any TEAE", row_type = "overall"),
  any_arm,
  any_total
)

# ── SOC-level: subjects and events ──
soc_subj_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS) |>
  count(TRT01A, AEBODSYS, name = "n_subj")

soc_events_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A, AEBODSYS, name = "n_events")

soc_arm <- left_join(soc_subj_arm, soc_events_arm, by = c("TRT01A", "AEBODSYS")) |>
  mutate(value = mapply(subj_events, n_subj, n_events)) |>
  select(TRT01A, AEBODSYS, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

soc_subj_total <- adae_teae |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "n_subj")

soc_events_total <- adae_teae |>
  count(AEBODSYS, name = "n_events")

soc_total <- left_join(soc_subj_total, soc_events_total, by = "AEBODSYS") |>
  mutate(Total = mapply(subj_events, n_subj, n_events)) |>
  select(AEBODSYS, Total)

soc_wide <- left_join(soc_arm, soc_total, by = "AEBODSYS") |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEBODSYS,
    row_type = "soc",
    .before  = 1
  ) |>
  select(-AEBODSYS)

# ── PT-level: subjects and events ──
pt_subj_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS, AEDECOD) |>
  count(TRT01A, AEBODSYS, AEDECOD, name = "n_subj")

pt_events_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  count(TRT01A, AEBODSYS, AEDECOD, name = "n_events")

pt_arm <- left_join(pt_subj_arm, pt_events_arm, by = c("TRT01A", "AEBODSYS", "AEDECOD")) |>
  mutate(value = mapply(subj_events, n_subj, n_events)) |>
  select(TRT01A, AEBODSYS, AEDECOD, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

pt_subj_total <- adae_teae |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "n_subj")

pt_events_total <- adae_teae |>
  count(AEBODSYS, AEDECOD, name = "n_events")

pt_total <- left_join(pt_subj_total, pt_events_total, by = c("AEBODSYS", "AEDECOD")) |>
  mutate(Total = mapply(subj_events, n_subj, n_events)) |>
  select(AEBODSYS, AEDECOD, Total)

pt_wide <- left_join(pt_arm, pt_total, by = c("AEBODSYS", "AEDECOD")) |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEDECOD,
    row_type = "pt",
    .before  = 1
  ) |>
  select(-AEBODSYS, -AEDECOD)

# ── Sort by descending subject frequency ──
soc_order <- adae_teae |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "soc_n") |>
  arrange(desc(soc_n)) |>
  pull(AEBODSYS)

pt_sorted <- adae_teae |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "pt_n") |>
  arrange(match(AEBODSYS, soc_order), desc(pt_n))

pt_wide <- pt_sorted |>
  select(soc = AEBODSYS, pt = AEDECOD) |>
  left_join(pt_wide, by = c("soc", "pt"))

# ── Interleave ──
ae_events_wide <- bind_rows(
  any_row,
  bind_rows(
    lapply(soc_order, function(s) {
      bind_rows(
        filter(soc_wide, soc == s),
        filter(pt_wide, soc == s)
      )
    })
  )
) |>
  mutate(across(
    where(is.character) & !c(soc, pt, row_type),
    ~ replace_na(.x, "0 (0)")
  ))
```

### cards

```{r}
#| label: cards-code

# cards ard_stack_hierarchical provides subject counts
# We supplement with event counts via manual aggregation
ae_subj_ard <- ard_stack_hierarchical(
  data        = adae_teae |> filter(TRT01A %in% arm_levels),
  variables   = c(AEBODSYS, AEDECOD),
  by          = TRT01A,
  denominator = adsl_saf,
  id          = USUBJID,
  overall     = TRUE,
  over_variables = FALSE
) |>
  sort_ard_hierarchical(sort = "descending")

# Note: cards output has subject counts only (no event counts)
# Use a separate variable to avoid overwriting the dplyr output
ae_events_cards <- fr_wide_ard(
  ae_subj_ard,
  statistic = "{n}",
  label     = c(
    AEBODSYS = "System Organ Class",
    AEDECOD  = "Preferred Term"
  )
)
```

:::


## arframe Pipeline

The rendered table below uses the **dplyr** data prep (`ae_events_wide`, with subject + event counts). The cards tab produces `ae_events_cards` (subject counts only) — swap it in to use the cards path instead.

```{r}
#| label: pipeline
#| eval: false
ae_events_wide |>
  fr_table() |>
  fr_titles(
    "Table 14.3.2",
    "Summary of Treatment-Emergent Adverse Events with Event Counts",
    "Safety Population"
  ) |>
  fr_cols(
    soc      = fr_col(visible = FALSE),
    pt       = fr_col("System Organ Class\n  Preferred Term", width = 3.5),
    row_type = fr_col(visible = FALSE),
    !!!setNames(
      lapply(arm_levels, function(a) fr_col(a, align = "decimal")),
      arm_levels
    ),
    Total = fr_col("Total", align = "decimal"),
    .n = n_vec
  ) |>
  fr_header(bold = TRUE, align = "center") |>
  fr_rows(
    group_by  = "soc",
    indent_by = "pt"
  ) |>
  fr_styles(
    fr_row_style(rows = fr_rows_matches("row_type", value = "soc"), bold = TRUE),
    fr_row_style(rows = fr_rows_matches("row_type", value = "overall"), bold = TRUE)
  ) |>
  fr_footnotes(
    "TEAE = Treatment-Emergent Adverse Event.",
    "Values displayed as: n_subjects (n_events).",
    "Subjects are counted once per SOC and once per PT; events are total occurrences.",
    "Percentages not shown \u2014 denominators differ for subjects vs events.",
    "SOC and PT sorted by descending subject frequency."
  )
```


## Rendered Table

```{r}
#| label: rendered-table
#| echo: false
#| ref.label: pipeline
```

Open-source TFL reference collection

 

CDISC Pilot Study (CDISCPILOT01) • pharmaverseadam datasets