Table One - gt

Last updated on 2025-09-02 | Edit this page

Overview

Questions

  • How do you make a Table One?
  • How do you make a Table One that is easy to configure?

Objectives

  • Explain what a Table One is
  • Know how to make a Tabel One and adjust key parameters

What is a “Table One”?


Primarily used in medical and epidemiological research, a Table One is typically the first table in any publication using data.

It presents the baseline characteristics of the participants in a study, and provides a concise overview of the relevant demographic and clinical variables.

It typically compares different groups (male~female, treatment~control), to highlight similarities and differences.

It can look like this:

control
(N=346)
case
(N=164)
Overall
(N=510)
Age (years)
Mean (SD) 61.0 (4.95) 60.9 (5.09) 61.0 (4.99)
Median [Min, Max] 62.0 [46.0, 69.0] 62.0 [45.0, 69.0] 62.0 [45.0, 69.0]
testost
Mean (SD) 24.9 (12.9) 27.7 (15.9) 25.8 (14.0)
Median [Min, Max] 22.0 [4.00, 111] 25.0 [6.00, 144] 23.0 [4.00, 144]
Missing 8 (2.3%) 4 (2.4%) 12 (2.4%)
prolactn
Mean (SD) 10.2 (6.77) 10.6 (6.32) 10.3 (6.63)
Median [Min, Max] 8.27 [1.96, 55.8] 9.18 [2.66, 59.9] 8.67 [1.96, 59.9]
Missing 14 (4.0%) 7 (4.3%) 21 (4.1%)

R

tbl_summary(blood, 
            by = case, 
              type = all_continuous() ~ "continuous2", # for at få multilinie summary stats
            include = c(ageblood, testost, curpmh),
                statistic = all_continuous() ~ c(
      "{mean} ({min}, {max})",
      "{median} ({p25}, {p75})"
    )
            ) |>
    add_overall(last = TRUE)
Characteristic control
N = 346
1
case
N = 164
1
Overall
N = 510
1
Age


    Mean (Min, Max) 61.0 (46.0, 69.0) 60.9 (45.0, 69.0) 61.0 (45.0, 69.0)
    Median (Q1, Q3) 62.0 (57.0, 65.0) 62.0 (57.0, 65.0) 62.0 (57.0, 65.0)
testost


    Mean (Min, Max) 25 (4, 111) 28 (6, 144) 26 (4, 144)
    Median (Q1, Q3) 22 (16, 31) 25 (19, 33) 23 (17, 31)
    Unknown 8 4 12
current_pmh 48 (14%) 29 (18%) 77 (15%)
1 n (%)

Og det gør vi så med gt i stedet. er der lettere måder? Ja, det er der. Link til lettere måde. Men! det her giver os ret omfattende muligheder for at tilpasse tabellen.

Herunder er vi ikke helt i mål endnu. Men vi er ret tæt.

R

library(dplyr)
library(gtsummary)
names(blood)

OUTPUT

[1] "ID"       "matchid"  "case"     "curpmh"   "ageblood" "estradol" "testost"
[8] "prolactn"

R

# grunddata
base <- blood |>
  select(ageblood, grade, stage, trt) |>
  mutate(grade = paste("Grade", grade))

ERROR

Error in `select()` at dplyr/R/mutate.R:146:3:
! Can't select columns that don't exist.
✖ Column `grade` doesn't exist.

R

# rækkefølge på paneler: Overall først, derefter Grade I/II/III
lvl <- c("Overall", paste("Grade", levels(trial$grade)))

# lav et samlet datasæt med et ekstra "Overall"-panel
df <- bind_rows(
  base |> mutate(.panel = "Overall"),
  base |> mutate(.panel = grade)
) |>
  mutate(.panel = factor(.panel, levels = lvl))

ERROR

Error: object 'base' not found

R

# tabel: tre strata + et overall-stratum
tbl <- df |>
  tbl_strata(
    strata = .panel,
    .tbl_fun = ~ .x |>
      select(-grade) |> 
      tbl_summary(by = trt, missing = "no") |>
      add_n(),
    .header = "**{strata}**, N = {n}"
  )

ERROR

Error in `tbl_strata()`:
! The `data` argument must be class <data.frame/survey.design>, not a
  function.

R

tbl

OUTPUT

function(src, ...) {
  UseMethod("tbl")
}
<bytecode: 0x556b3874c188>
<environment: namespace:dplyr>
Key Points
  • A Table One provides a compact describtion of the data we are working with
  • With a little bit of work we can control the content of the table.