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 = 3461 |
case N = 1641 |
Overall N = 5101 |
---|---|---|---|
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>
- 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.