A publication figure should carry
its own statistics. ggpubr gives you three complementary
ways to put a test result on a plot, and the right choice depends on how
many groups you have and what you want the reader to see:
geom_pwc(),
stat_compare_means()). Best for a few
groups where every pair matters.stat_cld()). Best for many groups, where
a full set of brackets becomes unreadable.add_test_label()). Answers
“is there any difference?” before the pairwise detail.This vignette shows each, and when to reach for which. All the
examples use rstatix under the hood (already a
ggpubr dependency).
geom_pwc() (“pairwise comparisons”) adds a bracket for
every pair of groups, with the adjusted p-value or significance stars.
Add it to any ggpubr plot.
ggboxplot(tg, x = "dose", y = "len", color = "dose", palette = "jco") +
geom_pwc(method = "t_test", label = "p.adj.format")With several groups the brackets stack into a tall tower.
pack = "auto" packs non-overlapping comparisons onto the
same level, so the figure stays compact – compare the two panels below
(same comparisons, packed on the right):
p <- ggboxplot(tg, x = "dose", y = "len", color = "dose", palette = "jco")
ggarrange(
p + geom_pwc(method = "t_test", label = "p.adj.signif") +
labs(title = "pack = \"none\" (default)"),
p + geom_pwc(method = "t_test", label = "p.adj.signif", pack = "auto") +
labs(title = "pack = \"auto\""),
ncol = 2, common.legend = TRUE, legend = "bottom"
)Hide the non-significant brackets with hide.ns = TRUE,
and append an effect size with the {effsize} token:
ggboxplot(tg, x = "dose", y = "len", color = "dose", palette = "jco") +
geom_pwc(
method = "t_test", label = "{p.adj.signif} (d = {effsize})",
hide.ns = TRUE
)When you have many groups, a full set of pairwise
brackets is unreadable. A compact letter display (CLD)
is the standard alternative: each group gets one or more letters, and
groups that share a letter are not significantly
different. stat_cld() computes the letters from
all-pairwise comparisons and places one label above each group.
InsectSprays has six groups – far too many for brackets,
ideal for letters:
ggboxplot(InsectSprays, x = "spray", y = "count",
color = "spray", palette = "jco") +
stat_cld() +
scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) +
labs(x = "Spray", y = "Insect count")Read it as: sprays sharing a letter (e.g. the group labelled
a) are statistically indistinguishable, while sprays with
no letter in common differ. Switch the underlying test with
method = (e.g. "dunn_test" for a
non-parametric analysis), and set a common label height with
label.y.
| Situation | Use |
|---|---|
| 2-4 groups, every pair of interest | pairwise brackets (geom_pwc()) |
| 5+ groups, or a crowded bracket tower | compact letters (stat_cld()) |
| You only need “is there any difference?” | omnibus label (below) |
Before the pairwise detail, readers often want the single overall
test. add_test_label() adds it as a subtitle – pass the
plot in, get the plot back:
p <- ggboxplot(tg, x = "dose", y = "len", color = "dose", palette = "jco") +
geom_pwc(method = "t_test", label = "p.adj.signif", hide.ns = TRUE)
add_test_label(p, method = "anova")Use method = "kruskal" for the non-parametric
Kruskal-Wallis test. When a second factor is mapped,
group.by = computes a two-way ANOVA and names the effect –
by default the interaction:
p2 <- ggboxplot(tg, x = "supp", y = "len", color = "dose", palette = "jco")
add_test_label(p2, group.by = "dose", type = "text")ggcompare() assembles the whole figure – base plot,
jittered points, group means, packed adjusted-p brackets, and the
omnibus subtitle – in a single call:
See the “Two-Way Comparison Figures with ggcompare()”
vignette for the grouped (two-way) design, and ?geom_pwc,
?stat_cld, ?add_test_label for the full
argument lists.