Combiner plusieurs ggplots avec ggarrange (ggpubr)
Assemblez des graphiques en grille, étiquetez les panneaux, partagez une seule légende et exportez — le tout avec ggarrange()
Combinez plusieurs ggplots indépendants en une seule figure prête à publier dans R avec la fonction ggarrange() de ggpubr : disposez les graphiques en grille avec ncol/nrow, étiquetez les panneaux A/B/C, rassemblez une seule légende partagée, construisez des étendues inégales avec des appels imbriqués, ajoutez des graphiques de densité marginaux avec ggscatterhist(), annotez la figure entière, mêlez un tableau et du texte, et exportez-la dans un fichier.
Date de publication
12 juillet 2026
Modifié
12 juillet 2026
AstucePoints clés
ggarrange() [ggpubr] combine des ggplots indépendants en une seule figure — passez les graphiques ainsi que ncol / nrow pour une grille.
Étiquetez les panneaux avec labels = c("A", "B", "C") — les repères qu’un relecteur attend sur une figure multi-panneaux.
Une seule légende partagée pour toute la figure : common.legend = TRUE, legend = "bottom".
Des étendues inégales proviennent d’appels ggarrange()imbriqués plus widths / heights ; align = "v" aligne les panneaux.
Des graphiques de densité marginaux sur un nuage de points en un seul appel — ggscatterhist().
annotate_figure() ajoute un titre/une légende de figure ; ggexport() (ou ggsave()) l’écrit dans un fichier.
Vous avez trois ou quatre graphiques terminés — une boîte à moustaches, un nuage de points, un tableau récapitulatif — et une revue les veut sous forme d’une seule figure, panneaux A/B/C, une légende unique. Les fonctions par(mfrow=) et layout() de R base ne fonctionnent pas sur les ggplots, il vous faut donc un outil qui parle ggplot.
Le package ggpubr du fondateur vous en offre un : ggarrange(). Il organise n’importe quel ensemble de ggplots en une grille, étiquette les panneaux, rassemble une légende partagée et — contrairement aux alternatives — pagine une longue liste de graphiques et exporte directement dans un fichier, le tout depuis un seul appel.
Deux distinctions rapides avant de commencer, pour que vous choisissiez le bon outil :
Le même graphique découpé par un groupe ? C’est du facettage, intégré à ggplot2 — voir facettes. N’organisez pas les facettes à la main.
Des graphiques indépendants en une seule figure ? C’est de l’organisation, et cette leçon couvre la manière ggpubr. La grammaire de ggplot2 a son propre outil basé sur des opérateurs, patchwork — le même travail, un idiome différent ; utilisez celui qui convient à votre flux de travail.
Chaque figure ci-dessous est rendue ici même à partir du code affiché, et vous pouvez réexécuter ou modifier n’importe lequel de ces exemples en direct à la fin.
Les graphiques que nous allons combiner
Nous construisons de petits graphiques à partir de trois jeux de données intégrés — ToothGrowth (longueur des dents selon la dose de vitamine C), mtcars (poids et consommation des voitures) et iris (mesures de fleurs) — à l’aide des fonctions de tracé de ggpubr (ggboxplot(), ggdotplot(), ggscatter()). Chacune prend un data frame plus des noms de colonnes sous forme de chaînes et renvoie un véritable objet ggplot que vous pouvez stocker dans une variable et combiner plus tard.
Comme chaque bloc de code de cette page est autonome (afin que vous puissiez le copier ou l’exécuter dans n’importe quel ordre), nous reconstruisons la poignée de graphiques dont nous avons besoin à l’intérieur de chaque bloc. Dans votre propre script, vous les construiriez une seule fois.
Organiser des graphiques sur une seule page
Stockez chaque graphique dans une variable, puis passez-les à ggarrange() avec la forme de la grille (ncol, nrow) et les labels des panneaux. Voici la figure que la plupart des gens recherchent — trois graphiques dans une grille 2×2, étiquetés A, B, C.
library(ggpubr)ToothGrowth$dose <-factor(ToothGrowth$dose)# Build three independent ggpubr plotsbxp <-ggboxplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco")dp <-ggdotplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco",binwidth =1)sp <-ggscatter(mtcars, x ="wt", y ="mpg", color ="#3a86d4", add ="reg.line")# Combine them into one figureggarrange(bxp, dp, sp,labels =c("A", "B", "C"),ncol =2, nrow =2)
Les trois arguments que vous utiliserez à chaque fois : ncol / nrow définissent la grille ; labels étiquette les panneaux ("AUTO" génère automatiquement A, B, C…) ; les graphiques remplissent la grille ligne par ligne par défaut (fixez byrow = FALSE pour remplir par colonne).
Partager une seule légende sur toute la figure
Lorsque plusieurs panneaux portent la même légende, la répéter gaspille de l’espace. Fixez common.legend = TRUE et placez-la une seule fois avec legend ("top", "bottom", "left" ou "right").
library(ggpubr)ToothGrowth$dose <-factor(ToothGrowth$dose)bxp <-ggboxplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco")dp <-ggdotplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco",binwidth =1)ggarrange(bxp, dp,labels =c("A", "B"),common.legend =TRUE, legend ="bottom")
Pour que cela fonctionne, les panneaux doivent partager la même légende (même variable, même échelle). ggarrange() prend la légende du premier graphique, supprime les autres et la dessine une seule fois dans la marge.
Étendues inégales et dispositions imbriquées
Toutes les figures ne sont pas des grilles bien nettes. Pour qu’un graphique occupe toute une ligne pendant que deux autres se partagent la ligne en dessous, imbriquez un ggarrange() dans un autre. L’appel interne devient une seule cellule de l’appel externe.
library(ggpubr)ToothGrowth$dose <-factor(ToothGrowth$dose)bxp <-ggboxplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco")dp <-ggdotplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco",binwidth =1)sp <-ggscatter(mtcars, x ="wt", y ="mpg", color ="#3a86d4", add ="reg.line")ggarrange( sp, # top row: one wide plotggarrange(bxp, dp, ncol =2, labels =c("B", "C")), # bottom row: two panelsnrow =2,labels ="A"# label for the top plot)
Deux arguments affinent les tailles et l’alignement :
widths / heights — tailles relatives des colonnes / lignes, par ex. heights = c(2, 1) rend la ligne du haut deux fois plus haute que celle du bas.
align — "v" aligne les panneaux verticalement, "h" horizontalement, "hv" les deux. Utilisez-le chaque fois que des panneaux empilés ont des étiquettes d’axe de largeurs différentes et que leurs zones de tracé se désalignent (une courbe de survie au-dessus de sa table des risques en est le cas classique).
Nuage de points avec graphiques de densité marginaux
Un nuage de points avec une courbe de densité sur chaque axe est un classique de la data-viz — et dans ggpubr, c’est un seul appel, ggscatterhist(), et non une grille à quatre cellules construite à la main. Pointez-le vers vos colonnes x/y et une color de groupement ; margin.plot choisit le type marginal.
library(ggpubr)ggscatterhist( iris, x ="Sepal.Length", y ="Sepal.Width",color ="Species", palette ="jco",margin.plot ="density",margin.params =list(fill ="Species", color ="black", size =0.2))
Remplacez margin.plot = "density" par "boxplot" ou "histogram" pour changer les panneaux marginaux ; retirez l’argument color/group pour un nuage de points à une seule série. ggscatterhist() affiche la figure assemblée directement, c’est donc la voie la plus rapide vers cette disposition.
Annoter la figure entière
Une fois les panneaux organisés, annotate_figure() ajoute du texte autour de la figure combinée — un titre général, une légende indiquant la source des données, des étiquettes latérales sur les axes, ou un numéro de figure.
library(ggpubr)ToothGrowth$dose <-factor(ToothGrowth$dose)sp <-ggscatter(mtcars, x ="wt", y ="mpg", color ="#3a86d4", add ="reg.line")bxp <-ggboxplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco")figure <-ggarrange(sp, bxp, ncol =1, nrow =2)annotate_figure( figure,top =text_grob("Two views of the data", face ="bold", size =14),bottom =text_grob("Data source: mtcars and ToothGrowth", face ="italic", size =10),fig.lab ="Figure 1", fig.lab.face ="bold")
text_grob() stylise chaque élément de texte (color, face, size, rot pour pivoter une étiquette latérale). annotate_figure() fonctionne sur la sortie de n’importe quelle fonction d’organisation, vous pouvez donc étiqueter une figure quelle que soit la manière dont elle a été assemblée.
Mêler un tableau et du texte aux graphiques
Une figure de résultats a souvent besoin de plus que des graphiques — un petit tableau récapitulatif et une légende ont leur place sur la même page. ggpubr transforme chacun en un ggplot pour que ggarrange() puisse les empiler : ggtexttable() dessine un data frame sous forme de tableau, ggparagraph() dessine un bloc de texte, et desc_statby() calcule le récapitulatif par groupe.
library(ggpubr)# 1. A density plotdensity.p <-ggdensity(iris, x ="Sepal.Length", fill ="Species", palette ="jco")# 2. A summary table (mean, sd, n by species) drawn as a plotstable <-desc_statby(iris, measure.var ="Sepal.Length", grps ="Species")stable <- stable[, c("Species", "length", "mean", "sd")]stable.p <-ggtexttable(stable, rows =NULL, theme =ttheme("mBlue"))# 3. A text paragraphtext.p <-ggparagraph(paste("The iris data set records sepal and petal length and width for 50 flowers","from each of three iris species: setosa, versicolor and virginica."),face ="italic", size =11)# Stack the three, giving the plot the most roomggarrange(density.p, stable.p, text.p,ncol =1, nrow =3,heights =c(1, 0.5, 0.4))
ttheme() stylise le tableau — "mBlue", "mOrange", "light" et d’autres définissent le jeu de couleurs. Voir la leçon dédiée aux tableaux de texte pour un contrôle complet du style des cellules et des en-têtes.
Exporter la figure dans un fichier
ggarrange() renvoie un ggplot, donc ggsave() fonctionne directement. ggpubr fournit aussi ggexport(), qui pagine en plus une liste de graphiques et écrit du PDF/PNG/EPS. Ces fonctions écrivent sur le disque, exécutez-les donc dans votre propre session :
library(ggpubr)ToothGrowth$dose <-factor(ToothGrowth$dose)bxp <-ggboxplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco")figure <-ggarrange(bxp, bxp, ncol =2)# ggpubr's exporter — PDF, PNG or EPSggexport(figure, filename ="figure.pdf", width =8, height =4)# ...or ggplot2's ggsave, since ggarrange returns a ggplotggsave("figure.png", figure, width =8, height =4, dpi =300)
De nombreux graphiques répartis sur plusieurs pages. Donnez à ggarrange() une longue liste plus ncol/nrow ; il calcule combien de pages il lui faut et renvoie une figure organisée par page, que ggexport() écrit sous forme de PDF multi-pages :
# 4 plots, 2 per page -> a 2-page PDFmulti.page <-ggarrange(bxp, bxp, bxp, bxp, ncol =2, nrow =1)ggexport(multi.page, filename ="plots.pdf")
D’autres packages que vous croiserez.ggarrange() est une surcouche de plot_grid() de cowplot ; le grid.arrange() de gridExtra et le plot_grid() de cowplot font aussi la grille de base. ggarrange ajoute la légende partagée, les étendues imbriquées, l’export multi-pages et annotate_figure() dans une seule interface cohérente, c’est pourquoi nous l’enseignons comme choix par défaut ici.
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 (aucun serveur, aucune installation). Essayez de changer ncol/nrow, de déplacer la legend, ou de désactiver common.legend.
🟢 Avec un agent IA
Demandez à Prova« j’ai organisé quatre ggplots avec ggarrange() mais les panneaux ne s’alignent pas — comment utiliser align et heights pour corriger cela ? » — elle répond avec du code que vous pouvez exécuter sur vos propres graphiques et vérifie les arguments align/widths/heights par rapport à votre disposition, de sorte que la correction soit reproductible. The runtime is the judge.Demander à Prova →
Problèmes fréquents
La légende partagée ne se regroupe pas.common.legend = TRUE ne fusionne que les légendes qui sont vraiment les mêmes (même attribut esthétique, même variable, même échelle). Si les panneaux associent des variables différentes à la couleur, ils ont légitimement besoin de légendes distinctes — donnez-en une à chaque graphique, ou harmonisez d’abord les échelles.
Des panneaux empilés sont mal alignés. Des étiquettes d’axe y de largeurs différentes décalent les zones de tracé. Ajoutez align = "v" (ou "hv") à ggarrange() pour qu’il aligne les panneaux, et pas seulement les cadres extérieurs.
ggexport() / ggsave() génère une erreur lors du rendu d’un document. Elles écrivent un fichier sur le disque — exécutez-les de manière interactive, pas au sein d’un build sans chemin accessible en écriture. Dans un rapport, enregistrez une fois et relisez l’image.
Les étiquettes de panneau chevauchent le graphique. Déplacez-les avec label.x / label.y (0–1 dans chaque panneau) ou restylisez-les avec font.label = list(size = 14, face = "bold").
Questions fréquentes
NoteComment combiner plusieurs ggplots en une seule figure dans R ?
Stockez chaque graphique dans une variable, puis passez-les à ggarrange() [ggpubr] avec la forme de la grille : ggarrange(p1, p2, p3, ncol = 2, nrow = 2). Ajoutez labels = c("A", "B", "C") pour étiqueter les panneaux. C’est la propre fonction du fondateur et elle gère aussi les légendes partagées, les étendues imbriquées et l’export.
NoteQuelle est la différence entre ggarrange() et facet_wrap() ?
Utilisez le facettage (facet_wrap() / facet_grid()) quand un seul jeu de données est découpé en panneaux par une variable de groupement — même type de graphique, échelles partagées. Utilisez ggarrange() pour combiner des graphiques indépendants (un nuage de points à côté d’une boîte à moustaches à côté d’un tableau). Voir facettes pour la voie du facettage.
NoteComment ajouter une seule légende commune à des ggplots combinés ?
Passez common.legend = TRUE et fixez sa position avec legend, par ex. ggarrange(p1, p2, common.legend = TRUE, legend = "bottom"). Les panneaux doivent partager la même légende (même variable et même échelle) ; ggarrange() la dessine alors une seule fois dans la marge.
NoteComment faire qu’un graphique occupe deux colonnes avec ggarrange() ?
Imbriquez des appels ggarrange() : placez le graphique large dans l’appel externe et un ggarrange() interne (contenant la ligne de graphiques plus petits) comme cellule suivante — ggarrange(wide, ggarrange(p2, p3, ncol = 2), nrow = 2). Utilisez widths / heights pour définir les tailles relatives.
NoteComment ajouter un titre ou une légende à une figure ggpubr combinée ?
Enveloppez la figure organisée dans annotate_figure() : annotate_figure(figure, top = text_grob("My title", face = "bold"), bottom = text_grob("Data source", face = "italic")). text_grob() stylise chaque élément de texte et peut pivoter les étiquettes latérales avec rot = 90.
NoteComment enregistrer une figure ggarrange organisée dans un fichier ?
ggarrange() renvoie un ggplot, donc ggsave("figure.png", figure, width = 8, height = 4) fonctionne. ggpubr fournit aussi ggexport(figure, filename = "figure.pdf"), qui pagine en plus une longue liste de graphiques en un PDF multi-pages.
Testez vos connaissances
ImportantExercice : une grille 2×2 étiquetée avec une seule légende partagée
Complétez le code pour que la boîte à moustaches et le graphique de points soient disposés côte à côte, étiquetés A et B, et partagent une seule légende le long du bas.
# 1. Tag the panels: labels = c("A", "B")# 2. Merge the legends: common.legend = TRUE
library(ggpubr)
ToothGrowth$dose <- factor(ToothGrowth$dose)
bxp <- ggboxplot(ToothGrowth, x = "dose", y = "len", color = "dose", palette = "jco")
dp <- ggdotplot(ToothGrowth, x = "dose", y = "len", color = "dose", palette = "jco",
binwidth = 1)
ggarrange(bxp, dp,
labels = c("A", "B"),
common.legend = TRUE, legend = "bottom",
ncol = 2, nrow = 1)
library(ggpubr)ToothGrowth$dose <-factor(ToothGrowth$dose)bxp <-ggboxplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco")dp <-ggdotplot(ToothGrowth, x ="dose", y ="len", color ="dose", palette ="jco",binwidth =1)ggarrange(bxp, dp,labels =c("A", "B"),common.legend =TRUE, legend ="bottom",ncol =2, nrow =1)
Vérification rapide. Vous empilez un graphique au-dessus de son tableau récapitulatif avec ggarrange(p, table, ncol = 1), mais le tableau est aussi haut que le graphique. Quel argument corrige les tailles relatives ?
AstuceAfficher la réponse
heights — passez heights = c(2, 1) (ou similaire) à ggarrange() pour que le graphique obtienne deux fois l’espace du tableau. widths fait de même pour les colonnes.
Conclusion
Vous avez combiné des ggplots indépendants en une seule figure prête à publier avec ggarrange() — organisés en grille avec ncol/nrow, étiqueté les panneaux, rassemblé une seule légende partagée, construit des étendues inégales avec des appels imbriqués, ajouté des graphiques de densité marginaux avec ggscatterhist(), annoté la figure entière avec annotate_figure(), mêlé un tableau et du texte, et exportée avec ggexport() / ggsave(). Le schéma est toujours le même : construisez chaque graphique comme un objet, puis passez les objets à ggarrange().
Pour la manière d’assembler des graphiques avec des opérateurs selon la grammaire de ggplot2, voir combiner les graphiques avec patchwork ; pour des panneaux d’un seul jeu de données, utilisez le facettage.
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.