It’s possible to set themes in {gtsummary}. The themes control many aspects of how a table is printed. Function defaults can be controlled with themes, as well as other aspects that are not modifiable with function arguments.

The {gtsummary} package comes with a few themes, and we welcome user-contributed themes as well! Our focus is tables that are ready for publication and encourage themes that assist in that process; for example, the theme_gtsummary_journal(journal = "jama") theme sets defaults that align with the published guidelines from the Journal of the American Medical AssociationJAMA. The defaults in {gtsummary} were written to align with the reporting guidelines for European Urology, The Journal of Urology, Urology, and the British Journal of Urology International.

Setting Themes

To set a pre-defined theme, simply include the theme function in a script or the R console.

theme_gtsummary_journal(journal = "jama")

Use the set_gtsummary_theme() function to set user-defined themes (more on that below).

set_gtsummary_theme(my_custom_theme)

Themes must be set before you create the {gtsummary} tables. Let’s take a look at the default table, comparing data between treatment groups.

Default Theme

library(gtsummary)
library(gt)
library(dplyr)

trial %>%
  select(trt, age, grade) %>%
  tbl_summary(by = trt) %>%
  add_p()
Characteristic Drug A, N = 981 Drug B, N = 1021 p-value2
Age 46 (37, 59) 48 (39, 56) 0.7
    Unknown 7 4
Grade 0.9
    I 35 (36%) 33 (32%)
    II 32 (33%) 36 (35%)
    III 31 (32%) 33 (32%)
1 Median (IQR); n (%)
2 Wilcoxon rank sum test; Pearson’s Chi-squared test

JAMA Theme

Now, the same code with the JAMA theme.

theme_gtsummary_journal(journal = "jama")
#> Setting theme `JAMA`
Characteristic Drug A, N = 98 Drug B, N = 102 p-value1
Age, Median (IQR) 46 (37 – 59) 48 (39 – 56) 0.72
    Unknown 7 4
Grade, n (%) 0.87
    I 35 (36) 33 (32)
    II 32 (33) 36 (35)
    III 31 (32) 33 (32)
1 Wilcoxon rank sum test; Pearson’s Chi-squared test

By setting the theme, we were able to change the default formatting for the p-value and add a dash between the 25th and 75th percentiles.

JAMA + Compact Theme

Themes can be stacked as well. In the example below, the JAMA theme and the compact theme (reduces font size and cell padding) are both called and both themes are utilized.

theme_gtsummary_journal(journal = "jama")
#> Setting theme `JAMA`
theme_gtsummary_compact()
#> Setting theme `Compact`
Characteristic Drug A, N = 98 Drug B, N = 102 p-value1
Age, Median (IQR) 46 (37 – 59) 48 (39 – 56) 0.72
    Unknown 7 4
Grade, n (%) 0.87
    I 35 (36) 33 (32)
    II 32 (33) 36 (35)
    III 31 (32) 33 (32)
1 Wilcoxon rank sum test; Pearson’s Chi-squared test

JAMA + Compact + Language Theme

All {gtsummary} tables can be translated into another language using theme_gtsummary_language()!

Característica Drug A, N = 98 Drug B, N = 102 p-valor1
Age, Mediana (RIQ) 46 (37 – 59) 48 (39 – 56) 0.72
    Desconocido 7 4
Grade, n (%) 0.87
    I 35 (36) 33 (32)
    II 32 (33) 36 (35)
    III 31 (32) 33 (32)
1 Prueba de la suma de rangos de Wilcoxon; prueba chi cuadrado de independencia

Clear all previously set themes using reset_gtsummary_theme().

Writing Themes

Theme Structure

There are many parts of a {gtsummary} table that may be controlled with theme elements. To construct a personalized theme, create a named list of at least one theme element. Here’s an example of a theme that modifies the function that styles p-values and updates the default statistics reported in tbl_summary().

my_theme <-
  list(
    # round large p-values to two places
    "pkgwide-fn:pvalue_fun" = function(x) style_pvalue(x, digits = 2),
    "pkgwide-fn:prependpvalue_fun" = function(x) style_pvalue(x, digits = 2, prepend_p = TRUE),
    # report median (IQR) and n (percent) as default stats in `tbl_summary()`
    "tbl_summary-str:continuous_stat" = "{median} ({p25} - {p75})",
    "tbl_summary-str:categorical_stat" = "{n} ({p})"
  )

Once you create the theme, first check the structure using check_gtsummary_theme(). Then apply or set the theme with set_gtsummary_theme().

Theme Elements

Each theme element follows a naming structure: "<function name>-<input type>:<description>". The function name is the function the change applies to, the input type specifies class or type of the theme element, and the description is brief text characterizing the theme element.

Theme elements fall into two categories. The first is modifying internal behavior of the functions that is not directly controllable by function arguments.

Theme Element Description Example
add_global_p

add_global_p-str:type

set argument default for add_global_p.tbl_regression(type=) and add_global_p.tbl_uvregression(type=)

"II"

add_global_p-str:type

set argument default for add_global_p.tbl_regression(type=) and add_global_p.tbl_uvregression(type=); default is "III"

"II"

add_p.tbl_summary

add_p.tbl_summary-attr:test.categorical

default test for categorical/dichotomous variables

"chisq.test"

add_p.tbl_summary-attr:test.categorical.group_by2

default test for categorical/dichotomous grouped/correlated variables with a 2-level by variable

"lme4"

add_p.tbl_summary-attr:test.categorical.low_count

default test for categorical/dichotomous variables with minimum expected count <5

"fisher.test"

add_p.tbl_summary-attr:test.continuous

default test for continuous variables with a 3- or more level by variable

"aov"

add_p.tbl_summary-attr:test.continuous.group_by2

default test for continuous grouped/correlated variables with a 2-level by variable

"lme4"

add_p.tbl_summary-attr:test.continuous_by2

default test for continuous variables with a 2-level by variable

"t.test"

add_p.tbl_svysummary

add_p.tbl_svysummary-attr:test.categorical

default test for categorical/dichotomous variables

"svy.chisq.test"

add_p.tbl_svysummary-attr:test.continuous

default test for continuous variables

"svy.wilcox.test"

as_flex_table

as_flex_table-lst:addl_cmds

named list of expressions of {flextable} package commands inserted in the as_flex_table() call; do not include the data= argument; the list of expressions is inserted after the named call, e.g. if the named list element is "tab_spanner" the expressions will be inserted after expressions named "tab_spanner"; to see the names of the expressions run as_flex_table(x, return_calls = TRUE) and check the names.

list(autofit = list(rlang::expr(flextable::font(fontname = "Bodoni 72", part = "all")), rlang::expr(flextable::fontsize(size = 8, part = "all"))))

as_gt

as_gt-lst:addl_cmds

named list of expressions of {gt} package commands inserted in the as_gt() call; do not include the data= argument; the list of expressions is inserted after the named call, e.g. if the named list element is "tab_spanner" the expressions will be inserted after expressions named "tab_spanner"; to see the names of the expressions run as_gt(x, return_calls = TRUE) and check the names.

list(tab_spanner = rlang::expr(gt::tab_options(table.font.size = 'small')))

as_hux_table

as_hux_table.gtsummary-lst:addl_cmds

named list of expressions of {huxtable} package commands inserted in the as_hux_table() call; do not include the data= argument; the list of expressions is inserted after the named call, e.g. if the named list element is "tab_spanner" the expressions will be inserted after expressions named "tab_spanner"; to see the names of the expressions run as_hux_table(x, return_calls = TRUE) and check the names.

as_kable_extra

as_kable_extra-lst:addl_cmds

named list of expressions of {kableExtra} package commands inserted in the as_kable_extra() call; do not include the data= argument; the list of expressions is inserted after the named call, e.g. if the named list element is "tab_spanner" the expressions will be inserted after expressions named "tab_spanner"; to see the names of the expressions run as_kable_extra(x, return_calls = TRUE) and check the names.

Package-wide

pkgwide-fn:prependpvalue_fun

function to style p-values throughout package that include a “p” prefix, e.g. “p<0.001” or “p=0.12”; this is common in the inline_text() functions; default is function(x) style_pvalue(x, prepend_p = TRUE)

function(x) style_pvalue(x, digits = 2, prepend_p = TRUE)

pkgwide-fn:pvalue_fun

function to style p-values throughout package; default is style_pvalue

function(x) style_pvalue(x, digits = 2)

pkgwide-lgl:quiet

logical indicating whether to suppress messages or not; default is FALSE

pkgwide-str:ci.sep

string indicating separator between upper and lower bounds of confidence intervals. Default is ", "

" to "

pkgwide-str:language

string indicating language; default is "en"

"es"

pkgwide-str:print_engine

string indicating the default print engine; default is "gt"

"flextable"

pkgwide-str:theme_name

optional name of theme; name is printed when theme loaded

"My Personal Theme"

pkgwide-fun:pre_conversion

function that is executed on the gtsummary object before it is converted with as_gt(), as_flex_table(), etc. Must be a function that can be run on every and any gtsummary object

bold_levels

tbl_regression

tbl_regression-fn:addnl-fn-to-run

a function that will be executed after at the end of each tbl_regression() call

bold_labels

tbl_regression-chr:tidy_columns

character vector of columns from tidy_fun= tibble to print. ‘estimate’ column will always be printed. Select among columns ‘conf.low’, ‘conf.high’, ‘std.error’, ‘statistic’, or ‘p.value’.

c("std.error", "p.value")

tbl_regression-lst:tidy_plus_plus

Additional tidy_plus_plus() arguments. Cannot be one of model=, tidy_fun=, exponentiate=, variable_labels=, show_single_row=, intercept=, include=, conf.level=, conf.int=, or strict= as these are controlled by tbl_regression(). The default value for the additional arguments is list(conf.int = TRUE, add_header_rows = TRUE, add_estimate_to_reference_rows = FALSE).

list(conf.int = TRUE, add_header_rows = TRUE, add_estimate_to_reference_rows = TRUE)

tbl_regression-str:coef_header

string setting the default term for the beta coefficient column header; default is "Beta"

ifelse(exponentiate == TRUE, "exp(coef)", "coef")

tbl_regression-str:ref_row_text

string indicating the text to print on reference rows (default is an em-dash)

"Reference"

tbl_stack

tbl_stack-str:group_header

string indicating the group column header used in as_tibble(), as_flex_table(), etc. where row headers are not supported; default is "**Group**"

"**Group Status**"

tbl_summary

tbl_summary-fn:addnl-fn-to-run

a function that will be executed after at the end of each tbl_summary() call

bold_labels

tbl_summary-fn:N_fun

function to style integers. Currently questioning…THIS MAY BE REMOVED IN A FUTURE RELEASE. Use style_number-arg:big.mark and style_number-arg:decimal.mark instead.

function(x) sprintf("%.0f", x)

tbl_summary-fn:percent_fun

function to style percentages; default is style_percent

function(x) style_percent(x)

tbl_summary-str:categorical_stat

glue string defining the default categorical and dichotomous summary statistics to display; default is "{n} ({p}%)". Also sets default statistic for tbl_svysummary()

"{n} / {N} ({p}%)"

tbl_summary-str:continuous_stat

glue string defining the default continuous summary statistics to display; default is "{median} ({p25}, {p75})". Also sets default statistic for tbl_svysummary()

"{mean} ({sd})"

tbl_summary-str:default_con_type

string indicating the default summary type for continuous variables; default is "continuous"; update to "continuous2" for multi-line summaries of continuous variables

"continuous2"

tbl_summary-str:missing_stat

string indicating the statistic(s) to present on the missing row. The default is "{N_miss}". Select among c("N_miss", "N_obs", "p_miss", "N_nonmiss", "p_nonmiss")

"{N_miss} ({p_miss}%)"

tbl_summary-str:header-noby

string indicating the statistic header when there is no by variable present

"N={N}"

tbl_summary-str:header-withby

string indicating the statistic header when there is a by variable present

"**{level}** \nN={n}"

tbl_svysummary

tbl_svysummary-fn:addnl-fn-to-run

a function that will be executed after at the end of each tbl_svysummary() call

bold_labels

tbl_svysummary-str:header-noby

string indicating the statistic header when there is no by variable present

"N={N}"

tbl_svysummary-str:header-withby

string indicating the statistic header when there is a by variable present

"**{level}** \nN={n}"

add_difference

add_difference-fn:addnl-fn-to-run

a function that will be executed after at the end of each add_difference() call

bold_labels

The second type of theme elements set function argument defaults. The values of these theme elements must align with the functions’ accepted input for the argument.

Theme Element
add_p.tbl_cross

add_p.tbl_cross-arg:pvalue_fun, add_p.tbl_cross-arg:source_note, add_p.tbl_cross-arg:test

add_p.tbl_summary

add_p.tbl_summary-arg:pvalue_fun, add_p.tbl_summary-arg:test

add_p.tbl_svysummary

add_p.tbl_svysummary-arg:pvalue_fun, add_p.tbl_svysummary-arg:test

add_q

add_q-arg:method, add_q-arg:pvalue_fun

add_stat_label

add_stat_label-arg:location

as_kable

as_kable-arg:dots

style_number

style_number-arg:big.mark, style_number-arg:decimal.mark

tbl_regression

tbl_regression-arg:conf.level, tbl_regression-arg:conf.int, tbl_regression-arg:estimate_fun, tbl_regression-arg:pvalue_fun, tbl_regression-arg:add_estimate_to_reference_rows, tbl_regression-arg:tidy_fun

tbl_summary

tbl_summary-arg:digits, tbl_summary-arg:label, tbl_summary-arg:missing, tbl_summary-arg:missing_text, tbl_summary-arg:percent, tbl_summary-arg:sort, tbl_summary-arg:statistic, tbl_summary-arg:type, tbl_summary-arg:value

tbl_survfit

tbl_survfit-arg:statistic

tbl_svysummary

tbl_svysummary-arg:digits, tbl_svysummary-arg:label, tbl_svysummary-arg:missing, tbl_svysummary-arg:missing_text, tbl_svysummary-arg:percent, tbl_svysummary-arg:sort, tbl_svysummary-arg:statistic, tbl_svysummary-arg:type, tbl_svysummary-arg:value

tbl_custom_summary

tbl_custom_summary-arg:digits, tbl_custom_summary-arg:label, tbl_custom_summary-arg:missing, tbl_custom_summary-arg:missing_text, tbl_custom_summary-arg:type, tbl_custom_summary-arg:value