gtsummary (version 1.6.3)

tests: Tests/methods available in add_p() and add_difference()

Description

Below is a listing of tests available internally within gtsummary.

Tests listed with ... may have additional arguments passed to them using add_p(test.args=). For example, to calculate a p-value from t.test() assuming equal variance, use tbl_summary(trial, by = trt) %>% add_p(age ~ "t.test", test.args = age ~ list(var.equal = TRUE))

Arguments

tbl_summary() %>% add_p()

aliasdescriptionpseudo-codedetails
"t.test"t-testt.test(variable ~ as.factor(by), data = data, conf.level = 0.95, ...)
"aov"One-way ANOVAaov(variable ~ as.factor(by), data = data) %>% summary()
"oneway.test"One-way ANOVAoneway.test(variable ~ as.factor(by), data = data, ...)
"kruskal.test"Kruskal-Wallis testkruskal.test(data[[variable]], as.factor(data[[by]]))
"wilcox.test"Wilcoxon rank-sum testwilcox.test(as.numeric(variable) ~ as.factor(by), data = data, ...)
"chisq.test"chi-square test of independencechisq.test(x = data[[variable]], y = as.factor(data[[by]]), ...)
"chisq.test.no.correct"chi-square test of independencechisq.test(x = data[[variable]], y = as.factor(data[[by]]), correct = FALSE)
"fisher.test"Fisher's exact testfisher.test(data[[variable]], as.factor(data[[by]]), conf.level = 0.95, ...)
"mcnemar.test"McNemar's testtidyr::pivot_wider(id_cols = group, ...); mcnemar.test(by_1, by_2, conf.level = 0.95, ...)
"mcnemar.test.wide"McNemar's testmcnemar.test(data[[variable]], data[[by]], conf.level = 0.95, ...)
"lme4"random intercept logistic regressionlme4::glmer(by ~ (1 \UFF5C group), data, family = binomial) %>% anova(lme4::glmer(by ~ variable + (1 \UFF5C group), data, family = binomial))
"paired.t.test"Paired t-testtidyr::pivot_wider(id_cols = group, ...); t.test(by_1, by_2, paired = TRUE, conf.level = 0.95, ...)
"paired.wilcox.test"Paired Wilcoxon rank-sum testtidyr::pivot_wider(id_cols = group, ...); wilcox.test(by_1, by_2, paired = TRUE, conf.int = TRUE, conf.level = 0.95, ...)
"prop.test"Test for equality of proportionsprop.test(x, n, conf.level = 0.95, ...)
"ancova"ANCOVAlm(variable ~ by + adj.vars)
"emmeans"Estimated Marginal Means or LS-meanslm(variable ~ by + adj.vars, data) %>% emmeans::emmeans(specs =~by) %>% emmeans::contrast(method = "pairwise") %>% summary(infer = TRUE, level = conf.level)When variable is binary, glm(family = binomial) and emmeans(regrid = "response") arguments are used. When group is specified, lme4::lmer() and lme4::glmer() are used with the group as a random intercept.

tbl_svysummary() %>% add_p()

aliasdescriptionpseudo-codedetails
"svy.t.test"t-test adapted to complex survey samplessurvey::svyttest(~variable + by, data)
"svy.wilcox.test"Wilcoxon rank-sum test for complex survey samplessurvey::svyranktest(~variable + by, data, test = 'wilcoxon')
"svy.kruskal.test"Kruskal-Wallis rank-sum test for complex survey samplessurvey::svyranktest(~variable + by, data, test = 'KruskalWallis')
"svy.vanderwaerden.test"van der Waerden's normal-scores test for complex survey samplessurvey::svyranktest(~variable + by, data, test = 'vanderWaerden')
"svy.median.test"Mood's test for the median for complex survey samplessurvey::svyranktest(~variable + by, data, test = 'median')
"svy.chisq.test"chi-squared test with Rao & Scott's second-order correctionsurvey::svychisq(~variable + by, data, statistic = 'F')
"svy.adj.chisq.test"chi-squared test adjusted by a design effect estimatesurvey::svychisq(~variable + by, data, statistic = 'Chisq')
"svy.wald.test"Wald test of independence for complex survey samplessurvey::svychisq(~variable + by, data, statistic = 'Wald')
"svy.adj.wald.test"adjusted Wald test of independence for complex survey samplessurvey::svychisq(~variable + by, data, statistic = 'adjWald')
"svy.lincom.test"test of independence using the exact asymptotic distribution for complex survey samplessurvey::svychisq(~variable + by, data, statistic = 'lincom')
"svy.saddlepoint.test"test of independence using a saddlepoint approximation for complex survey samplessurvey::svychisq(~variable + by, data, statistic = 'saddlepoint')
"emmeans"Estimated Marginal Means or LS-meanssurvey::svyglm(variable ~ by + adj.vars, data) %>% emmeans::emmeans(specs =~by) %>% emmeans::contrast(method = "pairwise") %>% summary(infer = TRUE, level = conf.level)When variable is binary, survey::svyglm(family = binomial) and emmeans(regrid = "response") arguments are used.

tbl_survfit() %>% add_p()

aliasdescriptionpseudo-code
"logrank"Log-rank testsurvival::survdiff(Surv(.) ~ variable, data, rho = 0)
"tarone"Tarone-Ware testsurvival::survdiff(Surv(.) ~ variable, data, rho = 1.5)
"petopeto_gehanwilcoxon"Peto & Peto modification of Gehan-Wilcoxon testsurvival::survdiff(Surv(.) ~ variable, data, rho = 1)
"survdiff"G-rho family testsurvival::survdiff(Surv(.) ~ variable, data, ...)
"coxph_lrt"Cox regression (LRT)survival::coxph(Surv(.) ~ variable, data, ...)
"coxph_wald"Cox regression (Wald)survival::coxph(Surv(.) ~ variable, data, ...)
"coxph_score"Cox regression (Score)survival::coxph(Surv(.) ~ variable, data, ...)

tbl_continuous() %>% add_p()

aliasdescriptionpseudo-code
"anova_2way"Two-way ANOVAlm(continuous_variable ~ by + variable)
"t.test"t-testt.test(continuous_variable ~ as.factor(variable), data = data, conf.level = 0.95, ...)
"aov"One-way ANOVAaov(continuous_variable ~ as.factor(variable), data = data) %>% summary()
"kruskal.test"Kruskal-Wallis testkruskal.test(data[[continuous_variable]], as.factor(data[[variable]]))
"wilcox.test"Wilcoxon rank-sum testwilcox.test(as.numeric(continuous_variable) ~ as.factor(variable), data = data, ...)
"lme4"random intercept logistic regressionlme4::glmer(by ~ (1 \UFF5C group), data, family = binomial) %>% anova(lme4::glmer(variable ~ continuous_variable + (1 \UFF5C group), data, family = binomial))
"ancova"ANCOVAlm(continuous_variable ~ variable + adj.vars)

tbl_summary() %>% add_difference()

aliasdescriptiondifference statisticpseudo-codedetails
"t.test"t-testmean differencet.test(variable ~ as.factor(by), data = data, conf.level = 0.95, ...)
"paired.t.test"Paired t-testmean differencetidyr::pivot_wider(id_cols = group, ...); t.test(by_1, by_2, paired = TRUE, conf.level = 0.95, ...)
"prop.test"Test for equality of proportionsrate differenceprop.test(x, n, conf.level = 0.95, ...)
"ancova"ANCOVAmean differencelm(variable ~ by + adj.vars)
"ancova_lme4"ANCOVA with random interceptmean differencelme4::lmer(variable ~ by + adj.vars + (1 \UFF5C group), data)
"cohens_d"Cohen's Dstandardized mean differenceeffectsize::cohens_d(variable ~ by, data, ci = conf.level, ...)
"smd"Standardized Mean Differencestandardized mean differencesmd::smd(x = data[[variable]], g = data[[by]], std.error = TRUE)
"emmeans"Estimated Marginal Means or LS-meansadjusted mean differencelm(variable ~ by + adj.vars, data) %>% emmeans::emmeans(specs =~by) %>% emmeans::contrast(method = "pairwise") %>% summary(infer = TRUE, level = conf.level)When variable is binary, glm(family = binomial) and emmeans(regrid = "response") arguments are used. When group is specified, lme4::lmer() and lme4::glmer() are used with the group as a random intercept.

tbl_svysummary() %>% add_difference()

aliasdescriptiondifference statisticpseudo-codedetails
"smd"Standardized Mean Differencestandardized mean differencesmd::smd(x = data$variables[[variable]], g = data$variables[[by]], w = weights(data), std.error = TRUE)
"emmeans"Estimated Marginal Means or LS-meansadjusted mean differencesurvey::svyglm(variable ~ by + adj.vars, data) %>% emmeans::emmeans(specs =~by) %>% emmeans::contrast(method = "pairwise") %>% summary(infer = TRUE, level = conf.level)When variable is binary, survey::svyglm(family = binomial) and emmeans(regrid = "response") arguments are used.

Custom Functions

To report a p-value (or difference) for a test not available in gtsummary, you can create a custom function. The output is a data frame that is one line long. The structure is similar to the output of broom::tidy() of a typical statistical test. The add_p() and add_comparison() functions will look for columns called "p.value", "estimate", "conf.low", "conf.high", and "method" for the p-value, difference, confidence interval, and the test name used in the footnote.

Example calculating a p-value from a t-test assuming a common variance between groups.

ttest_common_variance <- function(data, variable, by, ...) {
  data <- data[c(variable, by)] %>% dplyr::filter(complete.cases(.))
  t.test(data[[variable]] ~ factor(data[[by]]), var.equal = TRUE) %>%
  broom::tidy()
}

trial[c("age", "trt")] %>% tbl_summary(by = trt) %>% add_p(test = age ~ "ttest_common_variance")

A custom add_difference() is similar, and accepts arguments conf.level= and adj.vars= as well.

ttest_common_variance <- function(data, variable, by, conf.level, ...) {
  data <- data[c(variable, by)] %>% dplyr::filter(complete.cases(.))
  t.test(data[[variable]] ~ factor(data[[by]]), conf.level = conf.level, var.equal = TRUE) %>%
  broom::tidy()
}

Function Arguments

For tbl_summary() objects, the custom function will be passed the following arguments: custom_pvalue_fun(data=, variable=, by=, group=, type=, conf.level=, adj.vars=). While your function may not utilize each of these arguments, these arguments are passed and the function must accept them. We recommend including ... to future-proof against updates where additional arguments are added.

The following table describes the argument inputs for each gtsummary table type.

argumenttbl_summarytbl_svysummarytbl_survfittbl_continuous
data=A data frameA survey objectA survfit() objectA data frame
variable=String variable nameString variable nameNAString variable name
by=String variable nameString variable nameNAString variable name
group=String variable nameNANAString variable name
type=Summary typeSummary typeNANA
conf.level=Confidence interval levelNANANA
adj.vars=Character vector of adjustment variable names (e.g. used in ANCOVA)NANACharacter vector of adjustment variable names (e.g. used in ANCOVA)
continuous_variable=NANANAString of the continuous variable name