P-values de tests statistiques sur ggplot en R (rstatix)

Calculez un test avec rstatix, positionnez les crochets, dessinez-les sur n’importe quel graphique ggpubr — de base, groupé, en facettes et horizontal

Ajoutez des p-values issues de vrais tests statistiques à un ggplot en R avec rstatix et ggpubr. Le flux de travail est toujours le même : calculez un test avec t_test() / wilcox_test() / anova_test(), ajustez pour la multiplicité avec adjust_pvalue(), placez automatiquement les crochets avec add_xy_position(), puis dessinez-les avec stat_pvalue_manual() — sur des graphiques de base, groupés, en facettes, à échelle libre et horizontaux. Chaque exemple est rendu pour vous et s’exécute en direct.

Date de publication

22 juin 2026

Modifié

12 juillet 2026

AstuceÀ retenir
  • Le flux de travail est en trois étapes, toujours les mêmes : calculer le test avec rstatix (t_test(), wilcox_test(), anova_test()), positionner les crochets avec add_xy_position(), puis dessiner ceux-ci avec stat_pvalue_manual().
  • Obtenez des p-values ajustées avec adjust_pvalue() + add_significance() — puis étiquetez avec "p.adj" ou les étoiles "p.adj.signif".
  • Graphiques groupés : faites le test avec group_by(), puis add_xy_position(dodge = 0.8) pour que les crochets s’alignent sur les boîtes juxtaposées.
  • Graphiques en facettes : groupez par la variable de facette avec group_by() ; pour des panneaux à axes y différents, ajoutez scales = "free" à la fois dans add_xy_position() et dans la facette.
  • Graphiques horizontaux : passez coord.flip = TRUE à stat_pvalue_manual() et ajoutez coord_flip().
  • 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 compagne Add p-values to ggplots utilise un seul appel, stat_compare_means(), qui calcule et dessine le test ensemble — parfait pour une annotation rapide. Mais dès que vous avez besoin de p-values ajustées sur les crochets, d’un test spécifique (anova_test(), tukey_hsd()), ou de p-values sur un graphique groupé / en facettes / horizontal, vous voulez le test sous forme de data frame que vous contrôlez, puis dessiné séparément.

C’est le flux de travail rstatix → ggpubr, et il ne change jamais :

  1. Calculer le test avec rstatixt_test(), wilcox_test(), anova_test() (voir les guides de biostatistique pour savoir quand utiliser chacun) — et facultativement adjust_pvalue() + add_significance() pour des p-values corrigées pour la multiplicité et des étoiles.
  2. Positionner les crochets automatiquement avec add_xy_position() — la fonction lit le type de graphique (boîte, barre, juxtaposé, en facettes) et calcule une y.position sensée pour chaque comparaison.
  3. Dessiner ceux-ci sur le graphique avec stat_pvalue_manual() [ggpubr] — pointez son label vers n’importe quelle colonne de votre test ("p", "p.adj", "p.adj.signif").

Cette leçon parcourt ce flux de travail sur les données intégrées ToothGrowth, à travers toutes les dispositions que les gens recherchent réellement : comparaisons de base, graphiques groupés (juxtaposés), panneaux en facettes, facettes à échelles libres / différentes, et graphiques horizontaux. Chaque figure est rendue ici même, et vous pouvez ré-exécuter ou modifier n’importe laquelle en direct.

Si vous avez seulement besoin d’une p-value globale ou par paire rapide, sans ajustement, commencez par stat_compare_means() — c’est le point d’entrée le plus simple. Pour le raccourci moderne en une couche qui calcule et positionne en un seul appel, voir Auto p-values with geom_pwc().

Le flux de travail canonique : calculer → positionner → dessiner

Voici l’image que la plupart des gens recherchent : une boîte à moustaches de la longueur des dents par dose, avec un crochet et une étoile de signification ajustée au-dessus de chaque paire de doses. Lisez-la de haut en bas — les trois étapes sont indiquées dans le code.

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

# 1. COMPUTE: pairwise t-tests, p-values adjusted for multiplicity
stat.test <- df %>%
  t_test(len ~ dose) %>%
  adjust_pvalue(method = "holm") %>%
  add_significance("p.adj")

# 2. POSITION: auto-place the brackets for this box plot
stat.test <- stat.test %>% add_xy_position(x = "dose")

# 3. DRAW: put the adjusted stars on the plot
ggboxplot(df, x = "dose", y = "len", fill = "dose", palette = "jco") +
  stat_pvalue_manual(stat.test, label = "p.adj.signif", tip.length = 0.01)

A ggpubr box plot of tooth length by dose with three pairwise comparison brackets (0.5 vs 1, 1 vs 2, 0.5 vs 2) carrying adjusted significance stars computed with rstatix t_test.

Tout le reste dans cette leçon est une variation sur ces trois étapes. Construisons-les progressivement.

Comparaisons de base : deux groupes et une étiquette nette

Commencez par le cas le plus simple — les deux suppléments (OJ vs VC) diffèrent-ils ? Calculez un t_test() (utilisez wilcox_test() pour la version non paramétrique — même appel), ajoutez la position, et dessinez la p-value brute. add_significance() ajoute la colonne d’étoiles p.signif pour plus tard.

library(ggpubr)
library(rstatix)
df <- ToothGrowth

# Compute: t-test of len by supplement
stat.test <- df %>%
  t_test(len ~ supp) %>%
  add_significance()
stat.test
# A tibble: 1 × 9
  .y.   group1 group2    n1    n2 statistic    df      p p.signif
  <chr> <chr>  <chr>  <int> <int>     <dbl> <dbl>  <dbl> <chr>   
1 len   OJ     VC        30    30      1.92  55.3 0.0606 ns      
# Position + draw
stat.test <- stat.test %>% add_xy_position(x = "supp")
ggboxplot(df, x = "supp", y = "len", fill = "#3a86d4") +
  stat_pvalue_manual(stat.test, label = "p") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.1)))

A ggpubr box plot of tooth length by supplement (OJ vs VC) with a single bracket carrying the t-test p-value.

Les colonnes que vous étiquetterez méritent d’être connues : p (p-value brute), p.adj (ajustée), p.signif / p.adj.signif (les étoiles), et y.position (ajoutée par add_xy_position()).

Les étiquettes sont partiellement masquées par la bordure supérieure ? Ajoutez de la marge avec scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) — 5 % de marge en bas, 10 % en haut, pour que les crochets ne soient pas coupés.

Choisir et formater l’étiquette

Pointez label vers la colonne de votre choix — ou construisez-en une sur mesure. Un modèle glue comme "T-test, p = {p}" interpole n’importe quelle colonne dans l’étiquette ; vous pouvez aussi formater les nombres vous-même.

library(ggpubr)
library(rstatix)
df <- ToothGrowth

stat.test <- df %>% t_test(len ~ supp)
stat.test <- stat.test %>% add_xy_position(x = "supp")

ggboxplot(df, x = "supp", y = "len", fill = "#3a86d4") +
  stat_pvalue_manual(
    stat.test, label = "T-test, p = {p}",
    vjust = -1, bracket.nudge.y = 1
    ) +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.15)))

A ggpubr box plot of tooth length by supplement with a glue-formatted label reading T-test, p = the p-value.

Quelques recettes d’étiquettes que vous réutiliserez :

  • P-value formatée avec une précision contrôlée — p_format(stat.test$p, accuracy = 0.01, leading.zero = FALSE) dans une nouvelle colonne, puis label = "p.format" (affiche <.01).
  • Notation scientifiqueformat(stat.test$p, scientific = TRUE) dans une colonne, puis étiquetez-la.
  • Afficher p si significatif, sinon “ns” — construisez une colonne sur mesure avec ifelse(stat.test$p <= 0.05, stat.test$p, "ns") et étiquetez-la.

Échantillons appariés

Si les mêmes sujets ont été mesurés dans les deux conditions, passez paired = TRUE au test pour qu’il tienne compte de l’appariement. ggpaired() dessine les observations appariées avec des lignes de liaison.

library(ggpubr)
library(rstatix)
df <- ToothGrowth

stat.test <- df %>%
  t_test(len ~ supp, paired = TRUE) %>%
  add_significance()

stat.test <- stat.test %>% add_xy_position(x = "supp")
ggpaired(df, x = "supp", y = "len", fill = "#E7B800",
         line.color = "gray", line.size = 0.4) +
  stat_pvalue_manual(stat.test, label = "{p}{p.signif}")

A ggpubr paired plot of tooth length by supplement with gray lines connecting matched observations and a paired t-test star annotated above.

Par paires sur trois groupes + un groupe de référence

Pour trois groupes ou plus, t_test(len ~ dose) exécute toutes les comparaisons par paires et ajuste les p-values automatiquement. Souvent, vous voulez plutôt chaque groupe par rapport à une référence (un contrôle) — fixez ref.group. L’argument tip.length raccourcit les petites extrémités verticales du crochet.

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

bxp <- ggboxplot(df, x = "dose", y = "len", fill = "dose", palette = "jco")

# All pairwise comparisons
all.pairs <- df %>% t_test(len ~ dose) %>% add_xy_position(x = "dose")
p1 <- bxp + stat_pvalue_manual(all.pairs, label = "p.adj.signif", tip.length = 0.01)

# Each dose vs the reference 0.5
ref <- df %>% t_test(len ~ dose, ref.group = "0.5") %>% add_xy_position(x = "dose")
p2 <- bxp + stat_pvalue_manual(ref, label = "p.adj.signif", tip.length = 0.01)

ggarrange(p1, p2, ncol = 2)

Two ggpubr box plots side by side: left shows all pairwise dose comparisons with stars, right compares every dose to the reference 0.5.

Deux raccourcis de référence à connaître :

  • ref.group = "all" — compare chaque groupe à l’ensemble des données regroupées (la moyenne générale / base-mean), une façon nette de repérer quels groupes se démarquent.
  • Test à un échantillont_test(len ~ 1) (éventuellement précédé de group_by()) compare la moyenne de chaque groupe à un mu hypothétique (0 par défaut).

Vous pouvez aussi outrepasser le placement automatique : passez y.position = c(35, 40, 35) et bracket.shorten = 0.05 directement à stat_pvalue_manual() pour ajuster à la main des crochets encombrés.

Le test omnibus : ANOVA / Kruskal-Wallis

Avant les crochets par paires, vous voulez souvent le test global (« y a-t-il quelque chose de différent ? »). rstatix vous le donne aussi sous forme de tableau soigné : anova_test() pour le paramétrique, kruskal_test() pour le non paramétrique. Annotez-le en sous-titre avec get_test_label() tandis que les crochets portent les résultats par paires.

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

# Global one-way ANOVA
aov.test <- df %>% anova_test(len ~ dose)

# Pairwise comparisons for the brackets
pwc <- df %>%
  t_test(len ~ dose) %>%
  add_xy_position(x = "dose")

ggboxplot(df, x = "dose", y = "len", fill = "dose", palette = "jco") +
  stat_pvalue_manual(pwc, label = "p.adj.signif", tip.length = 0.01) +
  labs(subtitle = get_test_label(aov.test, detailed = TRUE))

A ggpubr box plot of tooth length by dose with three pairwise brackets and a global ANOVA p-value printed in the subtitle.

Remplacez anova_test() par kruskal_test() (et t_test() par wilcox_test()) pour obtenir la paire non paramétrique — le reste de l’appel est identique.

Graphiques groupés (juxtaposés)

Quand la couleur divise chaque position x en plusieurs boîtes juxtaposées, le test doit être groupé et les crochets doivent suivre la juxtaposition. Groupez les données par dose, comparez les niveaux de supp au sein de chacune, puis indiquez à add_xy_position() le même dodge que celui utilisé sur le graphique.

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

# Compute within each dose: OJ vs VC
stat.test <- df %>%
  group_by(dose) %>%
  t_test(len ~ supp) %>%
  adjust_pvalue(method = "bonferroni") %>%
  add_significance("p.adj")

# Position with the SAME dodge as the plot
stat.test <- stat.test %>% add_xy_position(x = "dose", dodge = 0.8)

ggboxplot(df, x = "dose", y = "len",
          color = "supp", palette = c("#00AFBB", "#E7B800")) +
  stat_pvalue_manual(stat.test, label = "p.adj", tip.length = 0) +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.1)))

A grouped ggpubr box plot of tooth length by dose, dodged by supplement, with an adjusted p-value bracket within each dose.

Options utiles sur la disposition groupée :

  • remove.bracket = TRUE — supprime le crochet et n’affiche que l’étiquette (pratique quand les boîtes sont étroites).
  • hide.ns = TRUE — masque les annotations non significatives ; combinez avec une étiquette composite "{p.adj}{p.adj.signif}".
  • Diagrammes en barres / courbes — pour ggbarplot(..., add = "mean_sd") ou ggline(..., add = "mean_sd"), passez le fun = "mean_sd" correspondant à add_xy_position() pour que le crochet démarre au-dessus des barres d’erreur.

Crochets par paires groupés par couleur

Pour dessiner plusieurs crochets par paires par groupe, groupez le test par la variable x, puis empilez les crochets au sein de chaque groupe avec step.group.by + step.increase.

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

# Within each supplement, compare the doses
pwc <- df %>%
  group_by(supp) %>%
  t_test(len ~ dose, p.adjust.method = "bonferroni")

pwc <- pwc %>% add_xy_position(x = "supp", group = "dose", dodge = 0.8)

ggboxplot(df, x = "supp", y = "len", color = "dose", palette = "npg") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.25))) +
  stat_pvalue_manual(
    pwc, step.group.by = "supp",
    tip.length = 0, step.increase = 0.1
    )

A grouped ggpubr box plot of tooth length by supplement, coloured by dose, with pairwise dose brackets coloured and stacked per supplement group.

Graphiques en facettes

Pour un graphique à plusieurs panneaux, groupez le test par la variable de facette afin que chaque panneau obtienne sa propre comparaison, puis positionnez et dessinez exactement comme avant — stat_pvalue_manual() associe chaque ligne du test à son panneau.

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

# One test per facet (dose), comparing OJ vs VC
stat.test <- df %>%
  group_by(dose) %>%
  t_test(len ~ supp) %>%
  adjust_pvalue(method = "bonferroni") %>%
  add_significance()

stat.test <- stat.test %>% add_xy_position(x = "supp")

ggboxplot(df, x = "supp", y = "len", fill = "#00AFBB", facet.by = "dose") +
  stat_pvalue_manual(stat.test, hide.ns = TRUE, label = "{p.adj}{p.adj.signif}") +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.1)))

A ggpubr box plot of tooth length by supplement, faceted by dose, with an adjusted p-value bracket in each panel.

La même recette monte en charge :

  • Par paires au sein d’une facette — quand chaque panneau contient 3 groupes ou plus, group_by(facet_var) puis add_y_position() (la fonction d’aide y seule) au lieu de add_xy_position().
  • facet_grid par deux variables — groupez le test avec group_by(var1, var2) et le graphique avec facet = c("var1", "var2") ; tout le reste est inchangé.
  • Diagrammes en barres en facettesggbarplot(..., add = "mean_sd") avec add_xy_position(fun = "mean_sd") (utilisez fun = "max" si vous ajoutez aussi un jitter, pour que les crochets dépassent les points).

Graphiques en facettes à échelles libres / différentes

Quand les panneaux ont des plages y très différentes, des échelles fixes écrasent certains panneaux. Définir scales = "free" corrige le graphique — mais les crochets doivent aussi être repositionnés en conséquence : passez scales = "free" également à add_xy_position(), et utilisez facet_wrap() pour que chaque panneau libère les deux axes. Ici, nous utilisons tukey_hsd() (post-hoc de Tukey) pour les tests par paires.

library(ggpubr)
library(rstatix)
df <- ToothGrowth
df$dose <- factor(df$dose)
df$group <- factor(rep(c("grp1", "grp2"), 30))
# Make the panels genuinely different in scale
df[c(1, 3, 5), "len"] <- c(500, 495, 505)

# Tukey post-hoc within each supp x group panel
stat.test <- df %>%
  group_by(supp, group) %>%
  tukey_hsd(len ~ dose)

# Position for FREE scales: pass scales = "free" here too
stat.test <- stat.test %>%
  add_xy_position(x = "dose", fun = "mean_se", scales = "free")

ggbarplot(df, x = "dose", y = "len", fill = "#00AFBB",
          add = "mean_se", facet.by = c("supp", "group")) +
  facet_wrap(vars(supp, group), scales = "free") +
  stat_pvalue_manual(stat.test, hide.ns = TRUE, tip.length = 0) +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.15)))

A ggpubr bar plot of tooth length by dose faceted by supplement and group with free y-scales, each panel carrying correctly positioned significance brackets.

facet_wrap vs facet_grid avec des échelles libres. facet_wrap() libère les deux axes par panneau, si bien que chaque graphique est indépendant — idéal quand les panneaux sont sans rapport. facet_grid(scales = "free") ne libère qu’au sein d’une ligne/colonne, si bien que les crochets peuvent encore nécessiter un ajustement : fixez step.increase = 0 dans add_xy_position() et fournissez-le (par panneau) dans stat_pvalue_manual() à la place, ou ajustez à la main avec un vecteur bracket.nudge.y.

Variables réponses multiples

Il arrive que vous mesuriez plusieurs réponses sur les mêmes sujets — quatre mesures de fleur, un panel de biomarqueurs — et que vous vouliez la même comparaison de groupes sur chacune, avec toutes les p-values sur une seule figure. L’astuce est de les tester ensemble : remodelez les données pour que chaque réponse s’empile dans une seule colonne value, indexée par une colonne variables, puis group_by(variables) et exécutez un test par réponse.

Remodelez du format large → long avec stack() de base R (aucun package supplémentaire), groupez par la réponse, et calculez un t_test() de value ~ Species au sein de chaque groupe. adjust_pvalue() corrige l’ensemble des tests d’un coup, et add_xy_position(scales = "free") donne à chaque panneau sa propre hauteur de crochet — essentiel ici, puisque les mesures de pétale et de sépale se situent sur des échelles très différentes.

library(ggpubr)
library(rstatix)

# Reshape WIDE -> LONG: stack the four numeric columns into value + variables
iris.long <- stack(iris[, 1:4])              # columns: values, ind
iris.long$Species <- rep(iris$Species, times = 4)
names(iris.long) <- c("value", "variables", "Species")

# One test per outcome: compare the three species within each variable
stat.test <- iris.long %>%
  group_by(variables) %>%
  t_test(value ~ Species) %>%
  adjust_pvalue(method = "holm") %>%
  add_significance("p.adj")

# Position for FREE scales, then facet by the outcome
stat.test <- stat.test %>% add_xy_position(x = "Species", scales = "free")

ggboxplot(iris.long, x = "Species", y = "value", fill = "Species", palette = "npg") +
  facet_wrap(~variables, scales = "free") +
  stat_pvalue_manual(stat.test, label = "p.adj.signif", tip.length = 0.01) +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.1)))

A ggpubr box plot of the four iris measurements in four free-scale panels — Sepal.Length, Sepal.Width, Petal.Length, Petal.Width — each comparing setosa, versicolor and virginica with pairwise adjusted-significance brackets.

Chaque panneau représente une réponse, testée pour elle-même : les espèces diffèrent sur chaque mesure (le plus souvent ****, la largeur de sépale plus proche versicolor-vs-virginica se situant à **), et chaque crochet se place à la bonne hauteur parce que scales = "free" a été passé à la fois à add_xy_position() et facet_wrap() — la même règle que pour les facettes à échelles libres ci-dessus. Un seul tableau stat.test, une seule figure, chaque réponse couverte.

Nommez la colonne clé variables, et non variable. rstatix utilise variable en interne, si bien qu’une colonne littéralement nommée variable entre en conflit avec add_xy_position() (names are duplicated). Tout autre nom — variables, outcome — fonctionne.

Graphiques horizontaux

Pour basculer un graphique à l’horizontale, vous ajoutez coord_flip() — mais les crochets sont dessinés dans le système de coordonnées d’origine, ils doivent donc être informés du basculement. Passez coord.flip = TRUE à stat_pvalue_manual() et ajoutez coord_flip().

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

stat.test <- df %>% t_test(len ~ dose) %>% add_xy_position(x = "dose")

ggboxplot(df, x = "dose", y = "len", fill = "dose", palette = "jco") +
  stat_pvalue_manual(
    stat.test, label = "p.adj.signif", tip.length = 0.01,
    coord.flip = TRUE
    ) +
  coord_flip()

A horizontal ggpubr box plot of tooth length by dose with pairwise significance-star brackets correctly drawn for the flipped coordinates.

Pour une comparaison à un groupe de référence, ou pour redresser les étiquettes à la verticale, les mêmes arguments que vous utiliseriez à l’endroit s’appliquent toujours — label = "p = {p.adj}", angle = 90, et hjust / vjust pour décaler le texte — aux côtés de coord.flip = TRUE et coord_flip().

P-values calculées entièrement ailleurs

stat_pvalue_manual() ne se soucie pas de comment les p-values ont été produites — si vous avez un data frame avec group1, group2, une colonne d’étiquette et une y.position, il les dessinera. C’est la porte de sortie pour des résultats issus de n’importe quel test, même en dehors de R.

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

# A hand-built results frame (could come from anywhere)
stat.test <- data.frame(
  group1   = c("0.5", "0.5", "1"),
  group2   = c("1",   "2",   "2"),
  p.adj    = c(2.5e-07, 1.3e-13, 1.9e-05)
)

ggboxplot(df, x = "dose", y = "len") +
  stat_pvalue_manual(
    stat.test, y.position = 35, step.increase = 0.1,
    label = "p.adj"
    )

A ggpubr box plot of tooth length by dose with three brackets carrying p-values supplied directly as a hand-built data frame.

Pour un contrôle total sur une seule annotation — texte personnalisé, expressions plotmath, crochets exactement placés — utilisez geom_bracket() :

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

ggboxplot(df, x = "dose", y = "len") +
  geom_bracket(
    xmin = c("0.5", "1"), xmax = c("1", "2"),
    y.position = c(30, 35), label = c("***", "**"),
    tip.length = 0.01
  )

A ggpubr box plot of tooth length by dose with two manually specified brackets carrying custom significance-star labels.

La recette ne change jamais : calculez le test avec rstatix, positionnez avec add_xy_position(), dessinez avec stat_pvalue_manual() — et geom_bracket() est là pour l’annotation personnalisée ponctuelle.

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 t_test par wilcox_test, de changer ref.group, ou de pointer label vers "p.adj" au lieu de "p.adj.signif".

🟢 Avec un agent IA

Demandez à Prova « mes crochets stat_pvalue_manual() flottent au mauvais endroit sur mon graphique groupé — comment corriger add_xy_position() ? » — elle répond avec du code que vous pouvez exécuter sur votre propre data frame et vérifie les arguments dodge/fun/scales par rapport à votre graphique, pour que la correction soit reproductible. The runtime is the judge. Demander à Prova →

Problèmes courants

  • Les crochets flottent au mauvais endroit sur un graphique groupé. add_xy_position() doit connaître la juxtaposition — passez le même dodge que celui donné au graphique (par ex. add_xy_position(x = "dose", dodge = 0.8)). Pour les diagrammes en barres/courbes, ajoutez le fun correspondant (par ex. fun = "mean_sd") pour que le crochet dépasse les barres d’erreur.
  • add_xy_position() échoue avec « object ‘p.adj’ not found ». Calculez la colonne avant de l’étiqueter : adjust_pvalue() crée p.adj, et add_significance("p.adj") crée p.adj.signif. Exécutez ces étapes avant stat_pvalue_manual(label = "p.adj.signif").
  • Les crochets sur une facette à échelle libre sont mal positionnés. scales = "free" doit être défini aux deux endroits — add_xy_position(..., scales = "free") et la facette (facet_wrap(..., scales = "free")). Le définir seulement sur le graphique laisse les positions y calculées pour une échelle fixe.
  • Les crochets horizontaux sont dessinés à la verticale (ou hors du graphique). coord_flip() seul ne suffit pas — passez aussi coord.flip = TRUE à stat_pvalue_manual() pour qu’il bascule la géométrie du crochet.
  • Les étiquettes sont coupées par la bordure supérieure. Ajoutez de la marge : scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))).

Questions fréquentes

Utilisez le flux de travail rstatix → ggpubr : calculez le test sous forme de data frame avec df %>% t_test(len ~ dose) (ou anova_test(), wilcox_test()), positionnez les crochets avec add_xy_position(x = "dose"), puis dessinez-les avec ggboxplot(...) + stat_pvalue_manual(stat.test, label = "p.adj.signif"). Les trois étapes ne changent jamais.

stat_compare_means() calcule et dessine le test en une seule couche — rapide pour une p-value globale ou par paire rapide. stat_pvalue_manual() dessine des p-values que vous avez calculées séparément (avec rstatix), ce qu’il faut pour des p-values ajustées, des tests spécifiques, ou des dispositions groupées / en facettes / horizontales. Voir la leçon compagne Add p-values to ggplots pour stat_compare_means().

Ajoutez adjust_pvalue(method = "holm") (ou "bonferroni", "BH", …) après le test, puis add_significance("p.adj") pour les étoiles. Étiquetez le graphique avec label = "p.adj" pour le nombre ou label = "p.adj.signif" pour le symbole de signification.

add_xy_position() doit correspondre à la géométrie du graphique. Pour les graphiques groupés/juxtaposés, passez le même dodge (par ex. dodge = 0.8) ; pour les diagrammes en barres/courbes, passez le fun correspondant (fun = "mean_sd") ; pour les facettes à échelle libre, passez scales = "free" à la fois dans add_xy_position() et dans la facette. Des arguments mal accordés sont la cause habituelle des crochets flottants.

Ajoutez coord_flip() pour rendre le graphique horizontal et passez coord.flip = TRUE à stat_pvalue_manual() pour que les crochets basculent avec lui. Vous pouvez redresser les étiquettes à la verticale avec angle = 90 et les décaler avec hjust / vjust.

Remodelez les données du format large au format long pour que les réponses s’empilent dans une seule colonne value indexée par une colonne variables (stack() de base R fonctionne), puis group_by(variables) %>% t_test(value ~ group), adjust_pvalue() et add_xy_position(scales = "free"). Dessinez un graphique facet_wrap(~variables, scales = "free") avec stat_pvalue_manual() — chaque panneau montre la comparaison d’une réponse. Voyez la section Variables réponses multiples ci-dessus.

Testez vos connaissances

Complétez le code pour que le test soit calculé au sein de chaque dose (OJ vs VC), que les p-values soient ajustées par Bonferroni, que les crochets soient positionnés pour un graphique juxtaposé, et que les étoiles ajustées soient dessinées.

# 1. Adjust the p-values:        adjust_pvalue(method = "bonferroni")
# 2. Match the plot's dodge:     dodge = 0.8
# 3. Label with the adj. stars:  p.adj.signif
library(ggpubr) library(rstatix) df <- ToothGrowth df$dose <- factor(df$dose) stat.test <- df %>% group_by(dose) %>% t_test(len ~ supp) %>% adjust_pvalue(method = "bonferroni") %>% add_significance("p.adj") stat.test <- stat.test %>% add_xy_position(x = "dose", dodge = 0.8) ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_pvalue_manual(stat.test, label = "p.adj.signif")
library(ggpubr)
library(rstatix)
df <- ToothGrowth
df$dose <- factor(df$dose)

stat.test <- df %>%
  group_by(dose) %>%
  t_test(len ~ supp) %>%
  adjust_pvalue(method = "bonferroni") %>%
  add_significance("p.adj")

stat.test <- stat.test %>% add_xy_position(x = "dose", dodge = 0.8)

ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") +
  stat_pvalue_manual(stat.test, label = "p.adj.signif")

Vérification rapide. Vous ajoutez scales = "free" à facet_wrap() mais les crochets restent mal positionnés. Qu’avez-vous oublié ? (Réponse : passez scales = "free" à add_xy_position() aussi — les positions y doivent être recalculées pour les échelles libres, pas seulement le graphique.)

Conclusion

Vous avez appris le flux de travail rstatix → ggpubr pour poser des p-values issues de vrais tests statistiques sur n’importe quel ggplot : calculer avec t_test() / wilcox_test() / anova_test() (+ adjust_pvalue() pour la multiplicité), positionner avec add_xy_position(), et dessiner avec stat_pvalue_manual() — à travers les dispositions de base, groupées, en facettes, à échelle libre et horizontales, plus geom_bracket() pour les annotations personnalisées ponctuelles. Les trois étapes ne changent jamais ; seuls les arguments de add_xy_position() s’adaptent au graphique.

Pour une annotation plus rapide, en une seule couche et sans ajustement, commencez par stat_compare_means(). Pour le raccourci moderne qui calcule et positionne en un seul appel, voir Auto p-values with geom_pwc(). Pour choisir et interpréter les tests eux-mêmes (hypothèses, taille d’effet), voir la prochaine série statistiques.

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 de tests statistiques sur ggplot en R (rstatix)},
  date = {2026-06-22},
  url = {https://www.datanovia.com/learn/data-visualization/ggpubr/p-values-from-tests},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“P-values de tests statistiques sur ggplot en R (rstatix).” 2026. June 22. https://www.datanovia.com/learn/data-visualization/ggpubr/p-values-from-tests.