tbl_custom_summary() builds a summary table whose cells are computed by
functions you supply: means adjusted for covariates, rates, treatment
effects within subgroups, or anything else a function can return. The
table has the structure of tbl_summary(), and add_overall(),
add_p(), add_n(), add_stat_label(), inline_text() and the styling
functions work on it the same way. ratio_summary() and
proportion_summary() build ready-made stat_fns functions.
Usage
tbl_custom_summary(
data,
by = NULL,
label = NULL,
stat_fns,
statistic,
digits = NULL,
type = NULL,
value = NULL,
missing = c("ifany", "no", "always"),
missing_text = "Unknown",
missing_stat = "{N_miss}",
include = everything(),
overall_row = FALSE,
overall_row_last = FALSE,
overall_row_label = "Overall"
)Arguments
- data
(
data.frame)
A data frame.- by
(selector)
A single column ofdata. The statistics are stratified by its levels, one column per level. Rows with a missingbyvalue are dropped with a message. Default isNULL.- label
(formula-list)
Variable labels. The default for each variable is itslabelattribute, or the column name.- stat_fns
(formula-list)
The function computing the statistics of each variable; see the contract below. Required.- statistic
(formula-list)
The statistics shown for each variable, as a string whose curly-brace names are columns of thestat_fnsreturn, e.g.~"{mean} ({conf.low}, {conf.high})". The missing-data statistics ({N_obs},{N_miss},{N_nonmiss},{p_miss},{p_nonmiss}) are also available. Required.- digits
(formula-list)
How the statistics are rounded: integers or formatting functions, possibly named by statistic. When not specified, defaults are guessed from each variable's own values, as for a continuous variable; character and date statistics print as they are.- type
(formula-list)
The summary type. Unliketbl_summary(),"continuous"is accepted for any variable class, since the statistics come fromstat_fns.- value
(formula-list)
The level of a variable to show on a single row.- missing, missing_text, missing_stat
As in
tbl_summary(): whether and how to show a missing-value row.- include
(selector)
Variables to summarize. Default iseverything().- overall_row
(
scalar logical)
Whether to add a first row summarizing all observations. Default isFALSE.- overall_row_last
(
scalar logical)
Whether to place the overall row last. Default isFALSE.- overall_row_label
(
string)
Label of the overall row. Default is"Overall".
The stat_fns contract
Each cell calls the variable's stat_fns function with these named
arguments, so the function should accept ...:
x: for a continuous variable, its non-missing values in the cell;NULLfor categorical and dichotomous variables.data: the cell's rows. For a continuous variable, theby-level subset ofdatawithout thebycolumn and without rows where the variable is missing. For a categorical variable, the rows of one (bylevel, variable level) cell, without thebycolumn and the variable's own column; unused factor levels and empty cells are still called, with zero rows.full_data: the full data frame; for categorical variables, without rows where the variable is missing.variable(string): the variable name.by(character): thebycolumn name; for categorical variables the variable's own name is appended, and withoutbyit ischaracter(0)for continuous variables.strata:NULL.
The function must return a one-row data frame; each column becomes a
statistic available to statistic under the column's name. (gtsummary
2.5.1 documents type and stat_display arguments, but does not pass
them; ltsummary matches what is passed.)
Caution
add_p() tests the row variable against the by variable, ignoring the
summarized values; make sure that test answers your question.
add_ci() does not work on custom summary tables.
See also
Other table builders:
tbl_continuous(),
tbl_cross(),
tbl_likert(),
tbl_merge(),
tbl_regression(),
tbl_stack(),
tbl_strata(),
tbl_strata_nested_stack(),
tbl_summary(),
tbl_survfit(),
tbl_uvregression(),
tbl_wide_summary()
Examples
# Example 1 ----------------------------------
# mean age by tumor grade and treatment
mean_age <- function(data, ...) {
data.frame(mean_age = mean(data$age, na.rm = TRUE))
}
trial |>
tbl_custom_summary(
by = trt,
include = grade,
stat_fns = ~mean_age,
statistic = ~"{mean_age}",
digits = ~1,
overall_row = TRUE
) |>
add_overall(last = TRUE)
# Example 2 ----------------------------------
# response rate with its confidence interval
trial |>
tbl_custom_summary(
by = trt,
include = c(stage, grade),
stat_fns = ~proportion_summary("response", value = 1),
statistic = ~"{prop}% ({conf.low}, {conf.high})",
digits = ~label_style_percent(digits = 1)
)