Search code examples
rgtsummary

gtsummary add units to variable labels in tbl_summary


I'm trying to customize the labels of a gtsummary::tbl_summary() and I'm having some trouble adding units to variables which do have this information.

Below the code I'm using:

set.seed(123)
library(tidyverse)
library(gtsummary)
d <- tidyr::tibble(
    id = c(1,2,3,4,5,6,7,8,9,10),
    inf_1 = structure(sample(rnorm(100, mean=42, sd=14), size = 10), label = "Age", units = "years"),
    inf_2 = structure(factor(sample(seq(0,1), size = 10, replace = TRUE), levels = c(0,1), labels = c("Unchecked", "Checked")), label = "BSI"),
)

d %>%
    gtsummary::tbl_summary(
        data = .,
        include = -id,
        label = ~ ifelse(
            "units" %in% names(attributes(.)),
            toString(attr(., "label"), attr(., "units")),
            toString(attr(., "label"))
        ),
        type = list(all_continuous() ~ "continuous2"),
        statistic = list(
            all_continuous() ~ c(
                "{median} ({p25}, {p75})",
                "{min}, {max}"
            ),
            all_categorical() ~ "{n} / {N} ({p}%)"
        )
    ) %>%
    gtsummary::as_gt()

And the output:

output_table

Created on 2024-12-25 with reprex v2.1.1

I believe this is because the "label" attribute is empty but this seems to be what the package uses by default according to documentation. Commenting out the label argument gives a standard output.

Any suggestions on how to do this?

Thank you.


Solution

  • this works:

    d %>%
      gtsummary::tbl_summary(
        data = .,
        include = -id,
        label = list(
          inf_1 ~ paste(attr(d$inf_1, "label"), paste0("(", attr(d$inf_1, "units"), ")")),
          inf_2 ~ attr(d$inf_2, "label")
        ),
        type = list(all_continuous() ~ "continuous2"),
        statistic = list(
          all_continuous() ~ c("{median} ({p25}, {p75})", "{min}, {max}"),
          all_categorical() ~ "{n} / {N} ({p}%)"
        )
      ) %>%
      gtsummary::as_gt()
    

    out


    Or to automatically use the label and units (if present) we can do:

    build_labels <- function(data) {
      lapply(data, function(x) {
        label <- attr(x, "label")
        units <- attr(x, "units")
        if (!is.null(units)) {
          paste(label, paste0("(", units, ")"))
        } else {
          label
        }
      })
    }
    
    e <- tidyr::tibble(
      id = c(1,2,3,4,5,6,7,8,9,10),
      inf_1 = structure(sample(rnorm(100, mean=42, sd=14), size = 10), label = "Age", units = "years"),
      inf_2 = structure(factor(sample(seq(0,1), size = 10, replace = TRUE), levels = c(0,1), labels = c("Unchecked", "Checked")), label = "BSI"),
      inf_3 = structure(sample(rnorm(50, mean=12, sd=3), size = 10), label = "Footsize", units = "cm"),
    )
    
    # Usage in tbl_summary
    e %>%
      gtsummary::tbl_summary(
        data = .,
        include = -id,
        label = build_labels(e),
        type = list(all_continuous() ~ "continuous2"),
        statistic = list(
          all_continuous() ~ c("{median} ({p25}, {p75})", "{min}, {max}"),
          all_categorical() ~ "{n} / {N} ({p}%)"
        )
      ) %>%
      gtsummary::as_gt()
    

    out2