install.packages("gtsummary")
install.packages("flextable") # For Word exportCreating Publication-Ready Tables with gtsummary
advanced
tables
statistics
Learn how to create professional statistical tables for manuscripts and reports
Introduction
One of the most time-consuming tasks in research is creating well-formatted statistical tables. The gtsummary package makes this incredibly easy while producing publication-ready output.
Why gtsummary?
- Creates APA-style tables automatically
- Supports complex statistical models
- Exports to Word, HTML, PDF, and LaTeX
- Minimal code required
- Perfect for epidemiological studies
Installation
Basic Summary Tables
Descriptive Statistics
library(gtsummary)
library(tidyverse)
# Create a summary table stratified by exposure status
outbreak_data %>%
select(age, sex, symptoms, exposed) %>%
tbl_summary(
by = exposed,
statistic = list(
all_continuous() ~ "{mean} ({sd})",
all_categorical() ~ "{n} ({p}%)"
),
label = list(
age ~ "Age (years)",
sex ~ "Sex",
symptoms ~ "Symptoms Present"
)
) %>%
add_p() %>% # Add p-values
add_overall() %>% # Add overall column
bold_labels()Regression Tables
Logistic Regression for Outbreak Investigation
# Fit logistic regression model
model <- glm(
case_status ~ age + sex + water_source + food_type,
data = outbreak_data,
family = binomial
)
# Create publication-ready table
tbl_regression(
model,
exponentiate = TRUE, # Show odds ratios
label = list(
age ~ "Age (years)",
sex ~ "Sex",
water_source ~ "Water Source",
food_type ~ "Food Type"
)
) %>%
add_global_p() %>% # Add overall p-values
bold_p(t = 0.05) %>% # Bold significant p-values
bold_labels()Exporting Tables
To Microsoft Word
my_table %>%
as_flex_table() %>%
flextable::save_as_docx(path = "table1.docx")To HTML
my_table %>%
as_gt() %>%
gt::gtsave("table1.html")Advanced Tips
Compare Multiple Models
# Compare unadjusted vs adjusted models
tbl_merge(
list(
tbl_regression(unadjusted_model, exponentiate = TRUE),
tbl_regression(adjusted_model, exponentiate = TRUE)
),
tab_spanner = c("**Unadjusted**", "**Adjusted**")
)Customize Themes
# Set a journal-specific theme
theme_gtsummary_journal("jama")
# Or create custom theme
theme_gtsummary_compact()Practical Example: Diphtheria Outbreak
Here’s a complete example analyzing outbreak data:
# Load outbreak data
diphtheria_data <- read_csv("diphtheria_outbreak.csv")
# Create comprehensive table
diphtheria_data %>%
select(age_group, sex, vaccination_status, outcome, district) %>%
tbl_summary(
by = outcome,
statistic = list(
all_categorical() ~ "{n} ({p}%)"
),
label = list(
age_group ~ "Age Group",
sex ~ "Sex",
vaccination_status ~ "Vaccination Status",
district ~ "District"
)
) %>%
add_p(test = all_categorical() ~ "fisher.test") %>%
add_overall() %>%
modify_header(label = "**Characteristic**") %>%
bold_labels() %>%
bold_p(t = 0.05)Resources
Join our next session to learn more advanced table techniques! RSVP on Meetup