Search code examples
rgtsummary

2 Levels of spanning headers using tbl_strata() and tbl_summary()


I am currently dealing with the following issue:
My data was collected over two timeopints and between two different groups.
I'm trying to get a summary table with a t-test using gtsummary::tbl_summary() and tbl_strata().
Unfortunately I am not able to figure out how to get a spanning header over the two timepoints each (first & second), while keeping the structure of the table the same (mainly the order of the columns).
Below is a reproducible example. Thanks so much in advance for any help!

#Create df
df <- data.frame(
  id = rep(c(1, 2, 3), each = 4, time = 1),
  var_01 = sample(1:5, 12, replace = TRUE),
  var_02 = sample(1:5, 12, replace = TRUE),
  group = rep(c("A", "B"), each = 2, times = 3),
  time = rep(c("first", "second"), each = 1, times = 6)
)

#Current best attempt at the summary table
df |> 
  tbl_strata(
    strata = group,
    .tbl_fun = 
      ~ .x |> 
        tbl_summary(
          include = -id,
          by = time,
          type = contains("var") ~ "continuous",
          statistic = list(
            contains("var") ~ "{mean} ({sd})"
          ),
          missing = "no"
        ) |> 
      add_difference(
        test = everything() ~ "paired.t.test",
        group = id,
      ),
    .header = "**Group {strata}**"
  )

Edit: Two show it visually (examples have a different design cause the first one is taken from R and the second one was edited in word):
My current table:
enter image description here

The goal for what I would love the table to look like: enter image description here


Solution

  • For now (and this is something we're looking to change pretty soon), gtsummary only supports one spanning header row. To get your second row, you'll need to convert your object to a {gt} table, then use gt::tab_spanner(level = 2) to add a second spanning header level. Example Below!

    library(gtsummary)
    packageVersion("gtsummary")
    #> [1] '2.0.1.9002'
    
    #Create df
    df <- data.frame(
      id = rep(c(1, 2, 3), each = 4, time = 1),
      var_01 = sample(1:5, 12, replace = TRUE),
      var_02 = sample(1:5, 12, replace = TRUE),
      group = rep(c("A", "B"), each = 2, times = 3),
      time = rep(c("first", "second"), each = 1, times = 6)
    )
    
    #Current best attempt at the summary table
    tbl <- df |> 
      tbl_strata(
        strata = group,
        .tbl_fun = 
          ~ .x |> 
          tbl_summary(
            include = -id,
            by = time,
            type = contains("var") ~ "continuous",
            statistic = list(
              contains("var") ~ "{mean} ({sd})"
            ),
            missing = "no"
          ) |> 
          add_difference(
            test = everything() ~ "paired.t.test",
            group = id,
          )
      ) |> 
      modify_spanning_header(everything() ~ NA) |> # reset default header
      modify_spanning_header(all_stat_cols() ~ "**Timepoint**") |> 
      as_gt() |> 
      gt::tab_spanner(
        label = gt::md("**Group A**"),
        columns = ends_with("_1"),
        level = 2L
      ) |> 
      gt::tab_spanner(
        label = gt::md("**Group B**"),
        columns = ends_with("_2"),
        level = 2L
      )
    

    enter image description here Created on 2024-08-29 with reprex v2.1.1