The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
library(sumExtras)
library(gtsummary)
library(dplyr)
library(gt)
# Apply the recommended JAMA theme
use_jama_theme()While extras() handles basic table formatting, sumExtras
provides additional tools for creating visually polished,
publication-ready tables. This vignette covers advanced styling
techniques that go beyond the basics.
You’ll learn how to:
For basic table creation and labeling, see:
vignette("sumExtras-intro") - Getting started with
sumExtrasvignette("labeling") - Automatic variable labeling
workflowsWhen tables contain many variables, organizing them into logical
sections improves readability. The
add_variable_group_header() function from gtsummary creates
section headers, and sumExtras provides tools to style them
effectively.
trial |>
select(age, marker, grade, stage, response, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Demographics",
variables = age
) |>
add_variable_group_header(
header = "Clinical Measures",
variables = marker:response
)| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Demographics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Clinical Measures | ||||
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Unknown | 7 | 3 | 4 | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
This creates section headers but they don’t stand out much from regular variables. Let’s fix that.
add_group_styling()The add_group_styling() function adds visual emphasis to
group headers, making section breaks clear and improving table
readability.
By default, add_group_styling() applies both bold and
italic formatting:
| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Demographics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Clinical Measures | ||||
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Unknown | 7 | 3 | 4 | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Demographics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Clinical Measures | ||||
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Unknown | 7 | 3 | 4 | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
Notice how the group headers now stand out with bold italic text, creating clear visual breaks between table sections.
You can control the text formatting using the format
argument:
trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Patient Characteristics",
variables = age:stage
) |>
add_group_styling(format = "bold")| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Patient Characteristics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Patient Characteristics",
variables = age:stage
) |>
add_group_styling(format = "italic")| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Patient Characteristics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Patient Characteristics",
variables = age:stage
) |>
add_group_styling(format = c("bold", "italic"))| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Patient Characteristics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
Using add_group_styling() also restores the original
left-justified variable label indentation. The default behavior of
add_variable_group_header() aligns variable labels with
categorical levels or “Unknown” display, which can look unbalanced.
add_group_styling() fixes this automatically.
Compare these two approaches:
Indentation may look off
| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Patient Variables | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Patient Variables | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
For additional visual emphasis, you can add background colors to
group headers using the add_group_colors() convenience
function.
trial |>
select(age, marker, grade, stage, response, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Demographics",
variables = age
) |>
add_variable_group_header(
header = "Clinical Measures",
variables = marker:response
) |>
add_group_styling() |>
add_group_colors() # Default light gray background| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Demographics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Clinical Measures | ||||
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Unknown | 7 | 3 | 4 | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
This applies text formatting (bold/italic) with a light gray background (#E8E8E8) to create clear visual separation between table sections.
get_group_rows()The get_group_rows() function identifies which rows in
your gtsummary table contain group headers:
# Create a table with groups
grouped_table <- trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Demographics",
variables = age
) |>
add_variable_group_header(
header = "Disease Measures",
variables = marker:stage
)
# Get row numbers
group_rows <- get_group_rows(grouped_table)
group_rows
#> [1] 1 4These row numbers correspond to the body rows in the resulting gt
table, which you can then target with gt::tab_style().
You can specify any color with the color argument:
trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Baseline Characteristics",
variables = age:stage
) |>
add_group_styling() |>
add_group_colors(color = "#E3F2FD") # Light blue| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Baseline Characteristics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
For most use cases, add_group_colors() provides the
simplest approach. However, understanding the manual pattern helps when
you need complex gt styling beyond simple background colors.
my_table <- trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Baseline Characteristics",
variables = age:stage
) |>
add_group_styling()
group_rows <- get_group_rows(my_table)
my_table |>
as_gt() |>
gt::tab_style(
style = gt::cell_fill(color = "#E3F2FD"),
locations = gt::cells_body(rows = group_rows)
)| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Baseline Characteristics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Baseline Characteristics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
Both approaches produce identical results, but
add_group_colors() is significantly cleaner—no intermediate
objects, no manual get_group_rows() call, fully
pipeable.
Use add_group_colors() when:
Use the manual pattern when:
gt::tab_style()
operationsThe most effective tables often combine multiple styling approaches. Here are some common patterns.
For tables in manuscripts where minimalist design is preferred:
trial |>
select(age, marker, grade, stage, response, trt) |>
tbl_summary(by = trt, missing = "no") |>
extras() |>
add_variable_group_header(
header = "Demographics",
variables = age:marker
) |>
add_variable_group_header(
header = "Tumor Characteristics",
variables = grade:response
) |>
add_group_styling(format = "bold") # Bold only, no italic| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Demographics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Tumor Characteristics | ||||
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
For presentations or reports where visual clarity is paramount:
my_table <- trial |>
select(age, marker, grade, stage, response, trt) |>
tbl_summary(by = trt, missing = "no") |>
extras() |>
add_variable_group_header(
header = "DEMOGRAPHICS",
variables = age:marker
) |>
add_variable_group_header(
header = "TUMOR CHARACTERISTICS",
variables = grade:response
) |>
add_group_styling() # Bold + italic
group_rows <- get_group_rows(my_table)
my_table |>
as_gt() |>
gt::tab_style(
style = list(
gt::cell_fill(color = "#E8E8E8"),
gt::cell_text(weight = "bold")
),
locations = gt::cells_body(rows = group_rows)
)| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| DEMOGRAPHICS | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| TUMOR CHARACTERISTICS | ||||
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
For complex tables with many grouped sections:
# Create a more complex grouping
my_table <- trial |>
select(trt, age, marker, grade, stage, response, death) |>
tbl_summary(by = trt, missing = "no") |>
extras() |>
add_variable_group_header(
header = "Baseline Demographics",
variables = age
) |>
add_variable_group_header(
header = "Biomarkers",
variables = marker
) |>
add_variable_group_header(
header = "Disease Characteristics",
variables = grade:stage
) |>
add_variable_group_header(
header = "Outcomes",
variables = response:death
) |>
add_group_styling()
group_rows <- get_group_rows(my_table)
my_table |>
as_gt() |>
gt::tab_style(
style = gt::cell_fill(color = "#F5F5F5"),
locations = gt::cells_body(rows = group_rows)
)| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Baseline Demographics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Biomarkers | ||||
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Disease Characteristics | ||||
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Outcomes | ||||
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Patient Died | 112 (56%) | 52 (53%) | 60 (59%) | 0.412 |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
Consistent styling across tables in a document or project requires thoughtful theme management. sumExtras provides tools for both gtsummary and gt tables.
use_jama_theme()The use_jama_theme() function applies the JAMA compact
theme to all gtsummary tables in your session:
# Apply JAMA compact theme (typically done once at the beginning)
use_jama_theme()
#> Setting theme "Compact"
#> Applied JAMA compact theme to {gtsummary}
# Now all gtsummary tables use this theme
trial |>
tbl_summary(by = trt) |>
extras()| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Unknown | 7 | 3 | 4 | |
| Patient Died | 112 (56%) | 52 (53%) | 60 (59%) | 0.412 |
| Months to Death/Censor | 22.4 (15.9, 24.0) | 23.5 (17.4, 24.0) | 21.2 (14.5, 24.0) | 0.145 |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
This is equivalent to:
But use_jama_theme() is more concise and memorable.
The JAMA compact theme provides:
theme_gt_compact()When mixing gtsummary tables with regular gt tables in the same
document, visual consistency matters. The
theme_gt_compact() function applies JAMA-style compact
formatting to gt tables, matching the appearance of the JAMA compact
theme used by gtsummary.
| Chemotherapy Treatment | Age | Grade |
|---|---|---|
| Drug A | 23 | II |
| Drug B | 9 | I |
| Drug A | 31 | II |
| Drug A | NA | III |
| Drug A | 51 | III |
| Drug B | 39 | I |
| Drug A | 37 | II |
| Drug A | 32 | I |
| Drug A | 31 | II |
| Drug B | 34 | I |
| Chemotherapy Treatment | Age | Grade |
|---|---|---|
| Drug A | 23 | II |
| Drug B | 9 | I |
| Drug A | 31 | II |
| Drug A | NA | III |
| Drug A | 51 | III |
| Drug B | 39 | I |
| Drug A | 37 | II |
| Drug A | 32 | I |
| Drug A | 31 | II |
| Drug B | 34 | I |
The compact theme creates visual consistency with gtsummary tables, resulting in a more professional, cohesive document.
theme_gt_compact() provides a solid foundation, but you
can customize further:
trial |>
select(trt, age, grade, marker) |>
head(8) |>
gt::gt() |>
theme_gt_compact() |>
gt::tab_header(
title = "Trial Patient Sample",
subtitle = "First 8 patients"
) |>
gt::tab_style(
style = gt::cell_fill(color = "#F0F0F0"),
locations = gt::cells_body(rows = seq(2, 8, 2)) # Zebra striping
)| Trial Patient Sample | |||
| First 8 patients | |||
| Chemotherapy Treatment | Age | Grade | Marker Level (ng/mL) |
|---|---|---|---|
| Drug A | 23 | II | 0.160 |
| Drug B | 9 | I | 1.107 |
| Drug A | 31 | II | 0.277 |
| Drug A | NA | III | 2.067 |
| Drug A | 51 | III | 2.767 |
| Drug B | 39 | I | 0.613 |
| Drug A | 37 | II | 0.354 |
| Drug A | 32 | I | 1.739 |
Combine group headers with zebra striping for maximum readability:
my_table <- trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Demographics",
variables = age:marker
) |>
add_variable_group_header(
header = "Disease",
variables = grade:stage
) |>
add_group_styling()
group_rows <- get_group_rows(my_table)
# Convert to gt and get the actual number of body rows
gt_table <- my_table |> as_gt()
n_body_rows <- nrow(gt_table$`_data`)
gt_table |>
gt::tab_style(
style = gt::cell_fill(color = "#E8E8E8"),
locations = gt::cells_body(rows = group_rows)
) |>
gt::tab_style(
style = gt::cell_fill(color = "#F9F9F9"),
locations = gt::cells_body(rows = !seq_len(n_body_rows) %in% group_rows)
)| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Demographics | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Disease | ||||
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
You can combine group styling with highlighting of specific variables of interest:
my_table <- trial |>
select(age, marker, grade, stage, response, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Baseline",
variables = age:marker
) |>
add_variable_group_header(
header = "Disease & Outcome",
variables = grade:response
) |>
add_group_styling()
group_rows <- get_group_rows(my_table)
my_table |>
as_gt() |>
gt::tab_style(
style = gt::cell_fill(color = "#E8E8E8"),
locations = gt::cells_body(rows = group_rows)
) |>
gt::tab_style(
style = list(
gt::cell_fill(color = "#FFF9E6"),
gt::cell_text(weight = "bold")
),
locations = gt::cells_body(
columns = label,
rows = label == "Tumor Response" # Highlight primary outcome
)
)| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Baseline | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Disease & Outcome | ||||
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Unknown | 7 | 3 | 4 | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
Add subtle borders between groups for additional visual separation:
my_table <- trial |>
select(age, marker, grade, stage, trt) |>
tbl_summary(by = trt) |>
extras() |>
add_variable_group_header(
header = "Patient Factors",
variables = age:marker
) |>
add_variable_group_header(
header = "Tumor Factors",
variables = grade:stage
) |>
add_group_styling()
group_rows <- get_group_rows(my_table)
my_table |>
as_gt() |>
gt::tab_style(
style = gt::cell_fill(color = "#F5F5F5"),
locations = gt::cells_body(rows = group_rows)
) |>
gt::tab_style(
style = gt::cell_borders(
sides = "bottom",
color = "#CCCCCC",
weight = gt::px(2)
),
locations = gt::cells_body(rows = max(group_rows))
)| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| Patient Factors | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Unknown | 11 | 7 | 4 | |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| Unknown | 10 | 6 | 4 | |
| Tumor Factors | ||||
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
Here’s a comprehensive example combining all the styling techniques:
# Create dictionary for labeling (see vignette("labeling") for details)
dictionary <- tibble::tribble(
~Variable, ~Description,
"trt", "Treatment Assignment",
"age", "Age at Baseline (years)",
"marker", "Biomarker Level (ng/mL)",
"stage", "Clinical Stage",
"grade", "Tumor Grade",
"response", "Treatment Response",
"death", "Patient Died"
)
# Build the styled table
trial |>
select(trt, age, marker, grade, stage, response, death) |>
tbl_summary(by = trt, missing = "no") |>
add_auto_labels(dictionary = dictionary) |>
extras() |>
add_variable_group_header(
header = "BASELINE CHARACTERISTICS",
variables = age:marker
) |>
add_variable_group_header(
header = "DISEASE CHARACTERISTICS",
variables = grade:stage
) |>
add_variable_group_header(
header = "OUTCOMES",
variables = response:death
) |>
add_group_styling() |>
add_group_colors(color = "#E8E8E8") |>
gt::tab_header(
title = "Patient Characteristics and Outcomes by Treatment",
subtitle = "Clinical Trial Dataset"
) |>
gt::tab_source_note(
source_note = "Data from gtsummary package trial dataset"
)| Patient Characteristics and Outcomes by Treatment | ||||
| Clinical Trial Dataset | ||||
| Overall N = 2001 |
Drug A N = 981 |
Drug B N = 1021 |
p-value2 | |
|---|---|---|---|---|
| BASELINE CHARACTERISTICS | ||||
| Age | 47 (38, 57) | 46 (37, 60) | 48 (39, 56) | 0.718 |
| Marker Level (ng/mL) | 0.64 (0.22, 1.41) | 0.84 (0.23, 1.60) | 0.52 (0.18, 1.21) | 0.085 |
| DISEASE CHARACTERISTICS | ||||
| Grade | 0.871 | |||
| I | 68 (34%) | 35 (36%) | 33 (32%) | |
| II | 68 (34%) | 32 (33%) | 36 (35%) | |
| III | 64 (32%) | 31 (32%) | 33 (32%) | |
| T Stage | 0.866 | |||
| T1 | 53 (27%) | 28 (29%) | 25 (25%) | |
| T2 | 54 (27%) | 25 (26%) | 29 (28%) | |
| T3 | 43 (22%) | 22 (22%) | 21 (21%) | |
| T4 | 50 (25%) | 23 (23%) | 27 (26%) | |
| OUTCOMES | ||||
| Tumor Response | 61 (32%) | 28 (29%) | 33 (34%) | 0.530 |
| Patient Died | 112 (56%) | 52 (53%) | 60 (59%) | 0.412 |
| 1 Median (Q1, Q3); n (%) | ||||
| 2 Wilcoxon rank sum test; Pearson’s Chi-squared test | ||||
| Data from gtsummary package trial dataset | ||||
This table demonstrates professional formatting suitable for publication:
sumExtras provides powerful tools for creating visually polished tables:
add_group_styling() - Add text
formatting (bold/italic) to group headersadd_group_colors() - Convenience
function for group colors with automatic gt conversionget_group_rows() - Identify group
header rows for further stylinguse_jama_theme() - Apply JAMA compact
theme to gtsummary tablestheme_gt_compact() - Match gt table
styling to gtsummary themeCombine these with gt’s styling functions for complete control over table appearance.
For more information:
vignette("sumExtras-intro") - Getting started with
sumExtrasvignette("labeling") - Automatic variable labeling
workflows?add_group_styling - Function documentation?add_group_colors - Function documentation?get_group_rows - Function documentation?use_jama_theme - Function documentation?theme_gt_compact - Function documentationThe styling system is designed to create professional tables efficiently. Start with simple formatting, then add visual elements as needed to enhance clarity and readability.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.