P-values auto dans ggplot avec geom_pwc (ggpubr)

Une seule couche ajoute comparaisons par paires, crochets et étiquettes ANOVA — groupé, en facettes, ajusté

Ajoutez des p-values par paires à un ggplot en une seule couche avec geom_pwc() de ggpubr — sans rstatix manuel. Annotez des graphiques groupés et en facettes, exécutez des comparaisons intra- vs inter-groupes, ajoutez des étiquettes ANOVA automatiques avec stat_anova_test(), et placez des p-values ajustées sur un graphique multi-panneaux. Chaque exemple est rendu pour vous et s’exécute en direct dans votre navigateur.

Date de publication

22 juin 2026

Modifié

7 juillet 2026

AstuceÀ retenir
  • geom_pwc() est le raccourci moderne en une couche : il exécute les comparaisons par paires et dessine les crochets + p-values en un seul appel — sans étape rstatix séparée.
  • Graphiques groupés : mappez la variable de légende avec aes(group = supp) pour les tests intra-groupes (par ex. OJ vs VC à chaque dose) ; ajoutez group.by = "legend.var" pour les tests inter-groupes (comparer les doses au sein de chaque supplément).
  • Graphiques en facettes : geom_pwc() teste par panneau ; ajustez sur l’ensemble des panneaux d’un coup avec ggadjust_pvalue().
  • Contrôlez la multiplicité avec p.adjust.method + p.adjust.by = "panel" ; étiquetez avec "p.format", "p.adj.format", "p.adj.signif" ou un modèle assemblé, et supprimez ns avec hide.ns = TRUE.
  • stat_anova_test() affiche automatiquement une étiquette d’ANOVA omnibus (avec F, DFn, DFd, taille d’effet) ; stat_pwc() est le jumeau stat_* de geom_pwc().
  • Pour des p-values ajustées sur un graphique multi-panneaux, calculez une fois avec rstatix + add_xy_position() et dessinez avec stat_pvalue_manual().
  • Chaque graphique ci-dessous est rendu pour vous — puis ajustez n’importe quel exemple en direct dans le bac à sable.
Obtenez le livre — R Graphics Essentials (PDF)

Introduction

La leçon add-p-values utilisait stat_compare_means() pour annoter un graphique simple. Mais dès que vos données sont groupées (des boîtes colorées par une seconde variable) ou en facettes (réparties en panneaux), vous vous tournez généralement vers rstatix : calculer le test, appeler add_xy_position(), puis dessiner avec stat_pvalue_manual(). Cela fonctionne — et c’est traité dans la leçon P-values issues de tests statistiques — mais ce sont trois étapes.

L’API la plus récente de ggpubr les condense en une seule couche. geom_pwc() (« comparaisons par paires ») exécute le test et dessine les crochets en un seul + geom_pwc(...) — sans appel rstatix manuel. Deux compagnons le complètent : stat_anova_test() ajoute une étiquette d’ANOVA omnibus automatique, et stat_pwc() est le jumeau de style stat_* de geom_pwc().

Cette leçon enseigne le flux de travail en une couche de bout en bout sur les données intégrées ToothGrowth : graphiques groupés (comparaisons intra- et inter-groupes), graphiques multi-panneaux en facettes, ajustement de la p-value, étiquettes ANOVA automatiques, et — pour le cas que geom_pwc() ne peut ajuster seul — des p-values ajustées sur l’ensemble des panneaux d’une figure multi-panneaux.

geom_pwc() vs stat_compare_means() + rstatix. Tournez-vous vers geom_pwc() quand vous voulez le raccourci moderne : crochets groupés/en facettes en une couche avec ajustement intégré. Tournez-vous vers le flux de travail rstatix + stat_pvalue_manual() quand vous avez besoin d’un contrôle total — un test personnalisé, des crochets placés à la main, des tailles d’effet, ou un ajustement des p-values sur l’ensemble des panneaux que geom_pwc() ne gère que par panneau.

Préparation des données

Chaque exemple ci-dessous est autonome, mais voici la forme des données. Nous utilisons ToothGrowth, transformons dose en facteur, et ajoutons une variable group à deux niveaux afin de pouvoir illustrer les dispositions en grille de facettes.

library(ggpubr)
library(rstatix)

df <- ToothGrowth
df$dose <- factor(df$dose)
df$group <- factor(rep(c("grp1", "grp2"), 30))   # a second factor, for facet grids
head(df, 3)
   len supp dose group
1  4.2   VC  0.5  grp1
2 11.5   VC  0.5  grp2
3  7.3   VC  0.5  grp1

Le raccourci en une couche : comparaisons par paires groupées

Voici la figure que la plupart des gens recherchent : une boîte à moustaches de la longueur des dents par dose, colorée par supplément, avec OJ comparé à VC à chaque dose — le tout depuis une seule couche geom_pwc(). Mappez la variable de légende avec aes(group = supp) ; method = "t_test" choisit le test, label = "p.format" affiche la p-value formatée.

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") +
  # add 5% / 10% headroom so the labels clear the top border
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(aes(group = supp), method = "t_test", label = "p.format",
           tip.length = 0)

A ggpubr grouped box plot of tooth length by dose, coloured by supplement (OJ vs VC), with a geom_pwc t-test p-value drawn over each dose group in one layer.

C’est tout — pas d’appel t_test(), pas d’add_xy_position(), pas de stat_pvalue_manual(). Tout ce qui suit est une variation sur cette unique couche.

Si les étiquettes sont rognées par la bordure supérieure du graphique, ajoutez de la marge avec scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) — 5 % en bas, 10 % en haut.

P-values ajustées & l’étiquette

geom_pwc() expose les mêmes étiquettes que le reste de ggpubr. Passez à la p-value ajustée, accolez les étoiles de signification, et supprimez les comparaisons non significatives :

  • label = "p.format" — p-value brute formatée · label = "p.adj.format" — ajustée
  • label = "p.adj.signif" — seulement les étoiles · label = "{p.adj.format}{p.adj.signif}" — les deux, accolées
  • p.adjust.method = "bonferroni" (et apparentés) fixe la correction · hide.ns = TRUE supprime ns.
library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(aes(group = supp), method = "t_test",
           label = "{p.adj.format}{p.adj.signif}",
           p.adjust.method = "bonferroni",
           hide.ns = TRUE, tip.length = 0)

The same grouped box plot with geom_pwc showing adjusted Bonferroni p-values combined with significance stars, non-significant comparisons hidden.

Ajuster par groupe ou sur l’ensemble du panneau

C’est l’option à intérioriser. Par défaut, les p-values sont ajustées au sein de chaque niveau de groupe indépendamment. Pour corriger toutes les p-values du panneau ensemble, fixez p.adjust.by = "panel".

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(aes(group = supp), method = "t_test", label = "p.adj.format",
           p.adjust.method = "bonferroni", p.adjust.by = "panel",
           remove.bracket = TRUE, tip.length = 0)

A grouped box plot where geom_pwc adjusts all p-values together across the panel via p.adjust.by = panel, with brackets removed.

remove.bracket = TRUE supprime les crochets quand la comparaison est sans ambiguïté (deux groupes à chaque x), et bracket.nudge.y (positif vers le haut, négatif vers le bas) décale les crochets quand ils entrent en collision avec les boîtes.

Empiler deux comparaisons : intra-groupe et inter-groupe

Un graphique groupé prend en charge deux questions distinctes, et vous pouvez superposer les deux sur une figure :

  1. Intra-groupe : comparer les niveaux de légende à chaque position xaes(group = supp) (le défaut, group.by = "x.var"). OJ diffère-t-il de VC à cette dose ?
  2. Inter-groupe : comparer les niveaux de l’axe x au sein de chaque groupe de légende — ajoutez group.by = "legend.var". Les doses diffèrent-elles au sein de OJ ? au sein de VC ?

Ajoutez le premier geom_pwc() pour le test intra-groupe, puis un second pour le test inter-groupe, en le décalant vers le haut pour que les deux jeux de crochets ne se chevauchent pas.

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)
# two doses keeps the figure readable for the inter-group brackets
df2 <- df[df$dose %in% c("0.5", "2"), ]
df2$dose <- factor(df2$dose)

bxp <- ggboxplot(df2, x = "dose", y = "len",
                 color = "supp", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.20)))

# 1. intra-group: OJ vs VC within each dose
bxp <- bxp + geom_pwc(aes(group = supp), method = "t_test",
                      label = "p.format", tip.length = 0)

# 2. inter-group: dose 0.5 vs 2 within each supplement (legend var)
bxp + geom_pwc(aes(group = supp, color = supp), method = "t_test",
               label = "p.format", group.by = "legend.var",
               tip.length = 0, bracket.nudge.y = 0.2)

A ggpubr grouped box plot of tooth length (doses 0.5 and 2) by supplement, with intra-group OJ-vs-VC brackets and a second set of inter-group dose-comparison brackets nudged up so they do not overlap.

Le motif se généralise : group.by = "x.var" teste à travers la légende à chaque x ; group.by = "legend.var" teste à travers x au sein de chaque groupe de légende. bracket.group.by = "legend.var" et dodge affinent l’emplacement des crochets inter-groupes par rapport aux boîtes juxtaposées.

Par paires sur trois groupes ou plus

Avec trois niveaux ou plus sur un axe, geom_pwc() exécute par défaut toutes les comparaisons par paires. Ici, la dose comparée par paires au sein de chaque panneau de supplément — ajustée automatiquement parce que dose a trois niveaux.

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "supp", y = "len", fill = "dose", palette = "npg") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(aes(group = dose), method = "t_test", label = "p.adj.format",
           bracket.nudge.y = -0.08, tip.length = 0)

A ggpubr box plot of tooth length by supplement, filled by dose, with geom_pwc drawing all pairwise dose comparisons and adjusted p-values.

Restreignez les comparaisons en passant method.args au test sous-jacent, ou testez chaque groupe contre une référence avec ref.group (un contrôle). Ici, chaque dose comparée à la référence "0.5" :

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", fill = "dose", palette = "npg") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(aes(group = dose), method = "t_test", label = "p.adj.format",
           ref.group = "0.5", bracket.nudge.y = -0.08, tip.length = 0)

A ggpubr box plot of tooth length by dose with geom_pwc comparing each dose against the reference dose 0.5 using adjusted p-values.

Barres empilées : geom_pwc(stack = TRUE)

Quand les barres sont empilées (position = position_stack()) plutôt que juxtaposées, geom_pwc() ne peut pas lire les positions x juxtaposées par lui-même — passez stack = TRUE pour qu’il place chaque crochet sur le bon segment de pile, et utilisez vjust pour décaler les étoiles vers le bas par rapport au crochet. C’est le seul argument supplémentaire qu’une disposition empilée requiert ; tout le reste (method, label, p.adjust.*) est inchangé.

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

# stacked (not dodged) bars: OJ on VC at each dose
bp <- ggbarplot(df, x = "dose", y = "len", add = "mean_sd",
                color = "supp", palette = "jco",
                position = position_stack())

bp + geom_pwc(aes(group = supp), method = "t_test",
              label = "p.adj.signif",
              p.adjust.method = "bonferroni", p.adjust.by = "panel",
              stack = TRUE, vjust = 0.3, tip.length = 0)

A ggpubr stacked bar plot of mean tooth length by dose, the OJ and VC supplements stacked, with geom_pwc adding a t-test significance star over each dose via stack = TRUE.

Le même stack = TRUE fonctionne sur un ggline() empilé, et se combine avec group.by = "legend.var" pour des comparaisons par paires inter-groupes sur des dispositions empilées.

Graphiques en facettes (multi-panneaux)

geom_pwc() fonctionne à l’intérieur des facettes sans code supplémentaire — passez facet.by au graphique et la couche s’exécute par panneau. Le piège est la multiplicité : au sein d’une facette, les p-values sont calculées et ajustées par panneau, indépendamment des autres panneaux (c’est voulu dans ggplot2).

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", fill = "supp", facet.by = "supp",
          palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(method = "t_test", label = "{p.adj.format}{p.adj.signif}",
           hide.ns = TRUE, tip.length = 0)

A faceted ggpubr box plot of tooth length by dose split into OJ and VC panels, each panel carrying its own geom_pwc pairwise p-values.

Une grille de facettes par deux variables fonctionne de la même façon — passez un vecteur de caractères des deux variables de facette :

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)
df$group <- factor(rep(c("grp1", "grp2"), 30))

ggboxplot(df, x = "supp", y = "len", fill = "#3a86d4",
          facet.by = c("group", "dose")) +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(method = "t_test", label = "p.format", tip.length = 0)

A ggpubr facet-grid box plot of tooth length by supplement across a grid of group and dose panels, each carrying its own geom_pwc t-test p-value.

Ajuster les p-values sur tous les panneaux avec ggadjust_pvalue()

L’ajustement par panneau est parfois trop indulgent — vous avez testé de nombreux panneaux et voulez que la correction couvre l’ensemble d’entre eux. Construisez le graphique en facettes avec geom_pwc() comme d’habitude, puis post-traitez-le avec ggadjust_pvalue(), qui ré-ajuste ensemble chaque p-value de la figure.

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

bxp <- ggboxplot(df, x = "dose", y = "len", fill = "supp",
                 facet.by = "supp", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(method = "t_test")

# re-adjust EVERY p-value in the plot together, then re-label
ggadjust_pvalue(bxp, p.adjust.method = "bonferroni",
                label = "{p.adj.format}{p.adj.signif}",
                hide.ns = TRUE)

A faceted ggpubr box plot where ggadjust_pvalue re-adjusts all panel p-values together with Bonferroni, showing adjusted values and significance stars.

Étiquettes ANOVA automatiques avec stat_anova_test()

Quand la question est celle de l’omnibusy a-t-il quoi que ce soit de différent entre les groupes ?stat_anova_test() dépose sur le graphique une étiquette d’ANOVA à un facteur sans test manuel. Par défaut, il affiche la p-value formatée ; demandez une étiquette détaillée pour faire apparaître la statistique F, les degrés de liberté et la taille d’effet.

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

bxp <- ggboxplot(df, x = "dose", y = "len", fill = "dose",
                 palette = "jco", legend = "none") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10)))

# plain p-value label vs a detailed, italic statistical report
ggarrange(
  bxp + stat_anova_test(),
  bxp + stat_anova_test(label = "as_detailed_italic"),
  ncol = 1
)

Two ggpubr box plots of tooth length by dose: the left with a plain ANOVA p-value, the right with a detailed italic ANOVA label showing F, degrees of freedom and effect size.

stat_anova_test() calcule F, DFn, DFd, p, p.signif et des tailles d’effet (ges/pes), que vous pouvez toutes assembler dans une étiquette personnalisée. Positionnez-la avec label.x/label.y (unités de données) ou label.x.npc/label.y.npc ("left"/"center"/"right", "bottom"/"top").

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", fill = "dose",
          palette = "jco", legend = "none") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.15))) +
  stat_anova_test(
    label = "ANOVA, italic(F)({DFn}, {DFd}) = {F}, eta2[g] = {ges}, italic(p) = {p.format}{p.signif}",
    label.x.npc = "left", hjust = 0, size = 3.3
  )

A ggpubr box plot of tooth length by dose with a custom glued ANOVA label reporting F, degrees of freedom, generalized eta-squared, the p-value and n.

Sur un graphique groupé, stat_anova_test() suit la même logique group.by que geom_pwc() : "x.var" exécute une ANOVA à travers les niveaux de légende à chaque position x ; "legend.var" l’exécute à travers les niveaux x au sein de chaque groupe de légende.

library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.15))) +
  stat_anova_test(aes(group = supp), group.by = "x.var",
                  label = "p = {p.format}{p.signif}")

A ggpubr grouped box plot of tooth length by dose, coloured by supplement, with a stat_anova_test label computed across supplements at each dose position.

stat_pwc() est le jumeau de style stat_* de geom_pwc() — même moteur, mêmes arguments (method, label, ref.group, p.adjust.method), juste l’orthographe stat_. Utilisez celui qui se lit le plus naturellement à côté de vos autres couches ; la sortie est identique.

Plans d’ANOVA : à deux facteurs, à mesures répétées & mixtes

L’ANOVA à un facteur ci-dessus est le défaut, mais stat_anova_test() exécute tous les plans courants via un seul argument — method. Le plan indique à stat_anova_test() comment modéliser les données ; pour tout plan intra-sujets (mesures répétées), vous passez aussi wid =, la colonne contenant l’identifiant de sujet afin que les scores répétés de chaque sujet soient liés.

method = Plan Arguments supplémentaires
"one_way" (défaut) À un facteur, inter-sujets
"two_way" À deux facteurs, inter-sujets aes(group = ...) pour le 2e facteur
"one_way_repeated" À un facteur, intra-sujets wid = "id"
"two_way_repeated" À deux facteurs, les deux intra wid = "id"
"two_way_mixed" Un inter × un intra wid = "id"

ANOVA à deux facteurs

Pour un plan à deux facteurs, mappez le second facteur avec aes(group = ...) et fixez method = "two_way" — l’étiquette rapporte la p-value de l’interaction. ToothGrowth est lui-même un plan à deux facteurs (len ~ supp * dose) :

library(ggpubr)
library(rstatix)
df <- ToothGrowth
df$dose <- factor(df$dose)

# two-way: len ~ supp * dose  →  interaction p-value
ggboxplot(df, x = "supp", y = "len", color = "dose", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  stat_anova_test(aes(group = dose), method = "two_way")

A ggpubr grouped box plot of tooth length by supplement, coloured by dose, with a two-way stat_anova_test label reporting the supplement-by-dose interaction p-value.

ANOVA à un facteur à mesures répétées

Un plan à mesures répétées a besoin d’un identifiant de sujet. Nous utilisons le jeu de données selfesteem du paquet datarium — 10 sujets mesurés chacun à trois instants (t1, t2, t3) sous forme large. Remettez-le en forme longue avec pivot_longer(), transformez id et time en facteurs avec convert_as_factor() de rstatix, puis basculez le plan avec un seul argument : method = "one_way_repeated", wid = "id".

library(ggpubr)
library(rstatix)
library(datarium)

data("selfesteem", package = "datarium")          # wide: id, t1, t2, t3
selfesteem <- selfesteem |>
  tidyr::pivot_longer(c(t1, t2, t3), names_to = "time", values_to = "score") |>
  convert_as_factor(id, time)                      # id + time as factors

ggboxplot(selfesteem, x = "time", y = "score", fill = "time",
          palette = "jco", legend = "none") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  stat_anova_test(method = "one_way_repeated", wid = "id")

A ggpubr box plot of self-esteem score across three time points t1, t2, t3 from the datarium selfesteem dataset, annotated with a one-way repeated-measures ANOVA p-value computed with stat_anova_test using subject id as the within-subject identifier.

À deux facteurs à mesures répétées & mixte à deux facteurs — la recette

Les plans restants sont le même appel avec un method différent et un jeu de données qui porte le facteur supplémentaire. Un plan mixte croise un facteur inter-sujets (group) avec un facteur intra-sujets (time) ; un plan à deux facteurs à mesures répétées a les deux facteurs en intra. Le jeu de données anxiety de datarium a exactement cette forme (un group inter, trois instants intra, liés par id) — remettez en forme et basculez la méthode :

library(ggpubr)
library(rstatix)
library(datarium)

data("anxiety", package = "datarium")             # wide: id, group, t1, t2, t3
anxiety <- anxiety |>
  tidyr::pivot_longer(c(t1, t2, t3), names_to = "time", values_to = "score") |>
  convert_as_factor(id, time)

bxp <- ggboxplot(anxiety, x = "group", y = "score",
                 color = "time", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10)))

# two-way mixed: between group × within time (wid links the within-subject repeats)
bxp + stat_anova_test(aes(group = time), method = "two_way_mixed", wid = "id")

A ggpubr grouped box plot of anxiety score by treatment group, coloured by time point, from the datarium anxiety dataset, with a two-way mixed ANOVA label from stat_anova_test crossing a between-subjects group factor with a within-subjects time factor.

Pour un plan à deux facteurs à mesures répétées où les deux facteurs sont intra-sujets, weightloss de datarium (id, diet, exercises, t1t3) est l’exemple canonique — l’appel est identique, juste method = "two_way_repeated" (tout le reste — aes(group = ...), wid = "id" — est inchangé). Comme avec geom_pwc(), un plan à mesures répétées groupé honore group.by : par ex. stat_anova_test(aes(group = time, color = time), method = "one_way_repeated", wid = "id", group.by = "legend.var") exécute une ANOVA intra-sujets à travers les niveaux x au sein de chaque groupe de légende.

Réétiqueter les étoiles de signification. Toute étiquette stat_anova_test() ou geom_pwc() qui affiche des symboles de signification accepte une liste significance = pour remapper les seuils — par ex. significance = list(cutpoints = c(0, 1e-4, 0.001, 0.01, 0.05, 1), symbols = c("****", "***", "**", "*", "")) efface le marqueur ns (un symbole final vide) au lieu de l’afficher. Insérez vos propres symbols pour correspondre au style d’une revue.

P-values ajustées sur un graphique multi-panneaux (contrôle total)

geom_pwc() ajuste par panneau. Quand vous avez besoin d’une seule correction de multiplicité sur l’ensemble des panneaux d’une figure multi-panneaux et d’un contrôle total sur les crochets, passez au flux de travail rstatix explicite : calculez le test groupé par les variables de panneau, ajustez une seule fois sur l’ensemble d’entre eux, ajoutez les coordonnées des crochets avec add_xy_position(), puis dessinez avec stat_pvalue_manual().

library(ggpubr)
library(rstatix)
df <- ToothGrowth
df$dose <- factor(df$dose)

# 1. test per panel, then adjust ACROSS ALL PANELS together
stat.test <- df %>%
  group_by(dose) %>%
  t_test(len ~ supp) %>%
  adjust_pvalue(method = "bonferroni") %>%   # one correction over every panel
  add_significance()

# 2. bracket coordinates
stat.test <- stat.test %>% add_xy_position(x = "supp")

# 3. plot + manual p-values
ggboxplot(df, x = "supp", y = "len", fill = "dose",
          palette = "npg", facet.by = "dose") +
  stat_pvalue_manual(stat.test, label = "{p.adj}{p.adj.signif}",
                     hide.ns = TRUE, tip.length = 0.01)

A ggpubr faceted box plot of tooth length by supplement across dose panels, annotated with adjusted p-values and significance stars computed once across all panels via rstatix and stat_pvalue_manual.

C’est la passerelle vers la leçon P-values issues de tests statistiques, où le flux de travail complet rstatix + stat_pvalue_manual() — tests personnalisés, tailles d’effet, placement manuel des crochets — est le sujet principal.

Essayez en direct

Les graphiques ci-dessus ont été rendus au moment de la construction. Envie d’expérimenter ? Modifiez le code et appuyez sur Run — il s’exécute dans votre navigateur via webR (pas de serveur, pas d’installation). Essayez de remplacer method par "wilcox_test", de basculer p.adjust.by entre "group" et "panel", ou d’ajouter un second geom_pwc() pour la comparaison inter-groupe.

Vous travaillez en Python ? Un guide basé sur statannotations arrive dans la série Python.

🟢 Avec un agent IA

Demandez à Prova « dois-je laisser geom_pwc() ajuster par groupe ou fixer p.adjust.by = \"panel\" pour mon graphique ? » — elle répond avec du code que vous pouvez exécuter sur votre propre data frame, affiche côte à côte les deux jeux de p-value ajustés, et vérifie les hypothèses du test, pour que le choix soit reproductible. The runtime is the judge. Ask Prova →

Problèmes courants

  • Les étiquettes sont rognées par la bordure supérieure. geom_pwc() dessine les crochets au-dessus des données, et l’axe par défaut n’a pas de marge. Ajoutez scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) — 5 % d’espace en bas, 10 % en haut — ou décalez les crochets vers le bas avec bracket.nudge.y = -0.08.
  • Mes p-values de facette ne sont pas corrigées sur l’ensemble des panneaux. C’est voulu : geom_pwc() ajuste par panneau. Pour corriger sur l’ensemble de la figure, enveloppez le graphique terminé dans ggadjust_pvalue(p, p.adjust.method = "bonferroni", ...), ou calculez avec rstatix + adjust_pvalue() et dessinez avec stat_pvalue_manual().
  • Les crochets intra- et inter-groupes se chevauchent. Ajoutez le geom_pwc() inter-groupe comme seconde couche et poussez-le vers le haut avec bracket.nudge.y = 0.2 ; donnez plus de place à l’axe y avec expansion(mult = c(0.05, 0.20)).
  • label = "p.adj" et label = "p" semblent identiques dans une facette. Quand un panneau n’a qu’une seule comparaison, il n’y a rien à ajuster au sein de ce panneau, donc les valeurs brutes et ajustées coïncident. Utilisez ggadjust_pvalue() pour ajuster sur l’ensemble des panneaux et les deux divergeront.
  • ref.group / comparisons se plaignent des noms de groupes. Dans geom_pwc(), ref.group correspond au niveau du facteurfactor(dose) d’abord, puis utilisez la chaîne du niveau (ref.group = "0.5"). Pour method.args = list(comparisons = ...), passez les comparaisons telles que documentées par le test rstatix sous-jacent.

Questions fréquentes

stat_compare_means() est la couche plus ancienne et plus simple — idéale pour une comparaison unique ou une p-value globale rapide. geom_pwc() est l’API plus récente, en une couche, conçue pour les graphiques groupés et en facettes : il exécute les comparaisons par paires, ajuste les p-values (par groupe ou par panneau), et dessine les crochets en un seul appel, remplaçant une étape manuelle rstatix + stat_pvalue_manual().

Mappez la variable de légende et ajoutez geom_pwc() : ggboxplot(df, x = "dose", y = "len", color = "supp") + geom_pwc(aes(group = supp), method = "t_test", label = "p.format"). Cela compare les niveaux de supplément à chaque dose en une seule couche — aucun calcul de test séparé nécessaire.

Il ajuste par panneau — chaque facette est corrigée indépendamment, ce qui est le fonctionnement de ggplot2. Pour ajuster sur l’ensemble des panneaux ensemble, construisez le graphique avec geom_pwc(), puis post-traitez-le avec ggadjust_pvalue(p, p.adjust.method = "bonferroni", ...), ou calculez le test avec rstatix::adjust_pvalue() et dessinez-le avec stat_pvalue_manual().

Intra-groupe compare les niveaux de légende au sein de chaque position x (par ex. OJ vs VC à chaque dose) — le défaut group.by = "x.var". Inter-groupe compare les niveaux de l’axe x au sein de chaque groupe de légende (par ex. dose 0.5 vs 2 au sein de OJ) — fixez group.by = "legend.var". Vous pouvez superposer les deux appels geom_pwc() sur un graphique, en décalant le second vers le haut avec bracket.nudge.y.

Ajoutez stat_anova_test() : ggboxplot(df, x = "dose", y = "len") + stat_anova_test() affiche une p-value d’ANOVA à un facteur sans test manuel. Utilisez label = "as_detailed_italic" pour le rapport complet (F, degrés de liberté, taille d’effet), ou un modèle assemblé comme label = "ANOVA, italic(p) = {p.format}{p.signif}".

Basculez le plan avec l’argument method : "two_way" (mappez le 2e facteur avec aes(group = ...)), "one_way_repeated", "two_way_repeated", ou "two_way_mixed". Tout plan à mesures répétées (intra-sujets) a aussi besoin de wid = "id", la colonne contenant l’identifiant de sujet, afin que les scores répétés de chaque sujet soient liés — par ex. stat_anova_test(method = "one_way_repeated", wid = "id"). Un plan mixte croise un facteur inter-sujets avec un facteur intra-sujets ; un plan à deux facteurs à mesures répétées a les deux facteurs en intra.

Testez vos connaissances

Complétez l’appel geom_pwc() pour que la comparaison de supplément (OJ vs VC) soit dessinée à chaque dose avec la p-value ajustée, corrigée sur l’ensemble du panneau ensemble (pas par groupe) avec Bonferroni.

# You need three arguments inside geom_pwc():
#   label = "p.adj.format"
#   p.adjust.method = "bonferroni"
#   p.adjust.by = "panel"     # <- corrects ALL p-values together
library(ggpubr) df <- ToothGrowth df$dose <- factor(df$dose) ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) + geom_pwc(aes(group = supp), method = "t_test", label = "p.adj.format", p.adjust.method = "bonferroni", p.adjust.by = "panel")
library(ggpubr)
df <- ToothGrowth
df$dose <- factor(df$dose)

ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) +
  geom_pwc(aes(group = supp), method = "t_test", label = "p.adj.format",
           p.adjust.method = "bonferroni", p.adjust.by = "panel")

Vérification rapide. Vous avez mis un graphique en facettes avec facet.by = "supp" et ajouté geom_pwc(), mais les p-values ne sont pas corrigées sur les deux panneaux. Quel est le bon correctif ?

A. Fixer p.adjust.by = "panel" à l’intérieur de geom_pwc(). B. Envelopper le graphique terminé dans ggadjust_pvalue(p, p.adjust.method = "bonferroni"). C. Rien — geom_pwc() ajuste toujours sur l’ensemble des facettes.

Réponse : B. p.adjust.by = "panel" n’ajuste qu’au sein d’un seul panneau ; sur l’ensemble des facettes, les p-values sont calculées par panneau par conception, vous ré-ajustez donc l’ensemble de la figure avec ggadjust_pvalue() (ou calculez avec rstatix et dessinez avec stat_pvalue_manual()).

Conclusion

geom_pwc() transforme le flux de travail p-value multi-étapes, groupé/en facettes, en une seule couche : mappez la légende avec aes(group = ...), choisissez le method, choisissez le label, et contrôlez la multiplicité avec p.adjust.method + p.adjust.by. Vous avez superposé des comparaisons intra- et inter-groupes sur un graphique groupé, l’avez exécuté à l’intérieur des facettes (et corrigé sur l’ensemble des panneaux avec ggadjust_pvalue()), déposé des étiquettes d’ANOVA automatiques avec stat_anova_test() — sur des plans à un facteur, à deux facteurs, à mesures répétées et mixtes via les arguments method + wid — et, pour une seule correction sur l’ensemble des panneaux, vous vous êtes rabattu sur la voie explicite rstatix + stat_pvalue_manual().

Tournez-vous vers geom_pwc() quand vous voulez le raccourci moderne. Quand vous avez besoin d’un contrôle total — tests personnalisés, crochets placés à la main, tailles d’effet, une correction de multiplicité sur l’ensemble des panneaux — tournez-vous vers la leçon P-values issues de tests statistiques, où le flux de travail rstatix est le sujet. Pour choisir et interpréter les tests eux-mêmes (hypothèses, plan d’ANOVA, taille d’effet), voir la prochaine série statistiques — ggpubr est le pont entre les deux.

Leçons connexes

Vous préférez un livre ? R Graphics Essentials est disponible en PDF téléchargeable — toutes les leçons de cette série, hors ligne et à vous.

Obtenir le livre (PDF) →Les leçons restent gratuites en ligne.
Cette page vous a-t-elle été utile ?

Prouvez que vous savez le faire. Maîtrisez toute la série ggpubr — suivez votre parcours, construisez des projets et obtenez un certificat.

Commencer gratuitement →

Passez à Pro — Prova illimité sur vos propres données et un certificat vérifiable qui atteste la compétence.

dès 15 $/mois facturé annuellement

Passer à Pro →

✓ Vous êtes Pro — continuez. The runtime is the judge.

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN
Note

Cette leçon est reproductible : les figures sont exécutées au moment de la construction (si elles s’affichent, le code fonctionne), et le bac à sable et le quiz se réexécutent en direct dans votre navigateur. The runtime is the judge.

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {P-values auto dans ggplot avec geom\_pwc (ggpubr)},
  date = {2026-06-22},
  url = {https://www.datanovia.com/learn/data-visualization/ggpubr/auto-p-values},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“P-values auto dans ggplot avec geom_pwc (ggpubr).” 2026. June 22. https://www.datanovia.com/learn/data-visualization/ggpubr/auto-p-values.