arframe TFL Gallery
  1. Tables
  2. Adverse Events by Grade / Intensity
  • 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 by Grade / Intensity

Adverse Events by Grade / Intensity

Summary of Treatment-Emergent Adverse Events by SOC, PT, and Severity Grade

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") |>
  mutate(AESEV = factor(AESEV, levels = c("MILD", "MODERATE", "SEVERE")))

arm_levels <- c("Placebo", "Xanomeline Low Dose", "Xanomeline High Dose")
sev_levels <- levels(adae_teae$AESEV)

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)

Data Preparation

  • dplyr
  • cards
n_pct <- function(n, denom) sprintf("%d (%.1f)", n, n / denom * 100)

# ── Column names: Placebo_MILD, Placebo_MODERATE, ... ──
col_names <- unlist(lapply(arm_levels, function(a) {
  paste(gsub(" ", "_", a), sev_levels, sep = "_")
}))

# ── Helper: pivot arm×sev to wide, preserving any non-TRT01A/AESEV/value cols ──
pivot_arm_sev <- function(df, value_col = "value") {
  id_cols <- setdiff(names(df), c("TRT01A", "AESEV", value_col))
  df |>
    mutate(col = paste(gsub(" ", "_", TRT01A), AESEV, sep = "_")) |>
    select(all_of(id_cols), col, all_of(value_col)) |>
    pivot_wider(names_from = col, values_from = all_of(value_col))
}

# ── SOC × severity ──
soc_sev_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS, AESEV) |>
  count(TRT01A, AEBODSYS, AESEV, .drop = FALSE) |>
  filter(!is.na(AEBODSYS)) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, AESEV, value) |>
  pivot_arm_sev()

soc_wide <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "soc_n") |>
  left_join(soc_sev_arm, by = "AEBODSYS") |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEBODSYS,
    row_type = "soc",
    .before  = 1
  ) |>
  select(-AEBODSYS, -soc_n)

# ── PT × severity ──
pt_sev_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS, AEDECOD, AESEV) |>
  count(TRT01A, AEBODSYS, AEDECOD, AESEV, .drop = FALSE) |>
  filter(!is.na(AEBODSYS), !is.na(AEDECOD)) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, AEDECOD, AESEV, value) |>
  pivot_arm_sev()

pt_wide <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "pt_n") |>
  left_join(pt_sev_arm, by = c("AEBODSYS", "AEDECOD")) |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEDECOD,
    row_type = "pt",
    .before  = 1
  ) |>
  select(-AEBODSYS, -AEDECOD, -pt_n)

# ── Sort order ──
soc_order <- adae_teae |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "n") |>
  arrange(desc(n)) |>
  pull(AEBODSYS)

pt_order <- adae_teae |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "n") |>
  arrange(match(AEBODSYS, soc_order), desc(n)) |>
  select(soc = AEBODSYS, pt = AEDECOD)

pt_wide <- pt_order |>
  left_join(pt_wide, by = c("soc", "pt"))

# ── Interleave SOC + PT rows ──
ae_grade_wide <- bind_rows(
  lapply(soc_order, function(s) {
    bind_rows(
      filter(soc_wide, soc == s),
      filter(pt_wide, soc == s)
    )
  })
) |>
  mutate(across(all_of(col_names), ~ replace_na(.x, "0 (0.0)")))

n_vec <- arm_n
ae_grade_ard <- ard_stack_hierarchical(
  data        = adae_teae |> filter(AESEV %in% sev_levels),
  variables   = c(AEBODSYS, AEDECOD),
  by          = c(TRT01A, AESEV),
  denominator = adsl_saf,
  id          = USUBJID,
  overall     = FALSE
) |>
  sort_ard_hierarchical(sort = "descending")

# Note: cards output has a different layout (AESEV as page_by)
# than the dplyr path (arm × grade column spans matching DPP shell)
ae_grade_cards <- fr_wide_ard(
  ae_grade_ard,
  statistic = "{n} ({p}%)",
  decimals  = c(p = 1),
  label     = c(
    AEBODSYS = "System Organ Class",
    AEDECOD  = "Preferred Term"
  )
)

arframe Pipeline

The rendered table below uses the dplyr data prep (ae_grade_wide, arm x severity columns with spans). The cards tab produces ae_grade_cards with a different layout — see the cards tab for details.

# Build fr_col() list for arm × severity columns
sev_cols <- unlist(lapply(arm_levels, function(a) {
  setNames(
    lapply(sev_levels, function(s) {
      fr_col(tools::toTitleCase(tolower(s)), align = "decimal")
    }),
    paste(gsub(" ", "_", a), sev_levels, sep = "_")
  )
}), recursive = FALSE)

ae_grade_wide |>
  fr_table() |>
  fr_titles(
    "Table 14.3.4",
    "Summary of Treatment-Emergent Adverse Events by SOC, Preferred Term, and Severity Grade",
    "Safety Population"
  ) |>
  fr_cols(
    soc      = fr_col(visible = FALSE),
    pt       = fr_col("System Organ Class\n  Preferred Term", width = 3.0),
    row_type = fr_col(visible = FALSE),
    !!!sev_cols,
    .n = n_vec
  ) |>
  fr_spans(
    !!!setNames(
      lapply(arm_levels, function(a) {
        paste(gsub(" ", "_", a), sev_levels, sep = "_")
      }),
      arm_levels
    )
  ) |>
  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_footnotes(
    "TEAE = Treatment-Emergent Adverse Event. Subjects counted once per SOC×grade and once per PT×grade.",
    "Severity grade: MILD, MODERATE, SEVERE as recorded in AESEV.",
    "Percentages based on N per treatment arm (Safety Population).",
    "SOC rows sorted by descending subject frequency; PT rows sorted within SOC by descending frequency."
  )

Rendered Table

Table 14.3.4
Summary of Treatment-Emergent Adverse Events by SOC, Preferred Term, and Severity Grade
Safety Population
Placebo
(N=86)
Xanomeline High Dose
(N=72)
Xanomeline Low Dose
(N=96)
System Organ Class
Preferred Term
MildModerateSevereMildModerateSevereMildModerateSevere
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS20 (23.3)5 (5.8)0 31 (43.1)19 (26.4)0 35 (36.5)27 (28.1)7 (7.3)
APPLICATION SITE PRURITUS 6 ( 7.0)1 (1.2)0 17 (23.6)11 (15.3)0 19 (19.8)10 (10.4)1 (1.0)
APPLICATION SITE ERYTHEMA 3 ( 3.5)0 0 12 (16.7) 5 ( 6.9)0 9 ( 9.4) 8 ( 8.3)2 (2.1)
APPLICATION SITE DERMATITIS 5 ( 5.8)0 0 6 ( 8.3) 5 ( 6.9)0 7 ( 7.3) 4 ( 4.2)1 (1.0)
APPLICATION SITE IRRITATION 2 ( 2.3)2 (2.3)0 8 (11.1) 6 ( 8.3)0 5 ( 5.2) 6 ( 6.2)3 (3.1)
APPLICATION SITE VESICLES 1 ( 1.2)0 0 2 ( 2.8) 3 ( 4.2)0 3 ( 3.1) 2 ( 2.1)0
FATIGUE 1 ( 1.2)0 0 5 ( 6.9) 0 0 3 ( 3.1) 2 ( 2.1)0
OEDEMA PERIPHERAL 2 ( 2.3)0 0 1 ( 1.4) 1 ( 1.4)0 0 1 ( 1.0)0
APPLICATION SITE SWELLING 0 0 0 1 ( 1.4) 1 ( 1.4)0 1 ( 1.0) 0 0
APPLICATION SITE URTICARIA 0 0 0 0 1 ( 1.4)0 2 ( 2.1) 0 0
CHILLS 0 1 (1.2)0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
MALAISE 0 0 0 2 ( 2.8) 1 ( 1.4)0 1 ( 1.0) 0 0
PYREXIA 2 ( 2.3)0 0 0 0 0 1 ( 1.0) 0 0
APPLICATION SITE PAIN 0 0 0 1 ( 1.4) 1 ( 1.4)0 0 0 0
APPLICATION SITE PERSPIRATION 0 0 0 1 ( 1.4) 1 ( 1.4)0 0 0 0
APPLICATION SITE REACTION 1 ( 1.2)1 (1.2)0 0 1 ( 1.4)0 0 0 0
ASTHENIA 1 ( 1.2)1 (1.2)0 0 0 0 0 1 ( 1.0)0
CHEST DISCOMFORT 0 0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
CHEST PAIN 0 0 0 2 ( 2.8) 0 0 0 0 0
OEDEMA 0 0 0 0 0 0 2 ( 2.1) 0 0
PAIN 0 0 0 1 ( 1.4) 0 0 0 1 ( 1.0)0
APPLICATION SITE BLEEDING 0 0 0 0 0 0 0 1 ( 1.0)0
APPLICATION SITE DESQUAMATION 0 0 0 0 0 0 1 ( 1.0) 0 0
APPLICATION SITE DISCHARGE 0 0 0 0 1 ( 1.4)0 0 0 0
APPLICATION SITE DISCOLOURATION 0 0 0 0 0 0 0 1 ( 1.0)0
APPLICATION SITE INDURATION 1 ( 1.2)0 0 0 0 0 0 0 0
APPLICATION SITE WARMTH 0 0 0 0 0 0 0 1 ( 1.0)1 (1.0)
FEELING ABNORMAL 0 0 0 1 ( 1.4) 0 0 0 0 0
FEELING COLD 0 0 0 1 ( 1.4) 0 0 0 0 0
INFLAMMATION 0 0 0 0 0 0 0 1 ( 1.0)0
SECRETION DISCHARGE 0 0 0 0 0 0 1 ( 1.0) 0 0
SUDDEN DEATH 0 0 0 0 0 0 0 0 1 (1.0)
SWELLING 0 0 0 0 0 0 0 1 ( 1.0)0
ULCER 0 0 0 0 0 0 0 1 ( 1.0)0
SKIN AND SUBCUTANEOUS TISSUE DISORDERS18 (20.9)8 (9.3)0 35 (48.6)15 (20.8)1 (1.4)19 (19.8)26 (27.1)4 (4.2)
PRURITUS 8 ( 9.3)1 (1.2)0 19 (26.4) 9 (12.5)0 11 (11.5)12 (12.5)1 (1.0)
ERYTHEMA 6 ( 7.0)4 (4.7)0 12 (16.7) 4 ( 5.6)0 7 ( 7.3) 8 ( 8.3)0
RASH 4 ( 4.7)3 (3.5)0 6 ( 8.3) 2 ( 2.8)1 (1.4)11 (11.5) 3 ( 3.1)1 (1.0)
HYPERHIDROSIS 2 ( 2.3)0 0 8 (11.1) 0 0 1 ( 1.0) 3 ( 3.1)0
SKIN IRRITATION 2 ( 2.3)1 (1.2)0 5 ( 6.9) 2 ( 2.8)0 2 ( 2.1) 4 ( 4.2)1 (1.0)
BLISTER 0 0 0 1 ( 1.4) 0 0 1 ( 1.0) 4 ( 4.2)1 (1.0)
RASH PRURITIC 0 0 0 1 ( 1.4) 1 ( 1.4)0 0 1 ( 1.0)0
PRURITUS GENERALISED 0 0 0 1 ( 1.4) 0 0 0 1 ( 1.0)0
URTICARIA 0 0 0 1 ( 1.4) 0 0 1 ( 1.0) 1 ( 1.0)0
ACTINIC KERATOSIS 0 0 0 1 ( 1.4) 0 0 0 0 0
ALOPECIA 1 ( 1.2)0 0 0 0 0 0 0 0
COLD SWEAT 0 1 (1.2)0 0 0 0 0 0 0
DERMATITIS CONTACT 0 0 0 0 0 0 0 1 ( 1.0)0
DRUG ERUPTION 1 ( 1.2)0 0 0 0 0 0 0 0
RASH ERYTHEMATOUS 0 0 0 0 0 0 0 1 ( 1.0)0
RASH MACULO-PAPULAR 0 0 0 1 ( 1.4) 0 0 0 0 0
SKIN EXFOLIATION 0 0 0 0 0 0 0 1 ( 1.0)0
SKIN ODOUR ABNORMAL 0 0 0 1 ( 1.4) 0 0 0 0 0
SKIN ULCER 0 1 (1.2)0 0 0 0 0 0 0
NERVOUS SYSTEM DISORDERS 6 ( 7.0)2 (2.3)0 18 (25.0) 8 (11.1)4 (5.6)15 (15.6) 9 ( 9.4)3 (3.1)
DIZZINESS 2 ( 2.3)0 0 7 ( 9.7) 3 ( 4.2)1 (1.4) 7 ( 7.3) 3 ( 3.1)0
HEADACHE 3 ( 3.5)0 0 5 ( 6.9) 1 ( 1.4)0 2 ( 2.1) 0 1 (1.0)
SYNCOPE 0 0 0 0 2 ( 2.8)1 (1.4) 1 ( 1.0) 2 ( 2.1)2 (2.1)
SOMNOLENCE 0 2 (2.3)0 1 ( 1.4) 0 0 2 ( 2.1) 2 ( 2.1)0
TRANSIENT ISCHAEMIC ATTACK 0 0 0 0 0 1 (1.4) 1 ( 1.0) 0 1 (1.0)
BURNING SENSATION 0 0 0 1 ( 1.4) 1 ( 1.4)0 0 0 0
LETHARGY 0 0 0 0 1 ( 1.4)0 0 1 ( 1.0)0
AMNESIA 0 0 0 1 ( 1.4) 0 0 0 0 0
BALANCE DISORDER 0 0 0 0 0 0 1 ( 1.0) 1 ( 1.0)0
COGNITIVE DISORDER 0 0 0 1 ( 1.4) 0 0 0 0 0
COMPLEX PARTIAL SEIZURES 0 0 0 0 0 0 0 1 ( 1.0)0
COORDINATION ABNORMAL 0 0 0 0 0 0 1 ( 1.0) 0 0
HEMIANOPIA HOMONYMOUS 0 0 0 0 0 0 1 ( 1.0) 0 0
HYPERSOMNIA 0 0 0 1 ( 1.4) 0 0 0 0 0
PARAESTHESIA 0 0 0 1 ( 1.4) 0 0 0 0 0
PARAESTHESIA ORAL 0 0 0 0 0 0 1 ( 1.0) 0 0
PARKINSON'S DISEASE 1 ( 1.2)0 0 0 0 0 0 0 0
PAROSMIA 0 0 0 1 ( 1.4) 0 0 0 0 0
PARTIAL SEIZURES WITH SECONDARY GENERALISATION 0 0 0 0 0 1 (1.4) 0 0 0
PSYCHOMOTOR HYPERACTIVITY 1 ( 1.2)0 0 0 0 0 0 0 0
STUPOR 0 0 0 0 0 0 0 0 1 (1.0)
SYNCOPE VASOVAGAL 0 0 0 0 1 ( 1.4)0 0 0 0
GASTROINTESTINAL DISORDERS15 (17.4)2 (2.3)0 16 (22.2) 4 ( 5.6)2 (2.8)10 (10.4) 5 ( 5.2)0
DIARRHOEA 9 (10.5)0 0 2 ( 2.8) 1 ( 1.4)0 4 ( 4.2) 1 ( 1.0)0
VOMITING 2 ( 2.3)1 (1.2)0 5 ( 6.9) 1 ( 1.4)0 2 ( 2.1) 2 ( 2.1)0
NAUSEA 2 ( 2.3)1 (1.2)0 5 ( 6.9) 1 ( 1.4)1 (1.4) 2 ( 2.1) 1 ( 1.0)0
ABDOMINAL PAIN 1 ( 1.2)0 0 1 ( 1.4) 1 ( 1.4)0 2 ( 2.1) 1 ( 1.0)0
SALIVARY HYPERSECRETION 0 0 0 4 ( 5.6) 0 0 0 0 0
DYSPEPSIA 1 ( 1.2)0 0 0 0 0 0 1 ( 1.0)0
ABDOMINAL DISCOMFORT 0 0 0 1 ( 1.4) 0 0 0 0 0
CONSTIPATION 1 ( 1.2)0 0 0 0 0 0 0 0
DYSPHAGIA 0 0 0 0 0 0 0 1 ( 1.0)0
FLATULENCE 1 ( 1.2)0 0 0 0 0 0 0 0
GASTROINTESTINAL HAEMORRHAGE 0 0 0 0 0 1 (1.4) 0 0 0
GASTROOESOPHAGEAL REFLUX DISEASE 1 ( 1.2)0 0 0 0 0 0 0 0
GLOSSITIS 1 ( 1.2)0 0 0 0 0 0 0 0
HIATUS HERNIA 0 1 (1.2)0 0 0 0 0 0 0
RECTAL HAEMORRHAGE 0 0 0 0 0 0 1 ( 1.0) 0 0
STOMACH DISCOMFORT 0 0 0 1 ( 1.4) 0 0 0 0 0
CARDIAC DISORDERS10 (11.6)3 (3.5)2 (2.3) 8 (11.1) 5 ( 6.9)1 (1.4)12 (12.5) 5 ( 5.2)0
SINUS BRADYCARDIA 1 ( 1.2)1 (1.2)0 4 ( 5.6) 4 ( 5.6)0 6 ( 6.2) 1 ( 1.0)0
MYOCARDIAL INFARCTION 1 ( 1.2)1 (1.2)2 (2.3) 3 ( 4.2) 1 ( 1.4)0 2 ( 2.1) 0 0
ATRIAL FIBRILLATION 0 1 (1.2)0 1 ( 1.4) 0 1 (1.4) 1 ( 1.0) 1 ( 1.0)0
SUPRAVENTRICULAR EXTRASYSTOLES 1 ( 1.2)0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
VENTRICULAR EXTRASYSTOLES 0 0 0 1 ( 1.4) 0 0 1 ( 1.0) 1 ( 1.0)0
ATRIAL FLUTTER 0 0 0 1 ( 1.4) 0 0 0 1 ( 1.0)0
ATRIOVENTRICULAR BLOCK FIRST DEGREE 1 ( 1.2)0 0 0 0 0 1 ( 1.0) 0 0
BUNDLE BRANCH BLOCK RIGHT 1 ( 1.2)0 0 0 0 0 0 1 ( 1.0)0
PALPITATIONS 0 0 0 0 0 0 0 2 ( 2.1)0
ATRIAL HYPERTROPHY 1 ( 1.2)0 0 0 0 0 0 0 0
ATRIOVENTRICULAR BLOCK SECOND DEGREE 1 ( 1.2)0 0 0 0 0 0 0 0
BRADYCARDIA 1 ( 1.2)0 0 0 0 0 0 0 0
BUNDLE BRANCH BLOCK LEFT 1 ( 1.2)0 0 0 0 0 0 0 0
CARDIAC DISORDER 0 0 0 1 ( 1.4) 0 0 0 0 0
CARDIAC FAILURE CONGESTIVE 0 1 (1.2)0 0 0 0 0 0 0
SINUS ARRHYTHMIA 1 ( 1.2)0 0 0 0 0 0 0 0
SUPRAVENTRICULAR TACHYCARDIA 0 0 0 0 0 0 0 1 ( 1.0)0
TACHYCARDIA 1 ( 1.2)1 (1.2)0 0 0 0 0 0 0
VENTRICULAR HYPERTROPHY 1 ( 1.2)0 0 0 0 0 0 0 0
WOLFF-PARKINSON-WHITE SYNDROME 0 0 0 0 0 0 1 ( 1.0) 0 0
INFECTIONS AND INFESTATIONS12 (14.0)5 (5.8)0 10 (13.9) 3 ( 4.2)0 7 ( 7.3) 2 ( 2.1)1 (1.0)
NASOPHARYNGITIS 1 ( 1.2)1 (1.2)0 5 ( 6.9) 1 ( 1.4)0 4 ( 4.2) 0 1 (1.0)
UPPER RESPIRATORY TRACT INFECTION 4 ( 4.7)2 (2.3)0 2 ( 2.8) 1 ( 1.4)0 1 ( 1.0) 0 0
INFLUENZA 1 ( 1.2)0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
URINARY TRACT INFECTION 2 ( 2.3)0 0 1 ( 1.4) 0 0 0 0 0
CYSTITIS 1 ( 1.2)0 0 1 ( 1.4) 0 0 0 0 0
EAR INFECTION 2 ( 2.3)0 0 0 0 0 0 0 0
BRONCHITIS 0 1 (1.2)0 0 0 0 0 0 0
CELLULITIS 0 0 0 0 0 0 0 1 ( 1.0)0
CERVICITIS 1 ( 1.2)0 0 0 0 0 0 0 0
GASTROENTERITIS VIRAL 0 1 (1.2)0 0 0 0 0 0 0
HORDEOLUM 0 0 0 1 ( 1.4) 0 0 0 0 0
LOCALISED INFECTION 1 ( 1.2)0 0 0 0 0 0 0 0
LOWER RESPIRATORY TRACT INFECTION 0 0 0 0 1 ( 1.4)0 0 0 0
PNEUMONIA 0 0 0 0 0 0 0 1 ( 1.0)0
RHINITIS 0 0 0 1 ( 1.4) 0 0 0 0 0
VAGINAL MYCOSIS 1 ( 1.2)0 0 0 0 0 0 0 0
VIRAL INFECTION 0 0 0 0 0 0 1 ( 1.0) 0 0
PSYCHIATRIC DISORDERS 7 ( 8.1)2 (2.3)1 (1.2) 4 ( 5.6) 3 ( 4.2)0 4 ( 4.2) 7 ( 7.3)1 (1.0)
CONFUSIONAL STATE 1 ( 1.2)1 (1.2)0 1 ( 1.4) 0 0 0 3 ( 3.1)0
AGITATION 2 ( 2.3)0 0 0 0 0 0 2 ( 2.1)1 (1.0)
INSOMNIA 2 ( 2.3)0 0 2 ( 2.8) 0 0 0 0 0
ANXIETY 0 0 0 0 0 0 3 ( 3.1) 0 0
DELUSION 1 ( 1.2)0 0 0 1 ( 1.4)0 0 0 0
IRRITABILITY 0 1 (1.2)0 0 0 0 1 ( 1.0) 0 0
COMPLETED SUICIDE 0 0 1 (1.2) 0 0 0 0 0 0
DELIRIUM 0 0 0 0 1 ( 1.4)0 0 0 0
DEPRESSED MOOD 0 0 0 0 0 0 1 ( 1.0) 1 ( 1.0)0
DISORIENTATION 1 ( 1.2)0 0 0 0 0 0 0 0
HALLUCINATION 0 0 0 0 1 ( 1.4)0 0 0 0
HALLUCINATION, VISUAL 0 0 0 0 1 ( 1.4)0 0 0 0
LIBIDO DECREASED 0 0 0 1 ( 1.4) 0 0 0 0 0
LISTLESS 0 0 0 1 ( 1.4) 0 0 0 0 0
NIGHTMARE 0 0 0 1 ( 1.4) 0 0 0 0 0
RESTLESSNESS 0 0 0 0 0 0 0 1 ( 1.0)0
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS 7 ( 8.1)1 (1.2)0 8 (11.1) 2 ( 2.8)0 7 ( 7.3) 3 ( 3.1)0
COUGH 1 ( 1.2)0 0 3 ( 4.2) 2 ( 2.8)0 3 ( 3.1) 2 ( 2.1)0
NASAL CONGESTION 3 ( 3.5)0 0 3 ( 4.2) 0 0 1 ( 1.0) 0 0
DYSPNOEA 0 1 (1.2)0 1 ( 1.4) 0 0 0 1 ( 1.0)0
EPISTAXIS 0 0 0 2 ( 2.8) 0 0 1 ( 1.0) 0 0
PHARYNGOLARYNGEAL PAIN 0 0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
RHINORRHOEA 0 0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
ALLERGIC GRANULOMATOUS ANGIITIS 0 0 0 1 ( 1.4) 0 0 0 0 0
DYSPHONIA 0 0 0 0 0 0 1 ( 1.0) 0 0
EMPHYSEMA 1 ( 1.2)0 0 0 0 0 0 0 0
HAEMOPTYSIS 1 ( 1.2)0 0 0 0 0 0 0 0
PHARYNGEAL ERYTHEMA 0 0 0 1 ( 1.4) 0 0 0 0 0
POSTNASAL DRIP 1 ( 1.2)0 0 0 0 0 0 0 0
PRODUCTIVE COUGH 0 0 0 1 ( 1.4) 0 0 0 0 0
RALES 1 ( 1.2)0 0 0 0 0 0 0 0
RESPIRATORY TRACT CONGESTION 0 0 0 1 ( 1.4) 0 0 0 0 0
INVESTIGATIONS 8 ( 9.3)2 (2.3)0 4 ( 5.6) 1 ( 1.4)0 6 ( 6.2) 1 ( 1.0)0
ELECTROCARDIOGRAM ST SEGMENT DEPRESSION 4 ( 4.7)0 0 0 0 0 1 ( 1.0) 0 0
ELECTROCARDIOGRAM T WAVE INVERSION 2 ( 2.3)0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
BLOOD GLUCOSE INCREASED 0 0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
ELECTROCARDIOGRAM T WAVE AMPLITUDE DECREASED 1 ( 1.2)0 0 0 0 0 1 ( 1.0) 0 0
BIOPSY 0 0 0 1 ( 1.4) 0 0 0 0 0
BIOPSY PROSTATE 0 0 0 0 1 ( 1.4)0 0 0 0
BLOOD ALKALINE PHOSPHATASE INCREASED 0 1 (1.2)0 0 0 0 0 0 0
BLOOD CHOLESTEROL INCREASED 0 0 0 1 ( 1.4) 0 0 0 0 0
BLOOD CREATINE PHOSPHOKINASE INCREASED 0 1 (1.2)0 0 0 0 0 0 0
BLOOD URINE PRESENT 1 ( 1.2)0 0 0 0 0 0 0 0
BODY TEMPERATURE INCREASED 0 0 0 0 0 0 1 ( 1.0) 0 0
CYSTOSCOPY 1 ( 1.2)0 0 0 0 0 0 0 0
HEART RATE INCREASED 1 ( 1.2)0 0 0 0 0 0 0 0
HEART RATE IRREGULAR 1 ( 1.2)0 0 0 0 0 0 0 0
NASAL MUCOSA BIOPSY 0 0 0 0 0 0 1 ( 1.0) 0 0
WEIGHT DECREASED 0 0 0 0 0 0 0 1 ( 1.0)0
MUSCULOSKELETAL AND CONNECTIVE TISSUE DISORDERS 4 ( 4.7)1 (1.2)0 4 ( 5.6) 4 ( 5.6)0 3 ( 3.1) 4 ( 4.2)1 (1.0)
BACK PAIN 1 ( 1.2)0 0 2 ( 2.8) 1 ( 1.4)0 0 1 ( 1.0)0
ARTHRALGIA 1 ( 1.2)0 0 0 1 ( 1.4)0 1 ( 1.0) 2 ( 2.1)0
SHOULDER PAIN 1 ( 1.2)1 (1.2)0 0 0 0 2 ( 2.1) 0 0
MUSCLE SPASMS 0 0 0 1 ( 1.4) 0 0 0 0 1 (1.0)
ARTHRITIS 0 0 0 0 1 ( 1.4)0 0 0 0
FLANK PAIN 0 0 0 0 1 ( 1.4)0 0 0 0
MUSCULAR WEAKNESS 0 0 0 0 0 0 0 1 ( 1.0)0
MYALGIA 0 0 0 1 ( 1.4) 0 0 0 0 0
PAIN IN EXTREMITY 1 ( 1.2)0 0 0 0 0 0 0 0
INJURY, POISONING AND PROCEDURAL COMPLICATIONS 3 ( 3.5)0 1 (1.2) 2 ( 2.8) 3 ( 4.2)1 (1.4) 3 ( 3.1) 4 ( 4.2)0
CONTUSION 1 ( 1.2)0 0 2 ( 2.8) 0 0 1 ( 1.0) 1 ( 1.0)0
EXCORIATION 2 ( 2.3)0 0 0 1 ( 1.4)0 0 1 ( 1.0)0
FALL 1 ( 1.2)0 0 1 ( 1.4) 0 0 1 ( 1.0) 1 ( 1.0)0
HIP FRACTURE 0 0 1 (1.2) 0 1 ( 1.4)1 (1.4) 0 0 0
SKIN LACERATION 1 ( 1.2)0 0 0 0 0 1 ( 1.0) 1 ( 1.0)0
FACIAL BONES FRACTURE 0 0 0 0 1 ( 1.4)0 0 0 0
JOINT DISLOCATION 0 0 0 0 0 0 0 1 ( 1.0)0
WOUND 0 0 0 0 0 0 1 ( 1.0) 0 0
RENAL AND URINARY DISORDERS 3 ( 3.5)1 (1.2)0 1 ( 1.4) 2 ( 2.8)0 3 ( 3.1) 0 0
MICTURITION URGENCY 1 ( 1.2)0 0 1 ( 1.4) 0 0 1 ( 1.0) 0 0
DYSURIA 1 ( 1.2)0 0 0 0 0 1 ( 1.0) 0 0
NEPHROLITHIASIS 0 1 (1.2)0 0 1 ( 1.4)0 0 0 0
CALCULUS URETHRAL 0 0 0 0 1 ( 1.4)0 0 0 0
INCONTINENCE 0 0 0 0 0 0 1 ( 1.0) 0 0
POLLAKIURIA 1 ( 1.2)0 0 0 0 0 0 0 0
METABOLISM AND NUTRITION DISORDERS 5 ( 5.8)2 (2.3)0 1 ( 1.4) 1 ( 1.4)0 0 1 ( 1.0)0
DECREASED APPETITE 1 ( 1.2)1 (1.2)0 0 1 ( 1.4)0 0 0 0
FOOD CRAVING 1 ( 1.2)0 0 0 0 0 0 1 ( 1.0)0
INCREASED APPETITE 1 ( 1.2)0 0 1 ( 1.4) 0 0 0 0 0
DEHYDRATION 1 ( 1.2)0 0 0 0 0 0 0 0
DIABETES MELLITUS 1 ( 1.2)0 0 0 0 0 0 0 0
HYPONATRAEMIA 0 1 (1.2)0 0 0 0 0 0 0
VASCULAR DISORDERS 2 ( 2.3)2 (2.3)0 0 1 ( 1.4)0 3 ( 3.1) 0 0
HYPOTENSION 2 ( 2.3)1 (1.2)0 0 0 0 1 ( 1.0) 0 0
HYPERTENSION 0 1 (1.2)0 0 0 0 1 ( 1.0) 0 0
HOT FLUSH 0 0 0 0 0 0 1 ( 1.0) 0 0
ORTHOSTATIC HYPOTENSION 1 ( 1.2)0 0 0 0 0 0 0 0
WOUND HAEMORRHAGE 0 0 0 0 1 ( 1.4)0 0 0 0
EYE DISORDERS 1 ( 1.2)1 (1.2)0 0 1 ( 1.4)0 1 ( 1.0) 1 ( 1.0)0
VISION BLURRED 0 0 0 0 1 ( 1.4)0 1 ( 1.0) 0 0
CONJUNCTIVAL HAEMORRHAGE 0 0 0 0 0 0 0 1 ( 1.0)0
CONJUNCTIVITIS 0 1 (1.2)0 0 0 0 0 0 0
EYE ALLERGY 1 ( 1.2)0 0 0 0 0 0 0 0
EYE PRURITUS 1 ( 1.2)0 0 0 0 0 0 0 0
EYE SWELLING 1 ( 1.2)0 0 0 0 0 0 0 0
SURGICAL AND MEDICAL PROCEDURES 1 ( 1.2)1 (1.2)0 2 ( 2.8) 0 0 1 ( 1.0) 0 0
CATARACT OPERATION 0 1 (1.2)0 0 0 0 1 ( 1.0) 0 0
ACROCHORDON EXCISION 0 0 0 1 ( 1.4) 0 0 0 0 0
EYE LASER SURGERY 1 ( 1.2)0 0 0 0 0 0 0 0
SKIN LESION EXCISION 0 0 0 1 ( 1.4) 0 0 0 0 0
EAR AND LABYRINTH DISORDERS 1 ( 1.2)0 0 0 1 ( 1.4)0 1 ( 1.0) 1 ( 1.0)0
VERTIGO 0 0 0 0 1 ( 1.4)0 0 1 ( 1.0)0
CERUMEN IMPACTION 0 0 0 0 0 0 1 ( 1.0) 0 0
EAR PAIN 1 ( 1.2)0 0 0 0 0 0 0 0
CONGENITAL, FAMILIAL AND GENETIC DISORDERS 0 0 0 2 ( 2.8) 0 0 0 1 ( 1.0)0
VENTRICULAR SEPTAL DEFECT 0 0 0 2 ( 2.8) 0 0 0 1 ( 1.0)0
NEOPLASMS BENIGN, MALIGNANT AND UNSPECIFIED (INCL CYSTS AND POLYPS) 0 0 0 0 0 1 (1.4) 1 ( 1.0) 0 1 (1.0)
COLON CANCER 0 0 0 0 0 0 0 0 1 (1.0)
MALIGNANT FIBROUS HISTIOCYTOMA 0 0 0 0 0 0 1 ( 1.0) 0 0
PROSTATE CANCER 0 0 0 0 0 1 (1.4) 0 0 0
REPRODUCTIVE SYSTEM AND BREAST DISORDERS 2 ( 2.3)0 1 (1.2) 0 1 ( 1.4)0 0 0 0
BENIGN PROSTATIC HYPERPLASIA 1 ( 1.2)0 1 (1.2) 0 1 ( 1.4)0 0 0 0
PELVIC PAIN 1 ( 1.2)0 0 0 0 0 0 0 0
HEPATOBILIARY DISORDERS 0 1 (1.2)0 0 0 0 0 0 0
HYPERBILIRUBINAEMIA 0 1 (1.2)0 0 0 0 0 0 0
IMMUNE SYSTEM DISORDERS 0 0 0 0 0 0 1 ( 1.0) 0 0
HYPERSENSITIVITY 0 0 0 0 0 0 1 ( 1.0) 0 0
SOCIAL CIRCUMSTANCES 0 0 0 1 ( 1.4) 0 0 0 0 0
ALCOHOL USE 0 0 0 1 ( 1.4) 0 0 0 0 0
TEAE = Treatment-Emergent Adverse Event. Subjects counted once per SOC×grade and once per PT×grade.
Severity grade: MILD, MODERATE, SEVERE as recorded in AESEV.
Percentages based on N per treatment arm (Safety Population).
SOC rows sorted by descending subject frequency; PT rows sorted within SOC by descending frequency.
/opt/quarto/share/rmd/rmd.R 01APR2026 09:52:06
Source Code
---
title: "Adverse Events by Grade / Intensity"
subtitle: "Summary of Treatment-Emergent Adverse Events by SOC, PT, and Severity Grade"
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") |>
  mutate(AESEV = factor(AESEV, levels = c("MILD", "MODERATE", "SEVERE")))

arm_levels <- c("Placebo", "Xanomeline Low Dose", "Xanomeline High Dose")
sev_levels <- levels(adae_teae$AESEV)

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)
```


## Data Preparation

::: {.panel-tabset}

### dplyr

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

n_pct <- function(n, denom) sprintf("%d (%.1f)", n, n / denom * 100)

# ── Column names: Placebo_MILD, Placebo_MODERATE, ... ──
col_names <- unlist(lapply(arm_levels, function(a) {
  paste(gsub(" ", "_", a), sev_levels, sep = "_")
}))

# ── Helper: pivot arm×sev to wide, preserving any non-TRT01A/AESEV/value cols ──
pivot_arm_sev <- function(df, value_col = "value") {
  id_cols <- setdiff(names(df), c("TRT01A", "AESEV", value_col))
  df |>
    mutate(col = paste(gsub(" ", "_", TRT01A), AESEV, sep = "_")) |>
    select(all_of(id_cols), col, all_of(value_col)) |>
    pivot_wider(names_from = col, values_from = all_of(value_col))
}

# ── SOC × severity ──
soc_sev_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS, AESEV) |>
  count(TRT01A, AEBODSYS, AESEV, .drop = FALSE) |>
  filter(!is.na(AEBODSYS)) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, AESEV, value) |>
  pivot_arm_sev()

soc_wide <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "soc_n") |>
  left_join(soc_sev_arm, by = "AEBODSYS") |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEBODSYS,
    row_type = "soc",
    .before  = 1
  ) |>
  select(-AEBODSYS, -soc_n)

# ── PT × severity ──
pt_sev_arm <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, TRT01A, AEBODSYS, AEDECOD, AESEV) |>
  count(TRT01A, AEBODSYS, AEDECOD, AESEV, .drop = FALSE) |>
  filter(!is.na(AEBODSYS), !is.na(AEDECOD)) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, AEDECOD, AESEV, value) |>
  pivot_arm_sev()

pt_wide <- adae_teae |>
  filter(TRT01A %in% arm_levels) |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "pt_n") |>
  left_join(pt_sev_arm, by = c("AEBODSYS", "AEDECOD")) |>
  mutate(
    soc      = AEBODSYS,
    pt       = AEDECOD,
    row_type = "pt",
    .before  = 1
  ) |>
  select(-AEBODSYS, -AEDECOD, -pt_n)

# ── Sort order ──
soc_order <- adae_teae |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "n") |>
  arrange(desc(n)) |>
  pull(AEBODSYS)

pt_order <- adae_teae |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD, name = "n") |>
  arrange(match(AEBODSYS, soc_order), desc(n)) |>
  select(soc = AEBODSYS, pt = AEDECOD)

pt_wide <- pt_order |>
  left_join(pt_wide, by = c("soc", "pt"))

# ── Interleave SOC + PT rows ──
ae_grade_wide <- bind_rows(
  lapply(soc_order, function(s) {
    bind_rows(
      filter(soc_wide, soc == s),
      filter(pt_wide, soc == s)
    )
  })
) |>
  mutate(across(all_of(col_names), ~ replace_na(.x, "0 (0.0)")))

n_vec <- arm_n
```

### cards

```{r}
#| label: cards-code
ae_grade_ard <- ard_stack_hierarchical(
  data        = adae_teae |> filter(AESEV %in% sev_levels),
  variables   = c(AEBODSYS, AEDECOD),
  by          = c(TRT01A, AESEV),
  denominator = adsl_saf,
  id          = USUBJID,
  overall     = FALSE
) |>
  sort_ard_hierarchical(sort = "descending")

# Note: cards output has a different layout (AESEV as page_by)
# than the dplyr path (arm × grade column spans matching DPP shell)
ae_grade_cards <- fr_wide_ard(
  ae_grade_ard,
  statistic = "{n} ({p}%)",
  decimals  = c(p = 1),
  label     = c(
    AEBODSYS = "System Organ Class",
    AEDECOD  = "Preferred Term"
  )
)
```

:::


## arframe Pipeline

The rendered table below uses the **dplyr** data prep (`ae_grade_wide`, arm x severity columns with spans). The cards tab produces `ae_grade_cards` with a different layout — see the cards tab for details.

```{r}
#| label: pipeline
#| eval: false

# Build fr_col() list for arm × severity columns
sev_cols <- unlist(lapply(arm_levels, function(a) {
  setNames(
    lapply(sev_levels, function(s) {
      fr_col(tools::toTitleCase(tolower(s)), align = "decimal")
    }),
    paste(gsub(" ", "_", a), sev_levels, sep = "_")
  )
}), recursive = FALSE)

ae_grade_wide |>
  fr_table() |>
  fr_titles(
    "Table 14.3.4",
    "Summary of Treatment-Emergent Adverse Events by SOC, Preferred Term, and Severity Grade",
    "Safety Population"
  ) |>
  fr_cols(
    soc      = fr_col(visible = FALSE),
    pt       = fr_col("System Organ Class\n  Preferred Term", width = 3.0),
    row_type = fr_col(visible = FALSE),
    !!!sev_cols,
    .n = n_vec
  ) |>
  fr_spans(
    !!!setNames(
      lapply(arm_levels, function(a) {
        paste(gsub(" ", "_", a), sev_levels, sep = "_")
      }),
      arm_levels
    )
  ) |>
  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_footnotes(
    "TEAE = Treatment-Emergent Adverse Event. Subjects counted once per SOC×grade and once per PT×grade.",
    "Severity grade: MILD, MODERATE, SEVERE as recorded in AESEV.",
    "Percentages based on N per treatment arm (Safety Population).",
    "SOC rows sorted by descending subject frequency; PT rows sorted within SOC by descending frequency."
  )
```


## Rendered Table

```{r}
#| label: pre-render
#| include: false

# Note: The cards path produces a different layout (AESEV as page_by variable)
# rather than arm×grade columns with spans. The dplyr layout below matches
# the standard arm×severity column spans layout.
```

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

Open-source TFL reference collection

 

CDISC Pilot Study (CDISCPILOT01) • pharmaverseadam datasets