With gtsummary, is it possible to have N on a separate row to the column name?

3.7k views Asked by At

gtsummary by default puts the number of observations in a by group beside the label for that group. This increases the width of the table... with many groups or large N, the table would quickly become very wide.

enter image description here

Is it possible to get gtsummary to report N on a separate row beneath the label? E.g.

> data(mtcars)
> mtcars %>%
+         select(mpg, cyl, vs, am) %>%
+         tbl_summary(by = am) %>%
+         as_tibble()
# A tibble: 6 x 3
  `**Characteristic**` `**0**, N = 19`   `**1**, N = 13`  
  <chr>                <chr>             <chr>            
1 mpg                  17.3 (14.9, 19.2) 22.8 (21.0, 30.4)
2 cyl                  NA                NA               
3 4                    3 (16%)           8 (62%)          
4 6                    4 (21%)           3 (23%)          
5 8                    12 (63%)          2 (15%)          
6 vs                   7 (37%)           7 (54%)          

would become

# A tibble: 6 x 3
  `**Characteristic**` `**0**`           `**1**`  
  <chr>                <chr>             <chr>            
1                      N = 19            N = 13
2 mpg                  17.3 (14.9, 19.2) 22.8 (21.0, 30.4)
3 cyl                  NA                NA               
4 4                    3 (16%)           8 (62%)          
5 6                    4 (21%)           3 (23%)          
6 8                    12 (63%)          2 (15%)          
7 vs                   7 (37%)           7 (54%)    

(I only used as_tibble so that it was easy to show what I mean by editing it manually...)

Any idea?

Thanks!

2

There are 2 answers

3
kittykatstat On BEST ANSWER

Here is one way you could do this:

library(tidyverse)
library(gtsummary)

mtcars %>%
  select(mpg, cyl, vs, am) %>%
# create a new variable to display N in table
  mutate(total = 1) %>%
# this is just to reorder variables for table 
  select(total, everything()) %>%
  tbl_summary(
    by = am,
# this is to specify you only want N (and no percentage) for new total variable
    statistic = total ~ "N = {N}") %>%
# this is a gtsummary function that allows you to edit the header
  modify_header(all_stat_cols() ~ "**{level}**")
  • First, I am making a new variable that is just total observations (called total)
  • Then, I am customizing the way I want that variable statistic to be displayed
  • Then I am using gtsummary::modify_header() to remove N from the header

Additionally, if you use the flextable print engine, you can add a line break in the header itself:

mtcars %>%
  select(mpg, cyl, vs, am) %>%
# create a new variable to display N in table
  tbl_summary(
    by = am
# this is to specify you only want N (and no percentage) for new total variable
    ) %>%
# this is a gtsummary function that allows you to edit the header
  modify_header(all_stat_cols() ~ "**{level}**\nN = {n}") %>%
  as_flex_table()

Good luck!

2
Daniel D. Sjoberg On

@kittykatstat already posted two fantastic solutions! I'll just add a slight variation :)

If you want to use the {gt} package to print the table and you're outputting to HTML, you can use the HTML tag <br> to add a line break in the header row (very similar to the \n solution already posted).

library(gtsummary)

mtcars %>%
  select(mpg, cyl, vs, am) %>%
  dplyr::mutate(am = factor(am, labels = c("Manual", "Automatic"))) %>%
  # create a new variable to display N in table
  tbl_summary(by = am) %>%
  # this is a gtsummary function that allows you to edit the header
  modify_header(stat_by =  "**{level}**<br>N = {N}")

enter image description here