arframe TFL Gallery
  1. Tables
  2. AEs Related to Study Drug
  • 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. AEs Related to Study Drug

AEs Related to Study Drug

Treatment-Emergent AEs Related to Study Drug by SOC and PT

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

# Related AEs: investigator-assessed relationship of POSSIBLE or PROBABLE
adae_rel <- pharmaverseadam::adae |>
  blank_to_na() |>
  filter(SAFFL == "Y", TRTEMFL == "Y", AEREL %in% c("POSSIBLE", "PROBABLE"))

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
n_pct <- function(n, denom) sprintf("%d (%.1f)", n, n / denom * 100)

# ── Overall row ──
any_rel_arm <- adae_rel |>
  distinct(USUBJID, TRT01A) |>
  count(TRT01A) |>
  filter(TRT01A %in% arm_levels) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

any_rel_total <- n_distinct(adae_rel$USUBJID)

any_rel_row <- bind_cols(
  tibble(soc = "TOTAL SUBJECTS WITH A RELATED TEAE",
         pt = "TOTAL SUBJECTS WITH A RELATED TEAE", row_type = "overall"),
  any_rel_arm,
  tibble(Total = n_pct(any_rel_total, N_total))
)

# ── SOC-level ──
soc_arm <- adae_rel |>
  distinct(USUBJID, TRT01A, AEBODSYS) |>
  count(TRT01A, AEBODSYS) |>
  filter(TRT01A %in% arm_levels) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

soc_total <- adae_rel |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS) |>
  mutate(Total = n_pct(n, N_total)) |>
  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 ──
pt_arm <- adae_rel |>
  distinct(USUBJID, TRT01A, AEBODSYS, AEDECOD) |>
  count(TRT01A, AEBODSYS, AEDECOD) |>
  filter(TRT01A %in% arm_levels) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, AEDECOD, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

pt_total <- adae_rel |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD) |>
  mutate(Total = n_pct(n, N_total)) |>
  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 and interleave ──
soc_order <- adae_rel |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "soc_n") |>
  arrange(desc(soc_n)) |> pull(AEBODSYS)

ae_rel_wide <- bind_rows(
  any_rel_row,
  bind_rows(lapply(soc_order, function(s) {
    bind_rows(
      filter(soc_wide, soc == s),
      filter(pt_wide, soc == s) |>
        left_join(
          adae_rel |> distinct(USUBJID, AEBODSYS, AEDECOD) |>
            count(AEBODSYS, AEDECOD, name = "pt_n"),
          by = c("soc" = "AEBODSYS", "pt" = "AEDECOD")
        ) |> arrange(desc(pt_n)) |> select(-pt_n)
    )
  }))
) |>
  mutate(across(where(is.character) & !c(soc, pt, row_type),
                ~ replace_na(.x, "0 (0.0)")))

for (a in arm_levels) {
  if (!a %in% names(ae_rel_wide)) ae_rel_wide[[a]] <- "0 (0.0)"
}
rel_ard <- ard_stack_hierarchical(
  data        = adae_rel,
  variables   = c(AEBODSYS, AEDECOD),
  by          = TRT01A,
  denominator = adsl_saf,
  id          = USUBJID,
  overall     = TRUE,
  over_variables = TRUE
) |>
  sort_ard_hierarchical(sort = "descending")

ae_rel_cards <- fr_wide_ard(
  rel_ard,
  statistic = "{n} ({p}%)",
  decimals  = c(p = 1),
  label     = c(
    "..ard_hierarchical_overall.." = "TOTAL SUBJECTS WITH A RELATED TEAE",
    AEBODSYS = "System Organ Class",
    AEDECOD  = "Preferred Term"
  )
)

arframe Pipeline

ae_rel_wide |>
  fr_table() |>
  fr_titles(
    "Table 14.3.1",
    "Treatment-Emergent Adverse Events Related to Study Drug",
    "by System Organ Class and Preferred Term",
    "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(
    "Related = Investigator-assessed relationship of Possible or Probable.",
    "Subjects counted once per SOC and once per PT.",
    "Percentages based on N per treatment arm (Safety Population).",
    "SOC sorted by descending frequency; PT sorted within SOC by descending frequency."
  )

Rendered Table

Table 14.3.1
Treatment-Emergent Adverse Events Related to Study Drug
by System Organ Class and Preferred Term
Safety Population
System Organ Class
Preferred Term
Placebo
(N=86)
Xanomeline High Dose
(N=72)
Xanomeline Low Dose
(N=96)
Total
(N=254)
TOTAL SUBJECTS WITH A RELATED TEAE43 (50.0)64 (88.9)77 (80.2)184 (72.4)
GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS18 (20.9)33 (45.8)45 (46.9) 96 (37.8)
APPLICATION SITE PRURITUS 6 ( 7.0)21 (29.2)23 (24.0) 50 (19.7)
APPLICATION SITE ERYTHEMA 3 ( 3.5)14 (19.4)13 (13.5) 30 (11.8)
APPLICATION SITE DERMATITIS 5 ( 5.8) 7 ( 9.7) 9 ( 9.4) 21 ( 8.3)
APPLICATION SITE IRRITATION 3 ( 3.5) 9 (12.5) 9 ( 9.4) 21 ( 8.3)
APPLICATION SITE VESICLES 1 ( 1.2) 5 ( 6.9) 5 ( 5.2) 11 ( 4.3)
FATIGUE 1 ( 1.2) 4 ( 5.6) 2 ( 2.1) 7 ( 2.8)
APPLICATION SITE SWELLING 0 2 ( 2.8) 1 ( 1.0) 3 ( 1.2)
APPLICATION SITE URTICARIA 0 1 ( 1.4) 2 ( 2.1) 3 ( 1.2)
APPLICATION SITE REACTION 1 ( 1.2) 1 ( 1.4) 0 2 ( 0.8)
CHILLS 1 ( 1.2) 0 1 ( 1.0) 2 ( 0.8)
APPLICATION SITE PAIN 0 2 ( 2.8) 0 2 ( 0.8)
APPLICATION SITE PERSPIRATION 0 2 ( 2.8) 0 2 ( 0.8)
MALAISE 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
PAIN 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
OEDEMA 0 0 2 ( 2.1) 2 ( 0.8)
APPLICATION SITE INDURATION 1 ( 1.2) 0 0 1 ( 0.4)
ASTHENIA 1 ( 1.2) 0 0 1 ( 0.4)
APPLICATION SITE DISCHARGE 0 1 ( 1.4) 0 1 ( 0.4)
FEELING ABNORMAL 0 1 ( 1.4) 0 1 ( 0.4)
OEDEMA PERIPHERAL 0 1 ( 1.4) 0 1 ( 0.4)
APPLICATION SITE BLEEDING 0 0 1 ( 1.0) 1 ( 0.4)
APPLICATION SITE DESQUAMATION 0 0 1 ( 1.0) 1 ( 0.4)
APPLICATION SITE DISCOLOURATION 0 0 1 ( 1.0) 1 ( 0.4)
APPLICATION SITE WARMTH 0 0 1 ( 1.0) 1 ( 0.4)
CHEST DISCOMFORT 0 0 1 ( 1.0) 1 ( 0.4)
SKIN AND SUBCUTANEOUS TISSUE DISORDERS16 (18.6)38 (52.8)37 (38.5) 91 (35.8)
PRURITUS 7 ( 8.1)25 (34.7)20 (20.8) 52 (20.5)
ERYTHEMA 8 ( 9.3)14 (19.4)13 (13.5) 35 (13.8)
RASH 3 ( 3.5) 6 ( 8.3)11 (11.5) 20 ( 7.9)
HYPERHIDROSIS 1 ( 1.2) 8 (11.1) 4 ( 4.2) 13 ( 5.1)
SKIN IRRITATION 2 ( 2.3) 5 ( 6.9) 6 ( 6.2) 13 ( 5.1)
BLISTER 0 1 ( 1.4) 5 ( 5.2) 6 ( 2.4)
RASH PRURITIC 0 2 ( 2.8) 1 ( 1.0) 3 ( 1.2)
PRURITUS GENERALISED 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
URTICARIA 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
COLD SWEAT 1 ( 1.2) 0 0 1 ( 0.4)
SKIN ULCER 1 ( 1.2) 0 0 1 ( 0.4)
RASH MACULO-PAPULAR 0 1 ( 1.4) 0 1 ( 0.4)
DERMATITIS CONTACT 0 0 1 ( 1.0) 1 ( 0.4)
RASH ERYTHEMATOUS 0 0 1 ( 1.0) 1 ( 0.4)
SKIN EXFOLIATION 0 0 1 ( 1.0) 1 ( 0.4)
NERVOUS SYSTEM DISORDERS 4 ( 4.7)13 (18.1)14 (14.6) 31 (12.2)
DIZZINESS 2 ( 2.3) 5 ( 6.9) 7 ( 7.3) 14 ( 5.5)
SYNCOPE 0 2 ( 2.8) 5 ( 5.2) 7 ( 2.8)
HEADACHE 1 ( 1.2) 1 ( 1.4) 1 ( 1.0) 3 ( 1.2)
BURNING SENSATION 0 2 ( 2.8) 0 2 ( 0.8)
LETHARGY 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
SOMNOLENCE 1 ( 1.2) 0 0 1 ( 0.4)
HYPERSOMNIA 0 1 ( 1.4) 0 1 ( 0.4)
PAROSMIA 0 1 ( 1.4) 0 1 ( 0.4)
SYNCOPE VASOVAGAL 0 1 ( 1.4) 0 1 ( 0.4)
BALANCE DISORDER 0 0 1 ( 1.0) 1 ( 0.4)
COMPLEX PARTIAL SEIZURES 0 0 1 ( 1.0) 1 ( 0.4)
COORDINATION ABNORMAL 0 0 1 ( 1.0) 1 ( 0.4)
PARAESTHESIA ORAL 0 0 1 ( 1.0) 1 ( 0.4)
STUPOR 0 0 1 ( 1.0) 1 ( 0.4)
TRANSIENT ISCHAEMIC ATTACK 0 0 1 ( 1.0) 1 ( 0.4)
GASTROINTESTINAL DISORDERS 4 ( 4.7) 9 (12.5) 8 ( 8.3) 21 ( 8.3)
DIARRHOEA 3 ( 3.5) 1 ( 1.4) 3 ( 3.1) 7 ( 2.8)
NAUSEA 0 3 ( 4.2) 3 ( 3.1) 6 ( 2.4)
VOMITING 0 2 ( 2.8) 3 ( 3.1) 5 ( 2.0)
SALIVARY HYPERSECRETION 0 3 ( 4.2) 0 3 ( 1.2)
DYSPEPSIA 1 ( 1.2) 0 1 ( 1.0) 2 ( 0.8)
ABDOMINAL PAIN 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
GASTROOESOPHAGEAL REFLUX DISEASE 1 ( 1.2) 0 0 1 ( 0.4)
STOMACH DISCOMFORT 0 1 ( 1.4) 0 1 ( 0.4)
CARDIAC DISORDERS 6 ( 7.0) 3 ( 4.2) 8 ( 8.3) 17 ( 6.7)
MYOCARDIAL INFARCTION 2 ( 2.3) 1 ( 1.4) 1 ( 1.0) 4 ( 1.6)
SINUS BRADYCARDIA 2 ( 2.3) 0 2 ( 2.1) 4 ( 1.6)
ATRIAL FIBRILLATION 1 ( 1.2) 1 ( 1.4) 1 ( 1.0) 3 ( 1.2)
SUPRAVENTRICULAR EXTRASYSTOLES 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
ATRIOVENTRICULAR BLOCK FIRST DEGREE 1 ( 1.2) 0 0 1 ( 0.4)
ATRIOVENTRICULAR BLOCK SECOND DEGREE 1 ( 1.2) 0 0 1 ( 0.4)
BRADYCARDIA 1 ( 1.2) 0 0 1 ( 0.4)
CARDIAC FAILURE CONGESTIVE 1 ( 1.2) 0 0 1 ( 0.4)
SINUS ARRHYTHMIA 1 ( 1.2) 0 0 1 ( 0.4)
ATRIAL FLUTTER 0 0 1 ( 1.0) 1 ( 0.4)
BUNDLE BRANCH BLOCK RIGHT 0 0 1 ( 1.0) 1 ( 0.4)
PALPITATIONS 0 0 1 ( 1.0) 1 ( 0.4)
VENTRICULAR EXTRASYSTOLES 0 0 1 ( 1.0) 1 ( 0.4)
WOLFF-PARKINSON-WHITE SYNDROME 0 0 1 ( 1.0) 1 ( 0.4)
PSYCHIATRIC DISORDERS 2 ( 2.3) 5 ( 6.9) 9 ( 9.4) 16 ( 6.3)
CONFUSIONAL STATE 1 ( 1.2) 0 2 ( 2.1) 3 ( 1.2)
ANXIETY 0 0 3 ( 3.1) 3 ( 1.2)
IRRITABILITY 1 ( 1.2) 0 1 ( 1.0) 2 ( 0.8)
INSOMNIA 0 2 ( 2.8) 0 2 ( 0.8)
AGITATION 0 0 2 ( 2.1) 2 ( 0.8)
DELIRIUM 0 1 ( 1.4) 0 1 ( 0.4)
HALLUCINATION, VISUAL 0 1 ( 1.4) 0 1 ( 0.4)
LIBIDO DECREASED 0 1 ( 1.4) 0 1 ( 0.4)
LISTLESS 0 1 ( 1.4) 0 1 ( 0.4)
DEPRESSED MOOD 0 0 1 ( 1.0) 1 ( 0.4)
RESTLESSNESS 0 0 1 ( 1.0) 1 ( 0.4)
INVESTIGATIONS 4 ( 4.7) 1 ( 1.4) 2 ( 2.1) 7 ( 2.8)
ELECTROCARDIOGRAM ST SEGMENT DEPRESSION 1 ( 1.2) 0 1 ( 1.0) 2 ( 0.8)
BLOOD CREATINE PHOSPHOKINASE INCREASED 1 ( 1.2) 0 0 1 ( 0.4)
HEART RATE INCREASED 1 ( 1.2) 0 0 1 ( 0.4)
HEART RATE IRREGULAR 1 ( 1.2) 0 0 1 ( 0.4)
ELECTROCARDIOGRAM T WAVE INVERSION 0 1 ( 1.4) 0 1 ( 0.4)
BODY TEMPERATURE INCREASED 0 0 1 ( 1.0) 1 ( 0.4)
METABOLISM AND NUTRITION DISORDERS 3 ( 3.5) 1 ( 1.4) 0 4 ( 1.6)
DECREASED APPETITE 1 ( 1.2) 1 ( 1.4) 0 2 ( 0.8)
FOOD CRAVING 1 ( 1.2) 0 0 1 ( 0.4)
INCREASED APPETITE 1 ( 1.2) 0 0 1 ( 0.4)
VASCULAR DISORDERS 1 ( 1.2) 1 ( 1.4) 2 ( 2.1) 4 ( 1.6)
HYPOTENSION 1 ( 1.2) 0 1 ( 1.0) 2 ( 0.8)
ORTHOSTATIC HYPOTENSION 1 ( 1.2) 0 0 1 ( 0.4)
WOUND HAEMORRHAGE 0 1 ( 1.4) 0 1 ( 0.4)
HYPERTENSION 0 0 1 ( 1.0) 1 ( 0.4)
INJURY, POISONING AND PROCEDURAL COMPLICATIONS 0 1 ( 1.4) 2 ( 2.1) 3 ( 1.2)
EXCORIATION 0 1 ( 1.4) 0 1 ( 0.4)
FALL 0 0 1 ( 1.0) 1 ( 0.4)
SKIN LACERATION 0 0 1 ( 1.0) 1 ( 0.4)
WOUND 0 0 1 ( 1.0) 1 ( 0.4)
EAR AND LABYRINTH DISORDERS 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
VERTIGO 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
EYE DISORDERS 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
VISION BLURRED 0 1 ( 1.4) 1 ( 1.0) 2 ( 0.8)
MUSCULOSKELETAL AND CONNECTIVE TISSUE DISORDERS 1 ( 1.2) 1 ( 1.4) 0 2 ( 0.8)
SHOULDER PAIN 1 ( 1.2) 0 0 1 ( 0.4)
MYALGIA 0 1 ( 1.4) 0 1 ( 0.4)
RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS 2 ( 2.3) 0 0 2 ( 0.8)
DYSPNOEA 1 ( 1.2) 0 0 1 ( 0.4)
EMPHYSEMA 1 ( 1.2) 0 0 1 ( 0.4)
CONGENITAL, FAMILIAL AND GENETIC DISORDERS 0 0 1 ( 1.0) 1 ( 0.4)
VENTRICULAR SEPTAL DEFECT 0 0 1 ( 1.0) 1 ( 0.4)
RENAL AND URINARY DISORDERS 0 1 ( 1.4) 0 1 ( 0.4)
MICTURITION URGENCY 0 1 ( 1.4) 0 1 ( 0.4)
REPRODUCTIVE SYSTEM AND BREAST DISORDERS 1 ( 1.2) 0 0 1 ( 0.4)
PELVIC PAIN 1 ( 1.2) 0 0 1 ( 0.4)
Related = Investigator-assessed relationship of Possible or Probable.
Subjects counted once per SOC and once per PT.
Percentages based on N per treatment arm (Safety Population).
SOC sorted by descending frequency; PT sorted within SOC by descending frequency.
/opt/quarto/share/rmd/rmd.R 01APR2026 09:52:16
Source Code
---
title: "AEs Related to Study Drug"
subtitle: "Treatment-Emergent AEs Related to Study Drug by SOC and PT"
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")

# Related AEs: investigator-assessed relationship of POSSIBLE or PROBABLE
adae_rel <- pharmaverseadam::adae |>
  blank_to_na() |>
  filter(SAFFL == "Y", TRTEMFL == "Y", AEREL %in% c("POSSIBLE", "PROBABLE"))

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

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

# ── Overall row ──
any_rel_arm <- adae_rel |>
  distinct(USUBJID, TRT01A) |>
  count(TRT01A) |>
  filter(TRT01A %in% arm_levels) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

any_rel_total <- n_distinct(adae_rel$USUBJID)

any_rel_row <- bind_cols(
  tibble(soc = "TOTAL SUBJECTS WITH A RELATED TEAE",
         pt = "TOTAL SUBJECTS WITH A RELATED TEAE", row_type = "overall"),
  any_rel_arm,
  tibble(Total = n_pct(any_rel_total, N_total))
)

# ── SOC-level ──
soc_arm <- adae_rel |>
  distinct(USUBJID, TRT01A, AEBODSYS) |>
  count(TRT01A, AEBODSYS) |>
  filter(TRT01A %in% arm_levels) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

soc_total <- adae_rel |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS) |>
  mutate(Total = n_pct(n, N_total)) |>
  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 ──
pt_arm <- adae_rel |>
  distinct(USUBJID, TRT01A, AEBODSYS, AEDECOD) |>
  count(TRT01A, AEBODSYS, AEDECOD) |>
  filter(TRT01A %in% arm_levels) |>
  mutate(value = mapply(n_pct, n, arm_n[TRT01A])) |>
  select(TRT01A, AEBODSYS, AEDECOD, value) |>
  pivot_wider(names_from = TRT01A, values_from = value)

pt_total <- adae_rel |>
  distinct(USUBJID, AEBODSYS, AEDECOD) |>
  count(AEBODSYS, AEDECOD) |>
  mutate(Total = n_pct(n, N_total)) |>
  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 and interleave ──
soc_order <- adae_rel |>
  distinct(USUBJID, AEBODSYS) |>
  count(AEBODSYS, name = "soc_n") |>
  arrange(desc(soc_n)) |> pull(AEBODSYS)

ae_rel_wide <- bind_rows(
  any_rel_row,
  bind_rows(lapply(soc_order, function(s) {
    bind_rows(
      filter(soc_wide, soc == s),
      filter(pt_wide, soc == s) |>
        left_join(
          adae_rel |> distinct(USUBJID, AEBODSYS, AEDECOD) |>
            count(AEBODSYS, AEDECOD, name = "pt_n"),
          by = c("soc" = "AEBODSYS", "pt" = "AEDECOD")
        ) |> arrange(desc(pt_n)) |> select(-pt_n)
    )
  }))
) |>
  mutate(across(where(is.character) & !c(soc, pt, row_type),
                ~ replace_na(.x, "0 (0.0)")))

for (a in arm_levels) {
  if (!a %in% names(ae_rel_wide)) ae_rel_wide[[a]] <- "0 (0.0)"
}
```

### cards

```{r}
#| label: cards-code
rel_ard <- ard_stack_hierarchical(
  data        = adae_rel,
  variables   = c(AEBODSYS, AEDECOD),
  by          = TRT01A,
  denominator = adsl_saf,
  id          = USUBJID,
  overall     = TRUE,
  over_variables = TRUE
) |>
  sort_ard_hierarchical(sort = "descending")

ae_rel_cards <- fr_wide_ard(
  rel_ard,
  statistic = "{n} ({p}%)",
  decimals  = c(p = 1),
  label     = c(
    "..ard_hierarchical_overall.." = "TOTAL SUBJECTS WITH A RELATED TEAE",
    AEBODSYS = "System Organ Class",
    AEDECOD  = "Preferred Term"
  )
)
```

:::


## arframe Pipeline

```{r}
#| label: pipeline
#| eval: false
ae_rel_wide |>
  fr_table() |>
  fr_titles(
    "Table 14.3.1",
    "Treatment-Emergent Adverse Events Related to Study Drug",
    "by System Organ Class and Preferred Term",
    "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(
    "Related = Investigator-assessed relationship of Possible or Probable.",
    "Subjects counted once per SOC and once per PT.",
    "Percentages based on N per treatment arm (Safety Population).",
    "SOC sorted by descending frequency; PT sorted within SOC by descending frequency."
  )
```


## Rendered Table

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

Open-source TFL reference collection

 

CDISC Pilot Study (CDISCPILOT01) • pharmaverseadam datasets