rgtsummaryr-cards

Hierarchy summary table for Subject and Event counts together using GTSUMMARY


I am trying to create table shell below. First row is event level count, 2nd and onwards are subject level.

enter image description here

I have tried following code.

# Read in data
adsl <- cards::ADSL %>%
  mutate(TRTA = TRT01A)

adcm <- pharmaverseadam::adcm %>%
  filter(SAFFL == "Y" & ONTRTFL == 'Y') %>%
  select(c(USUBJID, TRTA, CMTRT, CMCLAS, CMDECOD, ONTRTFL))

# Event level counts
tbl1 <- adcm %>% tbl_hierarchical_count(
  by = TRTA,
  variables = c(CMTRT),
  overall_row = TRUE,
  label = list(..ard_hierarchical_overall.. = "TOTAL NUMBER OF CONCOMITANT MEDICATIONS")
  ) %>% add_overall(last = TRUE)

tbl1$table_body <- tbl1$table_body %>%
  filter(grepl("ard_hierarchical", variable))

# Subject level counts
tbl2 <- adcm %>% tbl_hierarchical(
  by = c(TRTA),
  variables = c(CMCLAS, CMDECOD),
  denominator = adsl,
  id = USUBJID,
  include = everything(),
  statistic = everything() ~ "{n} ({p}%)",
  overall_row = TRUE,
  label = list(
    ..ard_hierarchical_overall.. = "NUMBER OF PARTICIPANTS WITH ANY CONCOMITANT MEDICATION")
  ) %>%
  add_overall(last = TRUE)

# Stack the tables together
tbl.final <- tbl_stack(list(tbl1, tbl2),
                       quiet = TRUE) %>%
  # Modify the zero percent
  modify_table_body(
    ~ .x %>%
      dplyr::mutate(across(
        all_stat_cols(), ~ dplyr::case_when(. == "0.0 (0.00)" ~ "0", TRUE ~ .)
      ))) %>%
  # Update header
  modify_header(
    all_stat_cols() ~ "**{level}**  \n(N = {n}) <br>n(%)",
    label ~ "**ATC Level 4 <br> Preferred Term**") %>%
  # Remove default footnote
  remove_footnote_header(columns = all_stat_cols()) %>%
  # Create GT for print
  as_gt()

tbl.final$`_data` <- tbl.final$`_data` %>%
  mutate(tbl_id1 = if_else(!grepl("ard_hierarchical", variable),3,tbl_id1))

# Add blank rows for each tbl_id1
tbl.final <- tbl.final %>%
  gt::tab_row_group(
    label = md("<br>"),
    rows = tbl_id1 <= 1
  ) %>%
  tab_options(row_group.default_label = md("<br>"))

Facing couple of issues here.

  1. The tbl2 have header N counts; but after stacking tbl.final loses the information. (N = NA) in output.
  2. I am trying to insert blank lines using tab_row_group (yellow highlights below). I tried using the tbl_id information. However, it didn't work as expected. Final output I have is below. enter image description here

Can someone please help me figure this out? Thank you!!


Solution

  • I would create this table by first creating a table with the first row only using tbl_summary(). Then I would create the rest of the table with tbl_hierarchical(). Lastly, I would stack them with tbl_stack().

    In the example below, I used ADAE instead of con meds, but they idea is the same.

    library(gtsummary)
    packageVersion("gtsummary")
    #> [1] '2.1.0'
    
    tbl_row_one <-
      # merge in the number of AEs into ADSL
      cards::ADSL |> 
      dplyr::left_join(
        cards::ADAE |> 
          dplyr::summarise(.by = USUBJID,  AE_COUNT = length(USUBJID)),
        by = "USUBJID"
      ) |> 
      dplyr::rename(TRTA = ARM) |> 
      tbl_summary(
        by = TRTA,
        include = AE_COUNT,
        statistic = AE_COUNT ~ "{sum}",
        digits = AE_COUNT ~ 0,
        label = list(AE_COUNT = "TOTAL NUMBER OF AEs"),
        missing = "no"
      ) |> 
      add_overall(last = TRUE) |> 
      remove_footnote_header(columns = everything())
      
    
    tbl_ae <- 
      cards::ADAE |> 
      tbl_hierarchical(
        by = TRTA,
        variables = c(AESOC, AEDECOD),
        include = AEDECOD,
        id = USUBJID,
        denominator = cards::ADSL |> dplyr::rename(TRTA = ARM),
        overall_row = TRUE,
        label = list(..ard_hierarchical_overall.. = "NUMBER OF SUBJECTS WITH AT LEAST ONE AE")
      ) |> 
      add_overall(last = TRUE)
    
    # combine the tables
    tbl_final <-
      list(tbl_row_one, tbl_ae) |> 
      tbl_stack() |> 
      modify_header(label = "**Primary System Organ Class**  \n\U00A0\U00A0\U00A0\U00A0**Dictionary-Derived Term**") |> 
      # insert blank rows
      modify_table_body(
        ~ .x |> 
          dplyr::add_row(data.frame(label = NA), .after = 2L) |> 
          dplyr::add_row(data.frame(label = NA), .after = 1L)
      )
    #> Column headers among stacked tables differ. Headers from the first table are
    #> used.
    #> ℹ Check the header is correct and use `modify_header()` to update, or `quiet =
    #>   TRUE` to suppress this message.
    

    enter image description here

    Created on 2025-04-07 with reprex v2.1.1