Given a one-way, independent-groups design
(outcome ~ group), check the ANOVA assumptions and run the post-hoc
test they imply, following the standard decision tree:
each group normal and variances equal: Tukey HSD (
tukey_hsd());each group normal but variances unequal: Games-Howell (
games_howell_test());at least one group not normal: Dunn's test (
dunn_test()).
Normality is assessed per group with the Shapiro-Wilk test applied
to each group's values, routing on the smallest p-value across groups (a
single non-normal group sends the data to the non-parametric test). This is
deliberately not the pooled model residuals, which unequal variances would
make non-normal and so hide the Games-Howell case. Homogeneity of variance
is assessed with Levene's test (levene_test()). Both are judged
at the significance level. The function returns the chosen test's
usual pairwise result, with the selected method and the assumption verdicts
attached (and shown when the result is printed), so the routing is
transparent rather than hidden.
To check the same assumptions before the omnibus test and read off the
recommended omnibus/post-hoc pair, use check_test_assumptions();
its result can be passed back here through .assumptions so the checks
are not repeated. Choosing a test by first testing its assumptions on the
same data has a known cost — see the note in ?check_test_assumptions.
See the Datanovia tutorial Statistical Tests and Assumptions in R for a worked walkthrough.
Usage
posthoc_test(
data,
formula,
significance = 0.05,
...,
.assumptions = NULL,
omnibus = NULL
)
# S3 method for class 'posthoc_test'
print(x, ...)Arguments
- data
a data frame containing the variables in the formula.
- formula
a formula of the form
x ~ groupwherexis a numeric outcome variable andgroupis a factor with two or more levels giving the independent groups.- significance
the significance level used to judge the Shapiro-Wilk and Levene assumption tests. Default is 0.05.
- ...
additional arguments forwarded to the selected post-hoc test, but only those it accepts, so an argument meant for one route does not error on another. In particular
p.adjust.methodis honoured only when Dunn's test is chosen; Tukey HSD and Games-Howell carry their own built-in adjustment and ignore it.- .assumptions
(optional) the tibble returned by
check_test_assumptions()for the same data. When supplied its verdicts are used directly, so the Shapiro-Wilk and Levene tests are not run a second time (useful aftercheck_test_assumptions()has already checked them). DefaultNULL(compute the assumptions here).- omnibus
(optional) an omnibus test result — from
anova_test(),welch_anova_test()orkruskal_test()— that you already ran. If the post-hoc route chosen here belongs to a different family than that omnibus — the families being parametric equal-variance (ANOVA / Tukey), parametric unequal-variance (Welch / Games-Howell) and non-parametric (Kruskal-Wallis / Dunn) — a warning is issued so the two stay coherent (for example ananova_test()omnibus followed by a Games-Howell route). DefaultNULL(no check).- x
an object of class
posthoc_test.
Value
the pairwise comparison table returned by the selected post-hoc test
(a tukey_hsd, games_howell_test or dunn_test object),
additionally classed posthoc_test. The selected method and the
assumption verdicts are stored in the attributes "posthoc.method" and
"assumptions", and printed above the table.
See also
check_test_assumptions(), tukey_hsd(), games_howell_test(),
dunn_test(), levene_test(),
shapiro_test().
The Datanovia tutorial: Statistical Tests and Assumptions in R.
Examples
df <- ToothGrowth
df$dose <- as.factor(df$dose)
# Assumptions hold here, so Tukey HSD is chosen
df %>% posthoc_test(len ~ dose)
#> Post-hoc test chosen: Tukey HSD
#> Normality (Shapiro-Wilk, min across groups): p = 0.164 -> normal
#> Homogeneity of variance (Levene): p = 0.528 -> equal variances
#>
#> # A tibble: 3 × 9
#> term group1 group2 null.value estimate conf.low conf.high p.adj
#> * <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 dose 0.5 1 0 9.13 5.90 12.4 2.00e- 8
#> 2 dose 0.5 2 0 15.5 12.3 18.7 1.12e-11
#> 3 dose 1 2 0 6.37 3.14 9.59 4.25e- 5
#> # ℹ 1 more variable: p.adj.signif <chr>
