Organisation et mise en page de figures à panneaux multiples

Le chapitre Facets (sous-graphiques) a montré comment une variable catégorielle peut servir à créer plusieurs sous-graphiques (facets) présentant des sous-groupes de données. On utilise pour cela des fonctions de ggplot2 (facet_wrap() et facet_grid()). Ces fonctions ne permettent toutefois pas de placer des graphiques distincts côte à côte. Il faut pour cela des extensions de ggplot2. Les deux packages les plus populaires sont gridExtra et cowplot. Seul cowplot est présenté ici, car il offre toutes les fonctionnalités nécessaires, y compris pour les utilisateurs les plus avancés. Cowplot possède une syntaxe intuitive et produit des mises en page homogènes et bien organisées, avec une très grande flexibilité.

Commencez par installer et charger cowplot. Chargez également tidyverse, qui contient entre autres ggplot2, ainsi que gapminder, qui contient les données d'exercice.

install.packages("cowplot")

library(cowplot)
library(tidyverse)
library(gapminder)

## Inspecter les 5 premières lignes de gapminder
head(gapminder)
country<fctr> continent<fctr> year<int> lifeExp<dbl> pop<int> gdpPercap<dbl>
Afghanistan Asia 1952 28.801 8425333 779.4453
Afghanistan Asia 1957 30.332 9240934 820.8530
Afghanistan Asia 1962 31.997 10267083 853.1007
Afghanistan Asia 1967 34.020 11537966 836.1971
Afghanistan Asia 1972 36.088 13079460 739.9811
Afghanistan Asia 1977 38.438 14880372 786.1134

Les 5 premières lignes de gapminder.

Pour organiser plusieurs graphiques dans une même mise en page, chaque graphique doit être enregistré sous forme d'objet. Dans ce chapitre, les objets seront nommés plot_1, plot_2, plot_3 et plot_4. Les différences entre ces graphiques seront minimes, mais cela n'a aucune importance pour montrer comment organiser des graphiques.

Nous commençons par créer plot_1, plot_2, plot_3 et plot_4 à partir des données gapminder. Les graphiques ci-dessous ne diffèrent que par ce qui figure sur l'axe des x, sur l'axe des y et par la palette de couleurs.

## Premier graphique
plot_1 <- ggplot(gapminder, aes(x=log(pop),
                                y=log(lifeExp),
                                color=year)) +
  geom_point() +
  scale_color_viridis_c(option = "plasma") +
  theme(legend.position = "none")

## Deuxième graphique
plot_2 <- ggplot(gapminder, aes(x=log(pop),
                                y=continent,
                                color=year)) +
  geom_point(size=3, alpha=.5) +
  scale_color_viridis_c(option = "magma") +
  theme(legend.position = "none")

## Troisième graphique
plot_3 <- ggplot(gapminder, aes(x=log(gdpPercap),
                                y=continent,
                                color=year)) +
  geom_point(size=3, alpha=.5) +
  scale_color_viridis_c(option = "plasma") +
  theme(legend.position = "none")

## Quatrième graphique
plot_4 <- ggplot(gapminder, aes(x=gdpPercap,
                                y=continent,
                                color=year)) +
  geom_point(size=3, alpha=.5) +
  scale_color_viridis_c(option = "magma") +
  theme(legend.position = "none")

Nous utilisons maintenant plot_grid() de cowplot pour réunir plot_1 et plot_2 dans une figure à 2 colonnes (ncol). Nous créons également des labels, comme illustré ci-dessous.

plot_grid(plot_1, plot_2, ncol = 2, labels = c('A', 'B'))
Deux nuages de points côte à côte, A : log(lifeExp) en fonction de log(pop) et B : continent en fonction de log(pop), colorés selon l'année

Les figures peuvent être disposées verticalement en remplaçant ncol par ncol=1. Ci-dessous, nous utilisons labels="AUTO" afin d'obtenir les étiquettes automatiquement.

plot_grid(plot_1, plot_2, ncol = 1, labels = "AUTO")
Les deux mêmes nuages de points empilés verticalement avec les étiquettes A et B, log(lifeExp) et continent respectivement en fonction de log(pop)

On peut également utiliser align="h" pour un alignement horizontal des figures, ou align="v" pour un alignement vertical.

plot_grid(plot_1, plot_2, aligh = "h")
Deux nuages de points côte à côte, A : log(lifeExp) en fonction de log(pop) et B : continent en fonction de log(pop), colorés selon l'année

L'argument rel_widths() permet de régler la part de l'espace occupée par chaque graphique. Ci-dessous, le premier graphique reçoit moitié moins d'espace (1) que le second (2).

plot_grid(plot_1, plot_2, ncol=2, rel_widths = c(1, 2))
Deux nuages de points côte à côte, le panneau de droite, continent en fonction de log(pop), étant deux fois plus large que celui de gauche

Remarquez, dans le graphique ci-dessous, que le titre de l'axe des y de la figure supérieure est plus éloigné des valeurs de l'axe.

plot_grid(plot_1, plot_2, ncol = 1, align = 'v')
Deux nuages de points empilés verticalement, le titre log(lifeExp) de l'axe des y supérieur étant plus éloigné de l'axe que celui du graphique inférieur

Lorsque les titres et les axes des figures d'un plot_grid() ne sont pas alignés, on utilise l'argument axis pour corriger cela. Axis accepte les valeurs none, l (left, gauche), r (right, droite), b (bottom, bas) et t (top, haut). Vous pouvez en utiliser une ou plusieurs pour aligner le côté correspondant. Ci-dessous, nous alignons les graphiques à gauche avec axis="l".

plot_grid(plot_1, plot_2, ncol = 1, align = 'v', axis = 'l')
Deux nuages de points empilés verticalement et alignés à gauche de sorte que les axes des y de log(lifeExp) et de continent soient alignés

Vous pouvez créer des emplacements de figure vides avec l'argument NULL dans plot_grid(). Ci-dessous, nous créons une matrice de quatre figures dont deux sont NULL, et nous ajoutons les étiquettes automatiquement.

plot_grid(
  plot_1, NULL, NULL, plot_2,
  labels = "AUTO",
  ncol = 2
)
Grille deux sur deux avec des nuages de points dans les cases A et D et des cases vides B et C

Vous pouvez créer des matrices de figures sur plusieurs lignes, avec des tailles variables pour ces lignes. Pour ce faire, on crée plusieurs plot_grid() qui servent ensuite d'objets dans un plot_grid() final.

## Première ligne avec plot_grid()
upper_row <- plot_grid(plot_1, plot_2, ncol = 2, labels=c("A", "B"))

## Deuxième ligne avec plot_grid()
middle_row <- plot_grid(plot_3, labels=c("C"))

## Troisième ligne avec plot_grid()
bottom_row <- plot_grid(plot_4, plot_1, ncol = 2, labels=c("D", "E"))

## plot_grid() final
plot_grid(upper_row, middle_row, bottom_row, ncol=1)
Mise en page sur trois lignes avec cinq panneaux de A à E : deux graphiques en haut, un large au milieu et deux en bas, données de gapminder

Titre commun pour plusieurs panneaux

Avec plot_grid(), on peut attribuer une étiquette (label) à chaque panneau, et chaque panneau peut lui-même avoir un titre créé avec ggplot(). Il peut cependant être souhaitable d'avoir un titre qui s'étend sur plusieurs panneaux. On y parvient avec ggdraw(), de la manière suivante :

plot_title <- ggdraw() +
  draw_label(
    "Här skriver vi en titel för samtliga paneler på en gång",
    fontface = 'bold',
    x = 0,
    hjust = 0) +
  # Ajoute une marge de 7 pixels à gauche, pour que le titre soit aligné sur le premier panneau
  theme(plot.margin = margin(0, 0, 0, 7))

plot_row <- plot_grid(plot_1, plot_2, labels="AUTO")

plot_grid(
  plot_title,
  plot_row,
  ncol = 1,
  rel_heights = c(0.1, 1) # le titre reçoit une faible part de la hauteur
)
Deux nuages de points A et B sous un titre commun en gras qui s'étend sur les deux panneaux

Superposer des figures

Il peut être utile de superposer des figures pour mettre plus clairement en évidence des relations. C'est intéressant lorsque les figures partagent un axe (le plus souvent l'axe des x). Si deux figures ont le même axe des x mais des axes des y différents, on peut les superposer afin de visualiser la relation entre l'axe des x et les deux axes des y. Cela donne parfois des illustrations plus lisibles, même si le gain (par rapport à deux figures distinctes placées côte à côte) est en réalité assez faible.

Pour cet exercice, nous utilisons les données mpg (miles per gallon), qui contiennent des données de consommation de carburant (variables cty et hwy) pour différentes voitures. Ces données sont fournies avec tidyverse, ce qui signifie qu'elles devraient déjà être disponibles (sinon, chargez tidyverse avec la commande library(tidyverse)). Commencez par examiner les données :

head(mpg)
manufacturer <chr> model <chr> displ <dbl> year <int> cyl <int> trans <chr> drv <chr> cty <int> hwy <int> fl <chr>
audi a4 1.8 1999 4 auto(l5) f 18 29 p
audi a4 1.8 1999 4 manual(m5) f 21 29 p
audi a4 2.0 2008 4 manual(m6) f 20 31 p
audi a4 2.0 2008 4 auto(av) f 21 30 p
audi a4 2.8 1999 6 auto(l5) f 16 26 p
audi a4 2.8 1999 6 manual(m5) f 18 26 p

Nous créons la première figure (voir les commentaires pour les explications) de la manière suivante :

plot_1 <- ggplot(mpg, aes(x=manufacturer,
                          y=hwy)) +
  geom_boxplot() +
  # Le thème "half open" n'a pas de quadrillage et seulement deux lignes (axe des x et axe des y)
  theme_half_open() +
  theme(
    # Fait pivoter les étiquettes de l'axe des x de 45°
    axis.text.x = element_text(angle = 45, hjust = 1, vjust= 1),
    # Supprime le titre de l'axe des x
    axis.title.x = element_blank())

plot_1
Boîtes à moustaches de hwy par constructeur automobile, avec les noms des constructeurs inclinés sur l'axe des x, sans quadrillage

Remarquez que la figure n'a pas de lignes sur le côté droit ni en haut. Passons à la deuxième figure :

plot_2 <- ggplot(mpg, aes(x=manufacturer,
                          y=cty,
                          color=drv)) +
  geom_point(size=3) +
  # Déplace l'axe des y sur le côté droit
  scale_y_continuous(position = "right") +
  # Même thème que ci-dessus
  theme_half_open() +
  # Supprime le titre et les étiquettes de l'axe des x
  theme(axis.text.x = element_blank(),
        axis.title.x = element_blank()) +
  # Utilise une belle palette de couleurs pour color=drv
  scale_color_viridis_d()

plot_2
Nuage de points de cty par constructeur coloré selon drv, avec l'axe des y à droite et sans texte sur l'axe des x

Enfin, ces deux graphiques doivent être superposés. On utilise pour cela align_plots() et ggdraw(), comme suit :

## Placer les graphiques l'un au-dessus de l'autre
aligned_plots <- align_plots(plot_1, plot_2, align="hv", axis="tblr")

## Afficher le graphique final
ggdraw(aligned_plots[[1]]) + draw_plot(aligned_plots[[2]])
Boîtes à moustaches de hwy et nuage de points de cty par constructeur automobile superposés, avec l'axe hwy à gauche et l'axe cty à droite