# gtsummary themes

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. 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 Association—JAMA. 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)

    trial |>
      tbl_summary(by = trt, include = c(age, grade)) |>
      add_p()

Characteristic | Drug A N = 981 | Drug B N = 1021 | p-value2
--- | --- | --- | ---
Age | 46 (37, 60) | 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 (Q1, Q3); 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 – 60) | 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 – 60) | 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 (IQR) | 46 (37 – 60) | 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()`.

    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" = label_style_pvalue(digits = 2),
        "pkgwide-fn:prependpvalue_fun" = label_style_pvalue(digits = 2, prepend_p = TRUE),
        # report median (Q1 - Q2) and n (percent) as default stats in `tbl_summary()`
        "tbl_summary-arg:statistic" = list(all_continuous() ~ "{median} ({p25} - {p75})",
                                           all_categorical() ~ "{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()`.

    set_gtsummary_theme(my_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
--- | --- | ---
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`
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.

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-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: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: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:add_estimate_to_reference_rows`, `tbl_regression-arg:tidy_fun`
tbl_summary
`tbl_summary-arg:digits`, `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`