The gt package has inspired the creation of extension packages that build upon its foundation to solve specialized problems. These packages demonstrate the flexibility of gt’s architecture and provide ready-made solutions for common table-making tasks in specific domains. In this chapter, we’ll explore gtsummary, one of the most impactful extension packages, which provides a streamlined workflow for creating clinical and analytical summary tables.
The gtsummary package wraps gt’s functionality to provide sensible defaults for its target use cases while still allowing full access to gt’s customization capabilities. This means you can use the package to quickly generate professional tables and then further refine them using the gt functions you’ve already learned.
13.1gtsummary
The gtsummary package provides an elegant way to create publication-ready summary tables and regression model results. Originally developed for biomedical research, it has become an indispensable tool for anyone who needs to present descriptive statistics or model outputs in a professional format.
13.1.1 The problem gtsummary solves
Creating a proper “Table 1” for a research paper involves many tedious steps. You need to calculate summary statistics for continuous and categorical variables, handle missing data appropriately, compare groups using the right statistical tests, and format everything consistently. Before gtsummary, this process typically required hundreds of lines of code and careful attention to formatting details. The gtsummary package reduces this to just a few lines while producing tables that meet the exacting standards of medical journals.
The package automatically detects variable types and calculates appropriate descriptive statistics. Continuous variables get medians and interquartile ranges (or means and standard deviations), while categorical variables get counts and percentages. Missing values are tracked and reported. When comparing groups, the package selects appropriate statistical tests based on data characteristics.
13.1.2 Summarizing data with tbl_summary()
The tbl_summary() function is the workhorse of gtsummary. It takes a data frame and produces a formatted summary table with minimal code. The package includes a trial dataset for demonstrating its capabilities, which contains simulated data from 200 patients receiving chemotherapy treatments.
This simple call produces a table with properly formatted statistics, clear labels, and handling of missing values. The age variable is summarized with median and interquartile range because gtsummary detected it as continuous. The grade variable shows counts and percentages because it’s categorical. Missing values are reported as "Unknown" at the bottom of each variable’s section.
The real power of tbl_summary() emerges when comparing groups. By specifying a by variable, you can split your summary statistics across treatment arms or other groupings. Adding add_p() automatically selects and applies appropriate statistical tests for each variable.
2Wilcoxon rank sum test; Pearson’s Chi-squared test
This example demonstrates several of gtsummary’s customization options. The label argument provides custom variable names. The add_overall() function adds a column with statistics for all patients combined. The modify_header() and modify_spanning_header() functions adjust column labels. Finally, bold_labels() applies bold formatting to variable names.
13.1.3 Presenting regression results with tbl_regression()
Clinical research frequently involves regression modeling, and gtsummary provides tbl_regression() to present model results in publication-ready format. The function works with many model types including linear models, logistic regression, Cox proportional hazards models, and mixed effects models.
# Fit a logistic regression modelmodel<-glm(response~age+stage+grade, data =trial, family =binomial)# Create a formatted table of resultsmodel|>tbl_regression( exponentiate =TRUE, label =list(age~"Patient Age",stage~"T Stage",grade~"Tumor Grade"))|>bold_labels()
Characteristic
OR
95% CI
p-value
Patient Age
1.02
1.00, 1.04
0.092
T Stage
T1
—
—
T2
0.57
0.23, 1.34
0.2
T3
0.91
0.37, 2.22
0.8
T4
0.76
0.31, 1.85
0.6
Tumor Grade
I
—
—
II
0.84
0.38, 1.85
0.7
III
1.05
0.49, 2.25
>0.9
Abbreviations: CI = Confidence Interval, OR = Odds Ratio
The exponentiate = TRUE argument transforms coefficients to odds ratios, which is the standard presentation for logistic regression. Reference categories are automatically identified and marked. The package also provides functions like add_global_p() to add overall p-values for categorical variables with multiple levels, though these require additional dependencies.
13.1.4 Combining multiple tables
Research papers often present multiple models side by side or combine different analyses into a single display. The gtsummary package provides tbl_merge() and tbl_stack() for these situations.
# Create two regression tablesmodel1<-glm(response~age+grade, data =trial, family =binomial)model2<-glm(response~age+stage, data =trial, family =binomial)tbl1<-tbl_regression(model1, exponentiate =TRUE)tbl2<-tbl_regression(model2, exponentiate =TRUE)# Merge them side by sidetbl_merge( tbls =list(tbl1, tbl2), tab_spanner =c("**Model 1**", "**Model 2**"))
The number rows in the tables to be merged do not match, which may result in
rows appearing out of order.
ℹ See `tbl_merge()` (`?gtsummary::tbl_merge()`) help file for details. Use
`quiet=TRUE` to silence message.
Characteristic
Model 1
Model 2
OR
95% CI
p-value
OR
95% CI
p-value
Age
1.02
1.00, 1.04
0.10
1.02
1.00, 1.04
0.091
Grade
I
—
—
II
0.85
0.39, 1.85
0.7
III
1.01
0.47, 2.16
>0.9
T Stage
T1
—
—
T2
0.58
0.24, 1.37
0.2
T3
0.94
0.39, 2.28
0.9
T4
0.79
0.33, 1.90
0.6
Abbreviations: CI = Confidence Interval, OR = Odds Ratio
This approach is particularly useful for showing how results change as you add or remove covariates, or for presenting models with different outcomes.
13.1.5 Converting to gt for additional customization
Every gtsummary table can be converted to a gt object using as_gt(), which opens up all of gt’s formatting capabilities. This is useful when you need styling options beyond what gtsummary provides natively.
trial|>select(trt, age, marker)|>tbl_summary(by =trt)|>add_p()|>as_gt()|>tab_header( title =md("**Patient Characteristics by Treatment**"), subtitle ="Simulated Clinical Trial Data")|>tab_source_note("Data simulated for demonstration purposes")
Patient Characteristics by Treatment
Simulated Clinical Trial Data
Characteristic
Drug A
N = 981
Drug B
N = 1021
p-value2
Age
46 (37, 60)
48 (39, 56)
0.7
Unknown
7
4
Marker Level (ng/mL)
0.84 (0.23, 1.60)
0.52 (0.18, 1.21)
0.085
Unknown
6
4
1Median (Q1, Q3)
2Wilcoxon rank sum test
Data simulated for demonstration purposes
This workflow demonstrates how gtsummary and gt complement each other. You get the convenience of gtsummary’s automatic calculations and sensible defaults, then add gt’s rich formatting options for the final presentation.
As you develop your table-making skills, extension packages like gtsummary become valuable tools in your toolkit. They handle common tasks efficiently while remaining flexible enough for customization. In the next chapter, we’ll explore how you can create your own gt extensions to share solutions with the broader community.
13.2 Summary
This chapter has introduced gtsummary, a powerful extension package that builds upon gt’s foundation for creating statistical summary tables.
The key capabilities we’ve explored:
gtsummary transforms statistical analysis into publication-ready tables. tbl_summary() creates descriptive statistics tables with automatic variable detection and appropriate statistics. tbl_regression() formats model outputs with proper coefficient presentation. tbl_merge() and tbl_stack() combine multiple tables for comprehensive reporting.
integration with gt: gtsummary produces gt objects, meaning you can further customize its output using any gt function. Apply additional formatting, add footnotes, adjust styling (the full gt toolkit remains available).
Extension packages embody a powerful pattern: domain experts identifying common needs and encoding solutions in reusable code. The tables they produce meet professional standards while requiring minimal code from users.
The final chapter shows how you can create your own extensions, building functions and packages that address the specific table-making challenges in your domain.