3.1 Philosophie du ggplot2
Le package ggplot2
fait partie du tidyverse
et dispose d’une logique de fonctionnement particulière. Cette dernière se nomme The Grammar of Graphics (les deux G sont d’ailleurs à l’origine du nom ggplot2
), proposée par Hadley Wickham (le créateur du tidyverse
!) dans un article intitulé A layered grammar of graphics (Wickham 2010). Nous proposons de synthétiser ici les concepts et principes centraux qui sous-tendent la production de graphiques avec ggplot2
.
3.1.1 Grammaire
Hadley Wickham propose une grammaire pour unifier la création de graphiques. L’idée est donc de dépasser les simples dénominations comme un nuage de points, un diagramme en boîte, un graphique en ligne, etc., pour comprendre ce qui relie tous ces graphiques. Ces éléments communs et centraux sont les géométries, les échelles et systèmes de coordonnées, et les annotations (figure 3.1) :

Figure 3.1: Trois composantes d’un graphique, adapté de Wickham (2010)
- Les géométries sont les formes utilisées pour représenter les données. Il peut s’agir de points, de lignes, de cercles, de rectangles, d’arcs de cercle, etc.
- Les échelles et systèmes de coordonnées permettent de contrôler la localisation des éléments dans un graphique en convertissant les données depuis leur échelle originale (dollars, kilomètres, pourcentages, etc.) vers l’échelle du graphique (pixels).
- Les annotations recoupent l’ensemble des informations complémentaires ajoutées au graphique comme son titre et sous-titre, la source des données, la mention sur les droits d’auteurs, etc.
En plus de ces trois éléments, il est bien sûr nécessaire de disposer de données. Ces dernières sont assignées à des dimensions du graphique pour être représentées (notamment les axes X et Y et la couleur). Cette étape est appelée aesthetics mapping dans ggplot2
.
Lorsque nous combinons des données, leur assignation a des dimensions, un type de géométries, des échelles et un système de coordonnées, nous obtenons un calque (layer en anglais). Un graphique peut comprendre plusieurs calques comme nous le verrons dans les prochaines sections.
Prenons un premier exemple très simple et construisons un nuage de points à partir du jeu de données iris fourni de base dans R. Nous représentons la relation qui existe entre la longueur et la largeur des sépales de ces fleurs. Pour commencer, nous devons charger le package ggplot2
et instancier un graphique avec la fonction ggplot
.
## [1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Species"

Figure 3.2: Base d’un graphique
Pour le moment, le graphique est vide (figure 3.2). La seconde étape consiste à lui ajouter des données (au travers du paramètre data
) et à définir les dimensions à associer aux données (avec le paramètre mapping
et la fonction aes()
). Dans notre cas, nous voulons utiliser les coordonnées X pour représenter la largeur des sépales, et les coordonnées Y pour représenter la longueur des sépales. Enfin, nous souhaitons représenter les observations par des points, nous utiliserons donc la géométrie geom_point
.

Figure 3.3: Ajout des dimensions au graphique
Ce graphique ne comprend qu’un seul calque avec une géométrie de type point (figure 3.3). Chaque calque est ajouté avec l’opérateur +
qui permet de superposer des calques, le dernier apparaissant au-dessus des autres. Les arguments mapping
et data
sont définis ici dans la fonction ggplot
et sont donc appliqués à tous les calques qui composent le graphique. Il est aussi possible de définir mapping
et data
au sein des fonctions des géométries :

Figure 3.4: Autre spécification des arguments mapping et data
La troisième étape consiste à ajouter au graphique des annotations. Pour notre cas, il faudrait ajouter un titre, un sous-titre et des intitulés plus clairs pour les axes X et Y, ce qu’il est possible de faire avec la fonction labs
(figure 3.5).
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales")

Figure 3.5: Ajout de titres
3.1.2 Types de géométries
Le package ggplot2
permet d’utiliser un très grand nombre de géométries différentes. Dans le tableau 3.1, nous avons reporté les principales géométries disponibles afin que vous puissiez vous faire une idée du « bestiaire » existant. Il ne s’agit que d’un extrait des principales fonctions. Sachez qu’il existe aussi des packages proposant des géométries supplémentaires pour compléter ggplot2
.
Géométrie | Fonction |
---|---|
point |
geom_point
|
ligne |
geom_line
|
chemin |
geom_path
|
boîte à moustaches |
geom_boxplot
|
diagramme violon |
geom_violin
|
histogramme |
geom_histogram
|
barre |
geom_bar
|
densité |
geom_density
|
texte |
geom_label
|
barre d’erreur |
geom_errorbar
|
surface |
geom_ribbon
|
3.1.3 Habillage
Dans le premier exemple, nous avons montré comment ajouter le titre, le sous-titre et les titres des axes sur un graphique. Il est aussi possible d’ajouter du texte sous le graphique (généralement la source des données avec l’argument caption
) et des annotations textuelles (annotate
). Pour ces dernières, il convient de spécifier leur localisation (coordonnées x
et y
) et le texte à intégrer (label
); elles sont ensuite ajoutées au graphique avec l’opérateur +
. Ajoutons deux annotations pour identifier deux fleurs spécifiques.
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
annotate("text", x = 6.7, y = 2.5, # position de la note
label = "une virginica", # texte de la note
hjust = "left", vjust = "top", # ajustement
size = 3, fontface = "italic") +
annotate("text", x = 5.7, y = 4.4, # position de la note
label = "une setosa", # texte de la note
hjust = "left", vjust = "top", # ajustement
size = 3, fontface = "italic")

Figure 3.6: Ajout d’annotations textuelles
Comme vous pouvez le constater, de nombreux paramètres permettent de contrôler le style des annotations. Pour avoir la liste des arguments disponibles, n’hésitez pas à afficher l’aide de la fonction : help(annotate)
.
En plus des annotations de type texte, il est possible d’ajouter des annotations de type géométrique. Nous pourrions ainsi délimiter une boîte encadrant les fleurs de l’espère setosa.
setosas <- subset(iris, iris$Species == "setosa")
sepal.length_extent <- c(min(setosas$Sepal.Length),max(setosas$Sepal.Length))
sepal.width_extent <- c(min(setosas$Sepal.Width),max(setosas$Sepal.Width))
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
annotate("text", x = 6.7, y = 2.5, # position de la note
label = "une virginica", # texte de la note
hjust = "left", vjust = "top", # ajustement
size = 3, fontface = "italic") +
annotate("text", x = 5.7, y = 4.4, # position de la note
label = "une setosa", # texte de la note
hjust = "left", vjust = "top", # ajustement
size = 3, fontface = "italic") +
annotate("rect",
ymin = sepal.width_extent[[1]],
ymax = sepal.width_extent[[2]],
xmin = sepal.length_extent[[1]],
xmax = sepal.length_extent[[2]],
fill = rgb(0.7,0.7,0.7,.5), # remplissage transparent à 50%
color = "black") # contour de couleur verte

Figure 3.7: Ajout d’annotations géométriques
Comme le dernier calque ajouté au graphique est le rectangle, vous noterez qu’il recouvre tous les calques existant, y compris les précédentes annotations. Pour corriger cela, il suffit de changer l’ordre des calques.
ggplot() +
annotate("rect",
ymin = sepal.width_extent[[1]],
ymax = sepal.width_extent[[2]],
xmin = sepal.length_extent[[1]],
xmax = sepal.length_extent[[2]],
fill = rgb(0.7,0.7,0.7,.5), # remplissage transparent à 50%
color = "green") + # contour de couleur verte
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
annotate("text", x = 6.7, y = 2.5, # position de la note
label = "une virginica", # texte de la note
hjust = "left", vjust = "top", # ajustement
size = 3, fontface = "italic") +
annotate("text", x = 5.7, y = 4.4, # position de la note
label = "une setosa", # texte de la note
hjust = "left", vjust = "top", # ajustement
size = 3, fontface = "italic")

Figure 3.8: Gestion de l’ordre des annotations
3.1.4 Utilisation des thèmes
De nombreux autres éléments peuvent être modifiés dans un graphique comme les paramètres des polices, l’arrière-plan, la grille de repères, etc. Il peut être fastidieux de paramétrer tous ces éléments. Une option intéressante est d’utiliser des thèmes déjà préconstruits. Le package ggplot2
propose une dizaine de thèmes : constatons leur impact sur le graphique précédent.
- Le thème classique (
theme_classic
) (figure 3.9)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
theme_classic()

Figure 3.9: Thème classique
- Le thème gris (
theme_gray
) (figure 3.10)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
theme_gray()

Figure 3.10: Thème gris
- Le thème noir et blanc (
theme_bw
) (figure 3.11)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
theme_bw()

Figure 3.11: Thème noir et blanc
- Le thème minimal (
theme_minimal
) (figure 3.12)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
theme_minimal()

Figure 3.12: Thème minimal
Il est aussi possible d’utiliser le package ggthemes
qui apporte des thèmes complémentaires intéressants dont :
- Le thème tufte (
theme_tufte
, à l’ancienne…) (figure 3.13)
library(ggthemes)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
theme_tufte()

Figure 3.13: Thème tufte
- Le thème economist (
theme_economist
, inspiré de la revue du même nom) (figure 3.14)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
theme_economist()

Figure 3.14: Thème economist
- Le thème solarized (
theme_solarized
, plus original) (figure 3.15)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
theme_solarized()

Figure 3.15: Thème solarized
Il en existe bien d’autres et vous pouvez composer vos propres thèmes. N’hésitez pas à explorer la documentation de ggplot2
et de ggthemes
pour en apprendre plus!
3.1.5 Composition d’une figure avec plusieurs graphiques
Il est très fréquent de vouloir combiner plusieurs graphiques dans une même figure. Deux cas se distinguent :
Les données pour les différents graphiques proviennent du même DataFrame et peuvent être distinguées selon une variable catégorielle. L’objectif est alors de dupliquer le même graphique, mais pour des sous-groupes de données. Dans ce cas, nous recommandons d’utiliser la fonction
facet_wrap
deggplot2
.Les graphiques sont complètement indépendants. Dans ce cas, nous recommandons d’utiliser la fonction
ggarrange
du packageggpubr
.
3.1.5.1 ggplot2
et ses facettes
Nous pourrions souhaiter réaliser une figure composite avec le jeu de données iris et séparer notre nuage de points en trois graphiques distincts selon l’espèce des iris (figure 3.16). Pour cela, il faut au préalable convertir la variable espèce en facteur.
iris$Species_fac <- as.factor(iris$Species)
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
facet_wrap(vars(Species_fac), ncol=2)

Figure 3.16: Graphique à facettes
Notez que le nom de la variable (ici Species_fac
) doit être spécifié au sein d’une sous-fonction vars
: vars(Species_fac)
. Nous aurions aussi pu réaliser le graphique sur une seule ligne en spécifiant ncol = 3
(figure 3.17).
ggplot() +
geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
labs(title = "Morphologie des sépales des iris", subtitle = "n = 150",
x = "Longueur des sépales",
y = "Largeur des sépales",
caption = "Source : jeu de données iris") +
facet_wrap(vars(Species_fac), ncol=3)

Figure 3.17: Graphique à facettes en une ligne
3.1.5.2 Arrangement des graphiques
La solution avec les facettes est très pratique, mais également très limitée puisqu’elle ne permet pas de créer une figure avec des graphiques combinant plusieurs types de géométries. ggarrange
du package ggpubr
permet tout simplement de combiner des graphiques déjà existant. Créons deux nuages de points comparant plusieurs variables en fonction de l’espèce des iris, puis combinons-les (figure 3.18). Attribuons également aux points une couleur en fonction de l’espèce des fleurs, afin de mieux les distinguer en associant la variable Species
au paramètre color
.
library(ggpubr)
plot1 <- ggplot(data = iris) +
geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
labs(subtitle = "Caractéristiques des sépales",
x = "Longueur",
y = "Largeur",
color = "Espèce")
plot2 <- ggplot(data = iris) +
geom_point(aes(x = Petal.Length, y = Petal.Width, color = Species)) +
labs(subtitle = "Caractéristiques des pétales",
x = "Longueur",
y = "Largeur",
color = "Espèce")
liste_plots <- list(plot1, plot2)
comp_plot <- ggarrange(plotlist = liste_plots, ncol = 2, nrow = 1,
common.legend = TRUE, legend = "bottom") #gérer la légende
annotate_figure(comp_plot,
top = text_grob("Morphologie des sépales et pétales des iris",
face = "bold", size = 12, just = "center"),
bottom = text_grob("Source : jeu de données iris",
face = "italic", size = 8, just = "left")
)

Figure 3.18: Figure avec plusieurs graphiques avec ggarrange
Quatre étapes sont nécessaires :
- Créer les graphiques et les enregistrer dans des objets (ici plot1 et plot2).
- Encapsuler ces objets dans une liste (ici liste_plots).
- Composer la figure finale avec la fonction
ggarrange
. - Ajouter les annotations à la figure composite.
L’argument common.legend
permet d’indiquer à la fonction ggarrange
de regrouper les légendes des deux graphiques. Dans notre cas, les deux graphiques ont les mêmes légendes, il est donc judicieux de les regrouper. L’argument legend
contrôle la position de la légende et peut prendre les valeurs : top, bottom, left, right ou none (absence de légende). La fonction annotate_figure
permet d’ajouter des éléments de texte au-dessus, au-dessous et sur les cotés de la figure composite.
3.1.6 Couleur
Dans un graphique, la couleur peut être utilisée à la fois pour représenter une variable quantitative (dégradé de couleur ou mise en classes), ou une variable qualitative (couleur par catégorie). Dans ggplot2
, il est possible d’attribuer une couleur au contour des géométries avec l’argument color
et au remplissage avec l’argument fill
. Il est possible de spécifier une couleur de trois façons dans R :
- En utilisant le nom de la couleur dans une chaîne de caractère :
"chartreuse4"
. R dispose de 657 noms de couleurs prédéfinis. Pour tous les afficher, utilisez la fonctioncolors()
, qui permet de les visualiser (figure 3.19).

Figure 3.19: Couleurs de base
En indiquant le code hexadécimal de la couleur. Il s’agit d’une suite de six lettres et de chiffres précédée par un dièse :
"#99ff33"
.En utilisant une notation RGB (rouge, vert, bleu, transparence). Cette notation doit contenir quatre nombres entre 0 et 1 (0 % et 100 %), indiquant respectivement la quantité de rouge, de vert, de bleu et la transparence. Ces quatre nombres sont donnés comme argument à la fonction
rgb
:rgb(0.6, 1, 0.2, 0)
.
Le choix des couleurs est un problème plus complexe que la manière de les spécifier. Il existe d’ailleurs tout un pan de la sémiologie graphique dédié à la question du choix et de l’association des couleurs. Une première ressource intéressante est ColorBrewer. Il s’agit d’une sélection de palettes de couleurs particulièrement efficaces et dont certaines sont même adaptées pour les personnes daltoniennes (figure 3.20). Il est possible d’accéder directement aux palettes dans R grâce au package RColorBrewer
et la fonction brewer.pal
:

Figure 3.20: Palette de couleurs de ColorBrewer
Une autre ressource pertinente est le site web coolors.co qui propose de nombreuses palettes à portée de clic.
Références
Wickham, Hadley. 2010. « A layered grammar of graphics ». Journal of Computational and Graphical Statistics 19 (1): 3‑28. http://dx.doi.org/10.1198/jcgs.2009.07098.