9 Les graphiques avec ggplot

Dans ce chapitre, nous allons apprendre à créer des graphiques en utilisant le package spécialisé ggplot2, abrégé ci-après en ggplot. ggplot est un package très complet et très célèbre qui repose sur le parincipe de “Grammar of Graphics”. Cette grammaire permet une description précise des différents composants d’un graphique, du plus simple au plus complexe. L’idée principale est de concevoir un graphique comme une succession de couches (layers, en anglais) qui se superposent pour, au final, donner le résultat escompté, un peu comme on peut décomposer la structure d’une phrase (complexe) à l’aide de règles grammaticales.

Ce principe, ainsi que les différentes composantes d’un graphique, sont décrits plus en détail dans ce document et dans les références qu’il contient.

Pratiquement, tout graphique que l’on peut faire avec R de base (càd. avec le package graphics) peut se faire avec ggplot et vise versa. Mais, lorsqu’il s’agit de réaliser des graphiques plus complexes et plus attractifs, ggplot est souvent plus facile (lorsqu’on le maîtrise !).

Pour commencer, nous avons besoin d’installer, si ce n’est pas déjà fait, et de charger le package ggplot2.

install.packages("ggplot2")
library(ggplot2)

Nous allons continuer à utiliser le jeu de données mpg, disponible dans le package ggplot2, que nous avons utilisé au chapitre précédent. Rappelons rapidement à quoi ressemble la structure des données (après traitement).

mpg <- transform(ggplot2::mpg, cyl = factor(cyl), trans = factor(trans), drv = factor(drv), fl = factor(fl), class = factor(class), year = factor(year))
levels(mpg$trans) <- c(rep("auto", 8), rep("manual", 2))
str(mpg)
'data.frame':   234 obs. of  11 variables:
 $ manufacturer: chr  "audi" "audi" "audi" "audi" ...
 $ model       : chr  "a4" "a4" "a4" "a4" ...
 $ displ       : num  1.8 1.8 2 2 2.8 2.8 3.1 1.8 1.8 2 ...
 $ year        : Factor w/ 2 levels "1999","2008": 1 1 2 2 1 1 2 1 1 2 ...
 $ cyl         : Factor w/ 4 levels "4","5","6","8": 1 1 1 1 3 3 3 1 1 1 ...
 $ trans       : Factor w/ 2 levels "auto","manual": 1 2 2 1 1 2 1 2 1 2 ...
 $ drv         : Factor w/ 3 levels "4","f","r": 2 2 2 2 2 2 2 1 1 1 ...
 $ cty         : int  18 21 20 21 16 18 18 18 16 20 ...
 $ hwy         : int  29 29 31 30 26 26 27 26 25 28 ...
 $ fl          : Factor w/ 5 levels "c","d","e","p",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ class       : Factor w/ 7 levels "2seater","compact",..: 2 2 2 2 2 2 2 2 2 2 ...

9.1 Les bases de ggplot

La création d’un graphique ggplot débute avec l’appel de la fonction ggplot(). Les couches supplémentaires (layers) sont ajoutées en ayant recours au symbole +. La syntaxe générique de base est la suivante :

ggplot(<data.name>) + aes(<variables>) + geom_<xxx>(...)
# or, equivalently
ggplot(data = <data.name>, mapping = aes(<variables>)) +
  geom_<xxx>(...)

Ce dernier format est le plus utilisé. Pour améliorer la lisibilité du code, il est recommandé de commencer par écrire ggplot(..., aes(...)) (ou ggplot(...) + aes(...)), sur la première ligne, puis d’ajouter une nouvelle ligne à chaque fois que l’on veut ajouter une nouvelle couche. Dans ce cas, + doit figurer à la fin de la ligne et non au début.

Dans la syntaxe ci-dessus

  • ggplot() permet, typiquement, de spécifier le jeu de données à analyser. Il doit s’agir d’un objet de type data.frame (ou ou assimilé à un tel).

  • aes(), pour aesthetics, permet de spécifier les variables à visualiser et associe à chaque variable un emplacement/rôle ou une propriété visuelle : les axes (x, y), couleur (color), forme (shape), taille (size), etc.; voir la Section 9.2 pour plus à ce sujet.

  • geom_<xxx>(), où <xxx> doit être remplacée par le nom d’une forme géométrique, permet de spécifier le type de représentation graphique souhaitée. Les geoms les plus fréquemment utilisés sont : geom_point() pour tracer des points, geom_line() pour des lignes, geom_bar() pour des barres, geom_histogram() pour un histogramme, geom_boxplot() pour un boxplot, geom_density() pour une densité, et geom_smooth() pour une courbe de tendance; voir la Section 9.3 pour plus à ce sujet.

Nous allons commencer par réaliser un diagramme à point (scatter plot) en utilisant geom_point(). Voici le code.

ggplot(data   = mpg,              # spécifier les données
      mapping = aes(x = displ,    # mapper 'displ' à l'axe des x
                    y = hwy)) +   # mapper 'hwy' à l'axe des y
  geom_point()                    # tracer les points

Le code ci-dessus peut être décomposé comme suite (exécutez le script ligne par ligne)

ggplot(mpg)                                          # left
ggplot(mpg) + aes(x = displ, y = hwy)                # middle
ggplot(mpg) + aes(x = displ, y = hwy) + geom_point() # right

Nous pouvons sauvegarder un ggplot dans un objet comme n’importe quel autre objet R.

p <- ggplot(mpg, aes(x = displ, y = "")) + geom_point() + labs(y = NULL)
p

Si vous examinez la structure de l’objet p, en tapant str(p), vous constateriez que p est une liste de 9 éléments dont les noms sont

names(p)
[1] "data"        "layers"      "scales"      "mapping"     "theme"      
[6] "coordinates" "facet"       "plot_env"    "labels"     

Ce sont ces éléments qui définissent de manière spécifique le ggplot p. Parmi ces éléments, on trouve l’objet p$data, qui n’est rien d’autre que le data.frame transmis à ggplot2(), p$layers qui contient la liste des couches, et p$mapping qui contient la liste des aesthetics.

Une façon plus élaborée d’inspecter la structure d’un ggplot est d’utiliser la fonction ggplot_build(). Cette fonction produit notamment une liste de data.frames (une par couche graphique) où les données de chaque couche sont stockées et organisées dans un format standardisé adapté à la représentation graphique utilisée.

ggplot_build(p)$data
[[1]]
      x y PANEL group shape colour size fill alpha stroke
1   1.8 1     1     1    19  black  1.5   NA    NA    0.5
2   1.8 1     1     1    19  black  1.5   NA    NA    0.5
3   2.0 1     1     1    19  black  1.5   NA    NA    0.5
4   2.0 1     1     1    19  black  1.5   NA    NA    0.5
5   2.8 1     1     1    19  black  1.5   NA    NA    0.5
6   2.8 1     1     1    19  black  1.5   NA    NA    0.5
7   3.1 1     1     1    19  black  1.5   NA    NA    0.5
8   1.8 1     1     1    19  black  1.5   NA    NA    0.5
9   1.8 1     1     1    19  black  1.5   NA    NA    0.5
10  2.0 1     1     1    19  black  1.5   NA    NA    0.5
11  2.0 1     1     1    19  black  1.5   NA    NA    0.5
12  2.8 1     1     1    19  black  1.5   NA    NA    0.5
13  2.8 1     1     1    19  black  1.5   NA    NA    0.5
14  3.1 1     1     1    19  black  1.5   NA    NA    0.5
15  3.1 1     1     1    19  black  1.5   NA    NA    0.5
16  2.8 1     1     1    19  black  1.5   NA    NA    0.5
17  3.1 1     1     1    19  black  1.5   NA    NA    0.5
18  4.2 1     1     1    19  black  1.5   NA    NA    0.5
19  5.3 1     1     1    19  black  1.5   NA    NA    0.5
20  5.3 1     1     1    19  black  1.5   NA    NA    0.5
21  5.3 1     1     1    19  black  1.5   NA    NA    0.5
22  5.7 1     1     1    19  black  1.5   NA    NA    0.5
23  6.0 1     1     1    19  black  1.5   NA    NA    0.5
24  5.7 1     1     1    19  black  1.5   NA    NA    0.5
25  5.7 1     1     1    19  black  1.5   NA    NA    0.5
26  6.2 1     1     1    19  black  1.5   NA    NA    0.5
27  6.2 1     1     1    19  black  1.5   NA    NA    0.5
28  7.0 1     1     1    19  black  1.5   NA    NA    0.5
29  5.3 1     1     1    19  black  1.5   NA    NA    0.5
30  5.3 1     1     1    19  black  1.5   NA    NA    0.5
31  5.7 1     1     1    19  black  1.5   NA    NA    0.5
32  6.5 1     1     1    19  black  1.5   NA    NA    0.5
33  2.4 1     1     1    19  black  1.5   NA    NA    0.5
34  2.4 1     1     1    19  black  1.5   NA    NA    0.5
35  3.1 1     1     1    19  black  1.5   NA    NA    0.5
36  3.5 1     1     1    19  black  1.5   NA    NA    0.5
37  3.6 1     1     1    19  black  1.5   NA    NA    0.5
38  2.4 1     1     1    19  black  1.5   NA    NA    0.5
39  3.0 1     1     1    19  black  1.5   NA    NA    0.5
40  3.3 1     1     1    19  black  1.5   NA    NA    0.5
41  3.3 1     1     1    19  black  1.5   NA    NA    0.5
42  3.3 1     1     1    19  black  1.5   NA    NA    0.5
43  3.3 1     1     1    19  black  1.5   NA    NA    0.5
44  3.3 1     1     1    19  black  1.5   NA    NA    0.5
45  3.8 1     1     1    19  black  1.5   NA    NA    0.5
46  3.8 1     1     1    19  black  1.5   NA    NA    0.5
47  3.8 1     1     1    19  black  1.5   NA    NA    0.5
48  4.0 1     1     1    19  black  1.5   NA    NA    0.5
49  3.7 1     1     1    19  black  1.5   NA    NA    0.5
50  3.7 1     1     1    19  black  1.5   NA    NA    0.5
51  3.9 1     1     1    19  black  1.5   NA    NA    0.5
52  3.9 1     1     1    19  black  1.5   NA    NA    0.5
53  4.7 1     1     1    19  black  1.5   NA    NA    0.5
54  4.7 1     1     1    19  black  1.5   NA    NA    0.5
55  4.7 1     1     1    19  black  1.5   NA    NA    0.5
56  5.2 1     1     1    19  black  1.5   NA    NA    0.5
57  5.2 1     1     1    19  black  1.5   NA    NA    0.5
58  3.9 1     1     1    19  black  1.5   NA    NA    0.5
59  4.7 1     1     1    19  black  1.5   NA    NA    0.5
60  4.7 1     1     1    19  black  1.5   NA    NA    0.5
61  4.7 1     1     1    19  black  1.5   NA    NA    0.5
62  5.2 1     1     1    19  black  1.5   NA    NA    0.5
63  5.7 1     1     1    19  black  1.5   NA    NA    0.5
64  5.9 1     1     1    19  black  1.5   NA    NA    0.5
65  4.7 1     1     1    19  black  1.5   NA    NA    0.5
66  4.7 1     1     1    19  black  1.5   NA    NA    0.5
67  4.7 1     1     1    19  black  1.5   NA    NA    0.5
68  4.7 1     1     1    19  black  1.5   NA    NA    0.5
69  4.7 1     1     1    19  black  1.5   NA    NA    0.5
70  4.7 1     1     1    19  black  1.5   NA    NA    0.5
71  5.2 1     1     1    19  black  1.5   NA    NA    0.5
72  5.2 1     1     1    19  black  1.5   NA    NA    0.5
73  5.7 1     1     1    19  black  1.5   NA    NA    0.5
74  5.9 1     1     1    19  black  1.5   NA    NA    0.5
75  4.6 1     1     1    19  black  1.5   NA    NA    0.5
76  5.4 1     1     1    19  black  1.5   NA    NA    0.5
77  5.4 1     1     1    19  black  1.5   NA    NA    0.5
78  4.0 1     1     1    19  black  1.5   NA    NA    0.5
79  4.0 1     1     1    19  black  1.5   NA    NA    0.5
80  4.0 1     1     1    19  black  1.5   NA    NA    0.5
81  4.0 1     1     1    19  black  1.5   NA    NA    0.5
82  4.6 1     1     1    19  black  1.5   NA    NA    0.5
83  5.0 1     1     1    19  black  1.5   NA    NA    0.5
84  4.2 1     1     1    19  black  1.5   NA    NA    0.5
85  4.2 1     1     1    19  black  1.5   NA    NA    0.5
86  4.6 1     1     1    19  black  1.5   NA    NA    0.5
87  4.6 1     1     1    19  black  1.5   NA    NA    0.5
88  4.6 1     1     1    19  black  1.5   NA    NA    0.5
89  5.4 1     1     1    19  black  1.5   NA    NA    0.5
90  5.4 1     1     1    19  black  1.5   NA    NA    0.5
91  3.8 1     1     1    19  black  1.5   NA    NA    0.5
92  3.8 1     1     1    19  black  1.5   NA    NA    0.5
93  4.0 1     1     1    19  black  1.5   NA    NA    0.5
94  4.0 1     1     1    19  black  1.5   NA    NA    0.5
95  4.6 1     1     1    19  black  1.5   NA    NA    0.5
96  4.6 1     1     1    19  black  1.5   NA    NA    0.5
97  4.6 1     1     1    19  black  1.5   NA    NA    0.5
98  4.6 1     1     1    19  black  1.5   NA    NA    0.5
99  5.4 1     1     1    19  black  1.5   NA    NA    0.5
100 1.6 1     1     1    19  black  1.5   NA    NA    0.5
101 1.6 1     1     1    19  black  1.5   NA    NA    0.5
102 1.6 1     1     1    19  black  1.5   NA    NA    0.5
103 1.6 1     1     1    19  black  1.5   NA    NA    0.5
104 1.6 1     1     1    19  black  1.5   NA    NA    0.5
105 1.8 1     1     1    19  black  1.5   NA    NA    0.5
106 1.8 1     1     1    19  black  1.5   NA    NA    0.5
107 1.8 1     1     1    19  black  1.5   NA    NA    0.5
108 2.0 1     1     1    19  black  1.5   NA    NA    0.5
109 2.4 1     1     1    19  black  1.5   NA    NA    0.5
110 2.4 1     1     1    19  black  1.5   NA    NA    0.5
111 2.4 1     1     1    19  black  1.5   NA    NA    0.5
112 2.4 1     1     1    19  black  1.5   NA    NA    0.5
113 2.5 1     1     1    19  black  1.5   NA    NA    0.5
114 2.5 1     1     1    19  black  1.5   NA    NA    0.5
115 3.3 1     1     1    19  black  1.5   NA    NA    0.5
116 2.0 1     1     1    19  black  1.5   NA    NA    0.5
117 2.0 1     1     1    19  black  1.5   NA    NA    0.5
118 2.0 1     1     1    19  black  1.5   NA    NA    0.5
119 2.0 1     1     1    19  black  1.5   NA    NA    0.5
120 2.7 1     1     1    19  black  1.5   NA    NA    0.5
121 2.7 1     1     1    19  black  1.5   NA    NA    0.5
122 2.7 1     1     1    19  black  1.5   NA    NA    0.5
123 3.0 1     1     1    19  black  1.5   NA    NA    0.5
124 3.7 1     1     1    19  black  1.5   NA    NA    0.5
125 4.0 1     1     1    19  black  1.5   NA    NA    0.5
126 4.7 1     1     1    19  black  1.5   NA    NA    0.5
127 4.7 1     1     1    19  black  1.5   NA    NA    0.5
128 4.7 1     1     1    19  black  1.5   NA    NA    0.5
129 5.7 1     1     1    19  black  1.5   NA    NA    0.5
130 6.1 1     1     1    19  black  1.5   NA    NA    0.5
131 4.0 1     1     1    19  black  1.5   NA    NA    0.5
132 4.2 1     1     1    19  black  1.5   NA    NA    0.5
133 4.4 1     1     1    19  black  1.5   NA    NA    0.5
134 4.6 1     1     1    19  black  1.5   NA    NA    0.5
135 5.4 1     1     1    19  black  1.5   NA    NA    0.5
136 5.4 1     1     1    19  black  1.5   NA    NA    0.5
137 5.4 1     1     1    19  black  1.5   NA    NA    0.5
138 4.0 1     1     1    19  black  1.5   NA    NA    0.5
139 4.0 1     1     1    19  black  1.5   NA    NA    0.5
140 4.6 1     1     1    19  black  1.5   NA    NA    0.5
141 5.0 1     1     1    19  black  1.5   NA    NA    0.5
142 2.4 1     1     1    19  black  1.5   NA    NA    0.5
143 2.4 1     1     1    19  black  1.5   NA    NA    0.5
144 2.5 1     1     1    19  black  1.5   NA    NA    0.5
145 2.5 1     1     1    19  black  1.5   NA    NA    0.5
146 3.5 1     1     1    19  black  1.5   NA    NA    0.5
147 3.5 1     1     1    19  black  1.5   NA    NA    0.5
148 3.0 1     1     1    19  black  1.5   NA    NA    0.5
149 3.0 1     1     1    19  black  1.5   NA    NA    0.5
150 3.5 1     1     1    19  black  1.5   NA    NA    0.5
151 3.3 1     1     1    19  black  1.5   NA    NA    0.5
152 3.3 1     1     1    19  black  1.5   NA    NA    0.5
153 4.0 1     1     1    19  black  1.5   NA    NA    0.5
154 5.6 1     1     1    19  black  1.5   NA    NA    0.5
155 3.1 1     1     1    19  black  1.5   NA    NA    0.5
156 3.8 1     1     1    19  black  1.5   NA    NA    0.5
157 3.8 1     1     1    19  black  1.5   NA    NA    0.5
158 3.8 1     1     1    19  black  1.5   NA    NA    0.5
159 5.3 1     1     1    19  black  1.5   NA    NA    0.5
160 2.5 1     1     1    19  black  1.5   NA    NA    0.5
161 2.5 1     1     1    19  black  1.5   NA    NA    0.5
162 2.5 1     1     1    19  black  1.5   NA    NA    0.5
163 2.5 1     1     1    19  black  1.5   NA    NA    0.5
164 2.5 1     1     1    19  black  1.5   NA    NA    0.5
165 2.5 1     1     1    19  black  1.5   NA    NA    0.5
166 2.2 1     1     1    19  black  1.5   NA    NA    0.5
167 2.2 1     1     1    19  black  1.5   NA    NA    0.5
168 2.5 1     1     1    19  black  1.5   NA    NA    0.5
169 2.5 1     1     1    19  black  1.5   NA    NA    0.5
170 2.5 1     1     1    19  black  1.5   NA    NA    0.5
171 2.5 1     1     1    19  black  1.5   NA    NA    0.5
172 2.5 1     1     1    19  black  1.5   NA    NA    0.5
173 2.5 1     1     1    19  black  1.5   NA    NA    0.5
174 2.7 1     1     1    19  black  1.5   NA    NA    0.5
175 2.7 1     1     1    19  black  1.5   NA    NA    0.5
176 3.4 1     1     1    19  black  1.5   NA    NA    0.5
177 3.4 1     1     1    19  black  1.5   NA    NA    0.5
178 4.0 1     1     1    19  black  1.5   NA    NA    0.5
179 4.7 1     1     1    19  black  1.5   NA    NA    0.5
180 2.2 1     1     1    19  black  1.5   NA    NA    0.5
181 2.2 1     1     1    19  black  1.5   NA    NA    0.5
182 2.4 1     1     1    19  black  1.5   NA    NA    0.5
183 2.4 1     1     1    19  black  1.5   NA    NA    0.5
184 3.0 1     1     1    19  black  1.5   NA    NA    0.5
185 3.0 1     1     1    19  black  1.5   NA    NA    0.5
186 3.5 1     1     1    19  black  1.5   NA    NA    0.5
187 2.2 1     1     1    19  black  1.5   NA    NA    0.5
188 2.2 1     1     1    19  black  1.5   NA    NA    0.5
189 2.4 1     1     1    19  black  1.5   NA    NA    0.5
190 2.4 1     1     1    19  black  1.5   NA    NA    0.5
191 3.0 1     1     1    19  black  1.5   NA    NA    0.5
192 3.0 1     1     1    19  black  1.5   NA    NA    0.5
193 3.3 1     1     1    19  black  1.5   NA    NA    0.5
194 1.8 1     1     1    19  black  1.5   NA    NA    0.5
195 1.8 1     1     1    19  black  1.5   NA    NA    0.5
196 1.8 1     1     1    19  black  1.5   NA    NA    0.5
197 1.8 1     1     1    19  black  1.5   NA    NA    0.5
198 1.8 1     1     1    19  black  1.5   NA    NA    0.5
199 4.7 1     1     1    19  black  1.5   NA    NA    0.5
200 5.7 1     1     1    19  black  1.5   NA    NA    0.5
201 2.7 1     1     1    19  black  1.5   NA    NA    0.5
202 2.7 1     1     1    19  black  1.5   NA    NA    0.5
203 2.7 1     1     1    19  black  1.5   NA    NA    0.5
204 3.4 1     1     1    19  black  1.5   NA    NA    0.5
205 3.4 1     1     1    19  black  1.5   NA    NA    0.5
206 4.0 1     1     1    19  black  1.5   NA    NA    0.5
207 4.0 1     1     1    19  black  1.5   NA    NA    0.5
208 2.0 1     1     1    19  black  1.5   NA    NA    0.5
209 2.0 1     1     1    19  black  1.5   NA    NA    0.5
210 2.0 1     1     1    19  black  1.5   NA    NA    0.5
211 2.0 1     1     1    19  black  1.5   NA    NA    0.5
212 2.8 1     1     1    19  black  1.5   NA    NA    0.5
213 1.9 1     1     1    19  black  1.5   NA    NA    0.5
214 2.0 1     1     1    19  black  1.5   NA    NA    0.5
215 2.0 1     1     1    19  black  1.5   NA    NA    0.5
216 2.0 1     1     1    19  black  1.5   NA    NA    0.5
217 2.0 1     1     1    19  black  1.5   NA    NA    0.5
218 2.5 1     1     1    19  black  1.5   NA    NA    0.5
219 2.5 1     1     1    19  black  1.5   NA    NA    0.5
220 2.8 1     1     1    19  black  1.5   NA    NA    0.5
221 2.8 1     1     1    19  black  1.5   NA    NA    0.5
222 1.9 1     1     1    19  black  1.5   NA    NA    0.5
223 1.9 1     1     1    19  black  1.5   NA    NA    0.5
224 2.0 1     1     1    19  black  1.5   NA    NA    0.5
225 2.0 1     1     1    19  black  1.5   NA    NA    0.5
226 2.5 1     1     1    19  black  1.5   NA    NA    0.5
227 2.5 1     1     1    19  black  1.5   NA    NA    0.5
228 1.8 1     1     1    19  black  1.5   NA    NA    0.5
229 1.8 1     1     1    19  black  1.5   NA    NA    0.5
230 2.0 1     1     1    19  black  1.5   NA    NA    0.5
231 2.0 1     1     1    19  black  1.5   NA    NA    0.5
232 2.8 1     1     1    19  black  1.5   NA    NA    0.5
233 2.8 1     1     1    19  black  1.5   NA    NA    0.5
234 3.6 1     1     1    19  black  1.5   NA    NA    0.5

Un objet ggplot sauvegardé peut être modifié en y ajoutant ou supprimant certains éléments. Dans l’exemple suivant, nous ajoutons l’axe des y et une ligne qui relie les observations, puis nous supprimons cette dernière.

p <- p + aes(y = hwy); p          # left
p <- p + geom_line(); p           # middle
p$layers[[2]] <- NULL; p          # right

Titres et noms des axes

La fonction labs() permet de titrer un ggplot, lui donner un sous titre, modifier les noms des axes, etc.. Reprenons notre précédent graphique et améliorons le.

p <- p + aes(y = hwy) + labs(
  title    = "Fuel economy for 38 popular models of cars",
  subtitle = "data from 1999 to 2008",
  x        = "Engine displacement, in litres",
  y        = "Highway miles per gallon",
  caption  = "mpg data from the ggplot2 package")
p

Modifier le thème

On peut customiser un ggplot en lui donnant un look particulier/personnaliser. La façon la plus simple pour faire cela est d’utiliser l’un des nombreux thèmes existants, que l’on peut facilement appliquer à l’aide des fonctions theme_<xxx>().

p + theme_gray()    # left  : the default theme
p + theme_bw()      # right  : black & white theme

On peut changer le thème pour la session R en cours en utilisant la fonction theme_set() comme suit :

theme_bw() |> theme_set()

La fonction theme() permet de modifier les composantes d’un thème. Voici un exemple

p + theme_bw() +
  theme(
    plot.title = element_text(colour = "grey59", face = "italic"),
    plot.subtitle = element_text(colour = "red"),
    axis.title = element_text(colour = "blue", face = "bold")
  )

Et la fonction theme_set() permet d’appliquer de tels changements globalement (pour tous les ggplot de la session R en cours).

(theme_bw() + theme(
  axis.title = element_text(colour = "blue", face = "bold"),
  plot.title = element_text(colour = "blue", face = "bold"),
  plot.subtitle = element_text(colour = "blue", face = "bold")
)) |>
  theme_set()

Le nombre de paramètres possibles est énorme et couvre toutes les propriétés visuelles du graphique. Il n’est pas toujours aisé de trouver les options souhaitées. À ce propos, le site ggplot2tutor peut vous faciliter la tâche (voir la rubrique ‘Theme finder’).

Scales

ggplot propose plusieurs fonctions de type scale_<aesthetic.name>_<xxx>() qui permettent de contrôler, entre autres, les axes du graphique. Par défaut, ggplot choisit les scales à appliquer et définit leurs arguments en fonction de la nature des données et de la représentation graphique souhaitée. Par exemple, lorsque vous tapze:

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point()

ggplot ajoute automatiquement les “scales” suivants

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point() +
  scale_x_continuous() + scale_y_continuous()

Consultez l’aide des fonctions scale_x_continuous() et scale_y_continuous() pour savoir quels éléments vous pouvez contrôler avec. L’exemple suivant montre comment contrôler les étiquettes de l’axe des x à l’aide de scale_x_continuous().

p <- ggplot(mpg, aes(x = displ, y = hwy)) + geom_point()
p

p + scale_x_continuous(n.breaks =  10)

p + scale_x_continuous(breaks =  c(2, 4, 6), labels = c("a", "b", "c"), minor_breaks = seq(1, 7, 0.1))

Les fonctions scale_x_continuous() et scale_y_continuous() peuvent être utilisées pour limiter l’affichage des données à un sous-ensemble spécifique. Si vous souhaitez zoomer (sans effacer de données), utilisez la fonction coord_cartesian().

p <- ggplot(mpg, aes(x = "", y = displ)) + geom_point() + geom_boxplot(fill = NA) + labs(x = NULL)
p

# remove all data points outside the given range before plotting
p + scale_y_continuous(limits = c(2, 3))
# aletrntive synatx:  p + ylim(2, 3)
# or:                 p + lims(y = c(2, 3))

# zoopm in without removing any data
p + coord_cartesian(ylim = c(2, 3))

Pour les variables discrètes, les fonctions scale_x_discrete() et scale_y_discrete(), dont le fonctionnement est similaire à ce qui est décrit ci-dessus, peuvent être utilisées.

Outre le pilotage des axes x et y, il existe un grand nombre de fonctions scale qui permettent de contrôler divers paramètres liés à la représentation des données, comme par exemple le choix des couleurs à privilégier. Tous les détails à ce sujet se trouvent ici. Pour un apprentissage interactif basé sur des exemples, reportez-vous à ggplot2tutor; voir la rubrique ‘Scales finder’.

9.2 Les arguments aesthetics

Dans un ggplot, le terme “esthétique” (ou plutôt aesthetic, en anglais) fait référence aux divers éléments de style ou d’emplacement, tels que la couleur (color), la forme des points (shape), la taille des points (size), le type de lignes (linetype), etc, utilisés pour représenter les variables dans la base de données étudiée, et non à l’affichage d’éléments externes (non-data), tels que les titres, les étiquettes des axes, la couleur d’arrière-plan, etc. discuté ci-dessus. Ces éléments sont contrôlés par les arguments dits aesthetics des fonctions aes() et geom_<xxx>(), comme illustré dans le code suivant.

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(shape = 18, size = 3, color = "blue")
ggplot(mpg, aes(x = displ, y = hwy)) + geom_line(color = "red", linetype = 3)

En plus des variables x et y, les arguments aesthetics dans ces deux graphiques sont shape, color, size, et linetype. Il existe d’autres arguments qui permettent de contrôler d’autres aspects de l’affichage des données, comme par exemple l’argument fill pour la couleur du remplissage, et l’argument alpha pour la transparence. Nous allons découvrir plus sur ces arguments et leurs utilisations au fur et à mesure.

Chacune des fonctions geom_<xxx>() accepte un certain nombre d’arguments aesthetics, qu’il serait difficile de présenter en détail ici. Consultez l’aide (?geom_<xxx>()) de chaque fonction pour les découvrir. Beaucoup de geom_<xxx>() partagent les mêmes arguments aesthetics. Par exemple, en plus de x et y qui sont obligatoires, les arguments aesthetics clés de geom_point() sont color, shape, size, et alpha; pour geom_line() ces arguments sont color, linetype, linewidth , et alpha.

Les arguments aesthetics n’ayant pas été modifiés conservent leurs valeurs par défaut. Par exemple, pour les points ggplot utilise, par défaut, shape = 19 et pour les lignes ggplot utilise linetype = 1. Voici la liste des formes et lignes (standards) disponible dans R; consultez ce lien pour plus d’information sur ce sujet.

Nous en apprendrons davantage sur l’utilisation les différents arguments aesthetics au fur et à mesure que nous progresserons dans le cours.

Setting vs mapping

Les arguments aesthetics peuvent se trouver à l’intérieur ou à l’extérieur d’un aes(). Considérant par exemple le cas où nous voulons changer la forme (shape) des points d’un graphique. Il y a deux situations possibles à considérer:

  • on désire une forme statique (fixe) à appliquer à l’ensemble des points. Dans ce cas il faut placer l’argument shape directement à l’intérieur du geom_point(), et écrire geom_point(shape = <value>).
  • on désir une forme dynamique qui varie en fonction des valeurs prises par une variable de notre data.frame; càd on désire mapper (associer) une variable à shape. Dans ce cas il faut placer shape à l’intérieur de la fonction aes(), et écrire geom_point(mapping = aes(shape = <var.name>)), ou simplement geom_point(aes(shape = <var.name>)).

On désigne la première situation par le terme setting et la deuxième par le terme mapping. Un mapping est une mise en correspondance entre un argument aesthetic (shap, color, size, etc.) et une variable du data.frame, alors qu’un setting est le fait d’assigner une valeur (fixe) à l’argument aesthetic. Contrairement au setting, un mapping doit toujours se faire à l’intérieur de la fonction aes(). En résumé, contrairement aux constantes, les variables doivent toujours être placées à l’intérieur d’une aes().

Voici un exemple qui illustre les deux cas pour l’argument shape.

# left : setting
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(shape = 1)         
# right : mapping
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(shape = trans))                     

Dans la dernière ligne du code ci-dessus, nous avons placé aes() à l’intérieur de la fonction geom_point(). On pourrait aussi écrire ggplot(mpg, aes(x = displ, y = hwy, shape = trans)) + geom_point(), ou encore ggplot(mpg) + aes(x = displ, y = hwy, shape = trans) + geom_point(), ce qui produirait exactement le même plot. Néanmoins, de façon générale, l’emplacement de l’aes() peut produire des résultats fort différents. Nous en discuterons de ce point un peu plus loin.

Notez également que, par défaut, ggplot ajoute automatiquement une légende lorsqu’un mapping (avec aes()) d’un élément esthétique, tel que shape, color, fill, size, etc., est effectué. Le titre de la légende n’est rien d’autre que le nom de la variable assignée à l’élément esthétique utilisé.

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(shape = trans, color = trans))

ggplot tente de minimiser le nombre de légendes présentes dans un graphique. Pour ce faire, les légendes impliquant la même variable (comme ci-dessus ou la variable trans est associée à la fois à shape et à color) sont fusionnées en une seule légende dont le titre est le nom de la variable en question. La fonction labs() permet de modifier le(s) titre(s) de(s) légende(s). Voici un exemple.

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(shape = trans, color = trans)) +
  labs(color = "Transmission", shape = "Transmission")

Un mapping ou un setting mal spécifié entraîne typiquement une erreur ou un résultat atypique. Voici trois exemples qui illustrent cela.

# Exemple (1): mauvais setting (Error) 
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(shape = trans)
Error in eval(expr, envir, enclos): object 'trans' not found

Cette erreur est due au fait que ggplot interprète trans comme un objet (chiffre) existant dans l’environnement de travail, or cela n’est pas le cas. Pour corriger cette erreur, il suffit de taper ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(shape = mpg$trans), ou mieux encore, ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(shape = trans)).

# Exemple (2): mauvais mapping (Error)
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(shape = 1)) 
Error in `geom_point()`:
! Problem while computing aesthetics.
ℹ Error occurred in the 1st layer.
Caused by error in `scale_f()`:
! A continuous variable cannot be mapped to the shape aesthetic
ℹ choose a different aesthetic or use `scale_shape_binned()`

Ici ggplot interprète le chifre 1 comme une variable numérique (continue) dont la valeur est fixée à \(1\), or shape n’accepte pas une telle entrée. Une façon d’y remédier est de taper

# Exemple (3): mauvais mapping (Résultat atypique)
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(shape = '1'))

Le message d’erreur disparaît, mais shape = '1' n’a aucun impact sur la forme des points (la forme par défaut est utilisée) et on constate l’apparition d’une légende. Cela est dû au fait que ggplot interprète '1' comme une facteur (factor variable), qui ne contient qu’un seul niveau (“1”). En pratique, on peut tirer avantage de cette “anomalie” pour, par exemple, ajouter facilement une légende à ggplot; un exemple concret est fourni plus loin.

Arguments aesthetics les plus courants

Comme expliqué plus haut, chaque fonction geom a un certain nombre d’arguments aesthetics (comme shape dans le cas de geom_point(), dont nous venons de parler). Ces arguments fonctionnent selon les mêmes règles que shape. Les arguments aesthetics les plus couramment invoqués sont passés en revue dans les quelques exemples qui suivent. Dans ces exemples, nous utiliserons geom_point() et geom_line(), cette dernière relie simplement les observations dans l’ordre de la variable sur l’axe des x.

+ color
# top left : setting color in geom_line()
ggplot(mpg, aes(x = displ, y = hwy)) + geom_line(color = "red")  
# top right : mapping color to a factor variable in geom_line()
ggplot(mpg, aes(x = displ, y = hwy)) + geom_line(aes(color = trans)) 
# bottom left : mapping color to a numeric variable in geom_point()
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(color = cty))  
# bottom right : mapping color to a logical variable 
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(color = cty > 15))    #  

+ size
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(size = 3)
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(size = cty))

+ linetype et linewidth
ggplot(mpg, aes(x = displ, y = hwy)) + geom_line(linewidth = 1)
ggplot(mpg, aes(x = displ, y = hwy)) + geom_line(linewidth = 1, aes(linetype = trans))

+ groupe

L’aesthetic group permet de diviser les données de façon à ce qu’elles puissent être représentées pour chaque groupe séparé plutôt que comme un seul ensemble. Dans la plupart des cas, le regroupement est appliqué implicitement lorsque l’on fait à un mapping via size, color, shape, linetype, etc. Ainsi, dans le code ci-dessus, aes(linetype = trans) entraîne la division des données en deux groupes selon les modalités du facteur trans.

Il y a des cas où on veut appliquer le regroupement explicitement (sans nécessairement faire appellent à un élément de style comme linetype), en voici un exemple.

ggplot(mpg, aes(x = displ, y = hwy)) + geom_line(aes(group = trans))

+ alpha

Un autre argument aesthetic souvent utilisé en ggplot est le alpha qui contrôle la transparence d’un remplissage. Il prend une valeur comprise entre 0 (transparence totale) et 1 (opacité totale) et permet de réduire le problème du chevauchement des points. Pour mieux comprendre cet aspect, considérant la variable hwy. Cette variable contient beaucoup de valeurs identiques. Par exemple, la valeur 26 apparaît \(32\) fois (\(20\) fois dans la catégorie trans = 'auto' et \(12\) dans trans = 'manual').

sum(mpg$hwy == 26)
[1] 32

Cela sera impossible à voir sur un simple geom_point(), mais plus facile à percevoir avec l’argument alpha.

ggplot(mpg, aes(x = trans, y = hwy)) + geom_point(size = 4)
ggplot(mpg, aes(x = trans, y = hwy)) + geom_point(alpha = 0.1, size = 4)

Mapping global vs mapping local

Afin de créer des graphiques riches en informations, nous combinons souvent une variété de geom_<xxx>() et d’arguments aesthetics dans un même ggplot, comme dans l’exemple suivant (attention toutefois, trop d’information tue l’information):

ggplot(mpg, aes(x = displ, y = hwy, color = drv, linetype = trans)) +
  geom_point(size = 1.5) + geom_line(alpha = 0.3) + labs(color = "Drive train", linetype = "Transmission")

Lors de la création de telles combinaisons, il est important de choisir les bons arguments aesthetics et (surtout) de les placer au bon endroit. En effet, comme la fonction ggplot(), toutes les fonctions geom_<xxx>() ont l’argument mapping, qui sert à définir les correspondances entre les variables étudiées et les éléments esthétiques via aes(). Si cet argument est omis, sa valeur est héritée de celle de la fonction ggplot(). En revanche, s’il est fourni, sa valeur remplace celle héritée. En d’autres termes, un mapping déclaré dans ggplot() est global et s’applique à toutes les couches du graphe, alors qu’un mapping déclaré localement, à l’intérieur d’un geom_<xxx>(), ne s’applique qu’à ce dernier. Ainsi, le code ci-dessus est équivalent au code suivant

ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, color = drv), size = 1.5) +
  geom_line(aes(x = displ, y = hwy, color = drv, linetype = trans), alpha = 0.3)

Ce type d’écriture (relativement plus informatif) n’est pas recommandé car il contient des redondances et est plus difficile à éditer.

Pour mieux comprendre la différence entre les deux types de mapping (global et local), comparez le dernier graphique ci-dessus avec le suivant, dont le code est repris ci-dessous.

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(color = drv), size = 1.5) +
  geom_line(aes(linetype = trans), alpha = 0.3) + labs(color = "Drive train", linetype = "Transmission")

Sur le même principe, toutes les fonctions geom_<xxx>() possèdent l’argument data. Lorsque celui-ci est fourni dans ggplot() alors il s’applique, par défaut, à tous les geoms. Ainsi, nous pouvons reproduire notre premier ggplot, qui apparaît au tout début de cette section, avec le code suivant.

ggplot() + geom_point(data = mpg, mapping = aes(x = displ, y = hwy, color = drv), size = 1.5) +
  geom_line(data = mpg, mapping = aes(x = displ, y = hwy, color = drv, linetype = trans), alpha = 0.3)

Dans ce code, data = mpg est repris dans les deux fonctions geom, mais il est possible de spécifier des données différentes pour chaque geom. Voici un exemple.

# left
ggplot() + geom_point(data = mpg, aes(x = displ, y = hwy))
# right
ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(alpha = 0.1, color = "blue") +
  geom_point(data = subset(mpg, displ == 4), aes(x = displ + 0.1, y = hwy + 15), color = "red")

9.3 Fonctions géométriques

Outre geom_point() et geom_line(), que nous avons présentées et utilisées ci-dessus, il existe un grand nombre de fonctions similaires pour représenter/résumer les données en utilisant divers formats. Chaque fonction geom_<xxx>() dispose de sa propre fiche d’aide en ligne avec de nombreux exemples qui illustrent son utilisation; vous trouverez la liste complète des geom_<xxx>() et leurs fiches d’aide ici. Vous pouvez également visiter ggplot2tutor pour découvrir les fonctions geom et leurs arguments aesthetics de manière plus interactive.

Dans ce qui suit, nous allons passer rapidement en revue les fonctions les plus couramment utilisées. Vous pouvez cliquer sur le nom de chaque fonction pour accéder à sa fiche détaillée.

+ geom_jitter()

C’est la même chose que geom_point() sauf qu’elle permet d’écarter les points, verticalement et/ou horizontalement, en y ajoutant un bruit aléatoire, permettant ainsi de réduire le problème du chevauchement.

# left: horizontal and vertical noise
ggplot(mpg, aes(x = displ, y = "")) +  geom_jitter() + labs(y = NULL)
# right: vertical noise only
ggplot(mpg, aes(x = displ, y = "")) + geom_jitter(width = 0, height = 0.3) + labs(y = NULL)

+ geom_boxplot()
ggplot(mpg, aes(x = "", y = hwy))  + geom_boxplot() + labs(x = NULL)
ggplot(mpg, aes(x = trans, y = hwy)) + geom_boxplot(varwidth = TRUE)

geom_boxplot() accepte plusieurs autres arguments, comme, par exemple, width qui permet de contrôler la largeur des boîtes, varwidth = TRUE qui permet de varier la largeur des boîtes en fonction des effectifs de chaque classe et outlier.shape = NA qui supprime l’affichage des outliers; voir le Help pour plus d’info.

ggplot(mpg, aes(x = trans, y = hwy)) +
  geom_boxplot(width = 0.2, outlier.shape = NA, fill = NA, color = "darkblue") +
  geom_jitter(alpha = 0.2, size = 2, width = 0.1, height = 0) +
  stat_summary(fun = mean, shape = "+", size = 1, colour = "red")

Notez l’utilisation de l’argument aesthetic fill. En règle générale, fill définit la couleur avec laquelle un géom (ici, la boîte) peut être rempli, tandis que color définit la couleur avec laquelle un géom (ici, la boîte + les moustaches) peut être délimité. Notez également le recours à la fonction stat_summary(), utilisée ici pour calculer la moyenne par groupe et la représenter sous forme d’un “+”.

+ geom_smooth()

Cette fonction permet de tracer une courbe de tendance à partir d’un nuage de points \((x,y)\). Par défaut, cette courbe est accompagnée par un intervalle de confiance à \(95\%\), pour le retirer, il faut ajouter se = FALSE. L’argument method contrôle la méthode utilisée pour tracer la courbe. Par défaut, cet argument est fixé à “loess”, ce qui signifie que la fonction loess() (voir le Help) est appelée pour produire une courbe lissée non-paramétriquement. Parmi les autres méthodes qu’il est possible d’utiliser, on retrouve lm, pour la courbe classique des moindres carrés, et glm, pour une courbe estimée à l’aide de la méthode de régression linéaire généralisée.

p <- ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(aes(color = trans))
p + geom_smooth()                                                        # left
p + geom_smooth(aes(color = trans), method = "lm", se = FALSE)           # right

+ geom_histogram()
ggplot(mpg, aes(x = hwy)) + geom_histogram(color = "white")

Par défaut, geom_histogram() découpe les données en 30 classes (bins, en anglais). Vous pouvez contrôler ce paramètre avec l’argument binwidth. De nombreuses règles existent pour choisir une valeur plus ou moins optimale pour ce dernier, l’une des formules les plus utilisées est celle de Sturge que l’on peut calculer à l’aide de la fonction (de base) nclass.Sturges().

nclass.Sturges(mpg$hwy)
[1] 9
p <- ggplot(mpg, aes(x = hwy)) + geom_histogram(bins  = 9, color = "black", fill = "lightgray")
p + labs(title = "Histogramme des fréquences")
p + aes(y = after_stat(density)) + labs(title = "Histogramme des densités")

Ci-dessus, after_stat(density) permet d’accéder à la variable appelée density (càd fréquence relative de chaque classe divisée par sa largeur) créée automatiquement et stockée en interne par geom_histogram().

De façon général, la fonction after_stat() peut être utilisée pour accéder aux variables internes à ggplot créées pendant la phase dite “stat”, où certaines transformations sont appliquées aux données afin de pouvoir les visualiser (utiliser ggplot_build() pour inspecter les données transformées).

+ geom_density()
ggplot(mpg, aes(x = hwy)) + geom_density()

On peut aussi superposer un histogramme et une densité ou plusieurs densités dans un seul et même graphe.

ggplot(mpg, aes(x = hwy)) + geom_histogram(aes(y = after_stat(density)), bins = 9, alpha = 0.5) +
  geom_density(linewidth = 1)
ggplot(mpg, aes(x = hwy, color = trans, fill = trans)) + geom_density(linewidth = 1, alpha = 0.05) +
  labs(color = "Transmission", fill = "Transmission")

L’un des arguments les plus importants de geom_density() est bw (pour bandwidth), qui contrôle le lissage de la courbe. Par défaut, pour choisir un bandwidth “optimale”, geom_density() utilise la méthode dite de Scott, telle que fournie par la fonction (de base) bw.nrd().

Le graphique suivant illustre l’impact du bandwidth sur la courbe de densité estimée. Il illustre aussi l’utilité de faire un mapping à une constante pour créer facilement une légende (voir la section “Setting vs mapping”).

ggplot(mpg, aes(x = hwy)) +
  geom_density(aes(color = "Scote", linetype = "Scote")) +
  geom_density(bw = 0.5, aes(color = "0.5", linetype = "0.5")) +
  geom_density(bw = 5, aes(color = "5", linetype = "5")) +
  labs(color = "Bandwidth", linetype = "Bandwidth")

+ geom_violin()

Un graphique en violon (violin plot, en anglais) est constitué de deux graphiques de densité identique retournés et affichés en miroir l’un en face de l’autre.

ggplot(mpg, aes(x = trans, y = hwy)) + geom_violin(trim = FALSE)
ggplot(mpg, aes(x = trans, y = hwy)) +
  geom_violin(color = NA, fill = "lightgray", alpha = 0.5, trim = FALSE) +
  geom_boxplot(width = 0.1, varwidth = TRUE, outlier.shape = NA, fill = NA) +
  geom_jitter(width = 0.1, height = 0, alpha = 0.2)

+ geom_bar()
ggplot(mpg) + geom_bar(aes(x = trans)) + labs(title = "Fréquences")
ggplot(mpg, aes(x = trans)) + geom_bar(aes(y = after_stat(count) / sum(after_stat(count)))) +
  labs(title = "Proportions", y = "prop")

Pour créer un graphique, geom_bar() commence par calculer les effectives du facteur considéré (icimpg$trans). Ces effectives son données par le tableau suivant

tb <- xtabs(~trans, data = mpg) |> print()
trans
  auto manual 
   157     77 

Au lieu d’utiliser les données brutes, nous pouvons nous servir de ce tableau (tb) pour créer le barplot. Une telle tâche est plus facile à réaliser avec la fonction geom_col(). geom_col() représente les données telles quelles, sans aucune transformation au préalable. Elle est souvent utilisé lorsque l’on dispose déjà des statistiques que l’on souhaite afficher. Voici un exemple simple.

df <- data.frame(x = c("A", "B"), y = c(10, 20))
ggplot(df) + geom_col(aes(x, y))

Et voici le code pour reproduire les deux graphiques ci-dessus avec geom_col().

dtb <- data.frame(tb) |> print()
dtbp <- proportions(tb) |> data.frame() |> print()
   trans Freq
1   auto  157
2 manual   77
   trans  Freq
1   auto 0.671
2 manual 0.329
ggplot(dtb) + geom_col(aes(x = trans, y = Freq)) + labs(y = "count")
ggplot(dtbp) + geom_col(aes(x = trans, y = Freq)) + labs(y = "prop")

Pour représenter des fréquences croisées, on peut ajouter une variable catégorique au graphique via l’argument fill.

ggplot(mpg) + geom_bar(aes(x = trans, fill = cyl))

La base de ce graphique est le tableau de contingence suivant

xtabs(~ trans + cyl, data = mpg) |> addmargins(2)
        cyl
trans      4   5   6   8 Sum
  auto    41   2  56  58 157
  manual  40   2  23  12  77

L’argument position de geom_bar() permet d’indiquer comment les différentes barres doivent être positionnées. Par défaut, position = "stack" et il s’agit donc des barres “empilées” des effectives. Mais on peut préciser position = "dodge" pour des barres côte à côte des effectives, ou encore position = "fill" pour des barres empilées des pourcentages (conditionnelles).

ggplot(mpg) + geom_bar(aes(x = trans, fill = cyl), position = "dodge", show.legend = FALSE)
ggplot(mpg) + geom_bar(aes(x = trans, fill = cyl), position = "fill")

Notez l’utilisation de la commande show.legend = FALSE, qui a pour effet de supprimer la légende du en haut à gauche. Le graphique en haut à droite montre les proportions de cyl par catégorie trans. Ces proportions sont données dans le tableau suivant.

xtabs(~ trans + cyl, data = mpg) |> proportions(margin = "trans")
        cyl
trans         4      5      6      8
  auto   0.2611 0.0127 0.3567 0.3694
  manual 0.5195 0.0260 0.2987 0.1558
+ stat_function()

stat_function() permet de tracer la courbe d’une fonction donnée. L’argument args permet d’introduire les arguments de la fonction à représenter sous forme d’une liste.

ggplot() + xlim(-2, 2) + stat_function(fun = \(x) x^2)
ggplot() + xlim(-5, 5) + stat_function(fun = dnorm, args = list(mean = 0, sd = 2))

Par défaut, stat_function() trace une courbe, mais il est possible de préciser d’autres geoms. Voici deux exemples qui illustrent cela.

ggplot() + xlim(-5, 5) +
  stat_function(fun = dnorm, linewidth = 1.2, mapping = aes(color = "N(0,1)")) +
  stat_function(fun = dnorm, args = list(mean = 0, sd = 2), geom = "point", mapping = aes(color = "N(0,4)")) +
  labs(y = "densité", color = "Distribution")
ggplot() + xlim(-3, 3) +
  stat_function(fun = dnorm) +
  stat_function(fun = dnorm, xlim = c(-1, 1), geom = "area", fill = "gray", alpha = .3)

9.4 Faceting

Le faceting sert à découper un graphique en une figure à plusieurs panneaux, chaque panneau (facette) correspond à un sous-ensemble de données. ggplot propose deux fonctions pour faire du faceting : facet_grid() et facet_wrap(). Ces deux fonctions sont très similaires mais facet_grid() réalise une matrice de graphiques alors que facet_wrap() réalise une suite de graphiques. Les deux arguments principaux de ces fonctions sont : rows et cols pour facet_grid() et facets pour facet_wrap(). Le graphique suivant illustre ces deux fonctions et leurs arguments.

ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_grid(row = vars(drv), cols = vars(trans))
ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_wrap(facets = vars(trans, drv))

Par défaut, chaque facette est fournie avec un label qui montre la valeur du facteur de découpage. Par défaut aussi, les échelles des axes affichées sont les mêmes (fixes) pour toutes les groupes/facettes. Les arguments labeller et scales peuvent être évoqués pour modifier/contrôler ces deux éléments. scales peut prendre les valeurs: fixed, la valeur par défaut, freex_x pour “librer” l’axe des x, freex_y pour “librer” l’axe des y, et free pour “liberer” les deux. labeller = "label_both" affiche à la fois le nom et la valeur du facteur du découpage.

ggplot(mpg, aes(displ, hwy)) + geom_point() +
  facet_grid(row = vars(drv), cols = vars(trans), labeller = "label_both", scales = "free")

9.5 Programmer avec ggplot

Si vous vous retrouvez à écrire les mêmes lignes de code ggplot encore et encore pour créer des graphiques plus ou moins similaires, il peut être intéressant d’envisager d’autres voies. Considérons, à titre d’exemple, le code/plot suivant.

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(color = "blue", size = 2) +
  geom_smooth(method = "lm", se = FALSE, linewidth = 1) +
  facet_wrap(facets = vars(trans), labeller = "label_both") + theme_bw()

Si, par la suite, vous devez, par exemple, retaper geom_point(color = "blue", size = 2) + geom_smooth(linewidth = 1, se = FALSE) + theme_bw() à multiples reprises, alors sauvegardez ce bout de code dans un objet et réutilisez-le, comme ceci.

mytmp <- list(
  geom_point(color = "blue", size = 2),
  geom_smooth(method = "lm", se = FALSE, linewidth = 1),
  theme_bw()
)

ggplot(mpg, aes(x = cty, y = hwy)) + facet_wrap(facets = vars(drv), labeller = "label_both") + mytmp

Pour aller plus loin, nous pourrions écrire une fonction qui créerait le même type de graphique, tout en donnant à l’utilisateur la possibilité de modifier l’un ou l’autre des arguments. Voici un exemple

mytmp <- function(clr = "blue", sz = 2, ...) {
  list(
    geom_point(color = clr, size = sz),
    geom_smooth(method = "lm", se = FALSE, linewidth = 1),
    theme_bw(),
    facet_wrap(...)
  )
}

Notez l’utilisation de l’argument spécial ..., qui est généralement employé pour passer un nombre variable d’arguments à une fonction située à l’intérieur de la fonction que l’on appelle. Dans notre cas, la fonction mytmp() passe ... à la fonction facet_wrap(), ce qui offre une flexibilité supplémentaire.

ggplot(mpg, aes(x = cty, y = hwy)) + mytmp(facets = vars(drv))
ggplot(mpg, aes(x = displ, y = hwy)) + mytmp(clr = "red", facets = vars(trans), labeller = "label_both")

Nous pouvons aller encore plus loin en donnant à l’utilisateur la liberté de choisir les données/variables à représenter (càd les objets à mettre dans data, aes() et vars()). Dès lors, il semble logique de recourir à la syntaxe suivante (par exemple)

ggFun <- function(dt, x, y, gr) {
  ggplot(dt, aes(x, y)) + geom_point(color = "blue", size = 2) +
    geom_smooth(method = "lm", se = FALSE, linewidth = 1) +
    facet_wrap(vars(gr), labeller = "label_both") + theme_bw()
}

L’utilisateur peut alors taper ggFun(dt, x, y, gr), en remplaçant les arguments (dt, x, y, gr) par les éléments de son choix, par exemple ggFun(mpg, displ, hwy, trans), pour obtenir le plot souhaité. Malheureusement, cela ne fonctionne pas de cette manière.

La raison en est que les fonctions aes() et vars() utilisent une évaluation non standard appelée tidy-evaluation. C’est ce qui permet de simplifier le code que l’on tape, puisque nous n’avons pas besoin de répéter systématiquement le nom du data.frame que nous utilisons, càd que nous n’avons pas besoin d’écrire, par exemple, ggplot(mpg, aes(x = mpg$displ, y = mpg$hwy)) + geom_point(), mais simplement ggplot(mpg, aes(x = displ, y = hwy)) + geom_point(). Cependant, cette facilité d’utilisation crée des difficultés lorsqu’il s’agit de programmer avec ce type de fonctions. En effet, lorsque l’on tape ggFun(mpg, displ, hwy, trans), R est conçu pour cherche mpg, displ, hwy et trans dans l’environnement global, mais, à l’exception de mpg, ces objets ne s’y trouvent pas, ce qui génère des erreurs.

La façon la plus simple de remédier à ce problème, tout en gardant un style d’écriture simple, est d’utiliser l’opérateur {{, comme illustré dans le code suivant.

ggFun <- function(dt, x, y, gr) {
  ggplot(dt, aes({{ x }}, {{ y }})) + geom_point(color = "blue", size = 2) +
    geom_smooth(method = "lm", se = FALSE, linewidth = 1) +
    facet_wrap(vars({{ gr }}), labeller = "label_both") + theme_bw()
}

Cela vous permet d’appeler la fonction ggFun() avec les données/variables souhaités, comme ceci.

ggFun(iris, Sepal.Length, Sepal.Width, Species)

Pour en apprendre davantage sur ce sujet, vous pouvez consulter cette page.

9.6 Extensions ggplot

Il existe un grand nombre d’extensions ggplot. Consultez cette galerie pour voir une liste de ce qui est possible. Dans ce qui suit, nous allons en parcourir quelques-unes.

Créer des ggplots à l’aide esquisse

esquisse est un package R qui permet de créer des graphiques ggplot (de base) de façon interactive simple et rapide et fournit aussi la syntaxe à utiliser pour aboutir au même résultat.

Après l’avoir installé, vous pouvez commencer à l’utiliser à l’aide de la commande

esquisse::esquisser(<data>)

, où <data> est le nom du jeu de données à anlayser. Essayez en remplaçant <data> par le data.frame mpg. Alternativement, vous pouvez utiliser la commande esquisse::esquisser(), sans spécifier un data.frame, et introduire ce dernier par la suite. Dans ce cas, une fenêtre s’ouvrira, en superposition, vous invitant à choisir les données.

La liste des variables de data.frame apparaît en haut de la fenêtre de “Esquisse”, et vous pouvez les faire glisser dans les zones “X”, “Y”, “Fill”, “Color”, etc. pour créer des correspondances (mapping) entre ces éléments esthétiques et les variables choisies. Le graphique se met automatiquement à jour (cliquez sur l’image ci-dessus pour plus de détails) :

Image name

Par défaut, esquisse sélectionne le type de graphique le plus approprié selon la nature de vos variables. Mais vous pouvez choisir un autre type de graphique à l’aide de l’icône en haut à gauche (Auto).

Les menus en bas de l’interface vous permettent de personnaliser les titres, les thèmes, les couleurs et d’autres éléments affectant l’aspect global du graphique. Quand vous avez fini, si vous le souhaitiez, vous pouvez conserver le code R (généré automatiquement) en utilisant la rubrique “Code” en bas de la fenêtre de “Esquisse”. Pour plus d’information, consultez cette page et celle-ci.

Aménagement des graphes: package patchwork

Il est très facile de combiner plusieurs ggplots dans le même graphique à l’aide de patchwork. Ce package propose trois opérateurs simple: + pour réaliser une grille carrée, dans la mesure du possible, et la remplir ligne par ligne, | pour placer les plots les unes à côté des autres, et / pour les empiler. | et / sont souvent combinés pour construire toutes sortes d’agencement. La fonction plot_layout() permet de contrôler le remplissage des grills. L’option guides = "collect" permet, dans la mesure du possible, de ressembler les légendes en supprimant les doublons. Les deux exemples suivants illustrent certaines des nombreuses possibilités offertes par ce package.

Une fois le package patchwork chargé, tapez

ggplot(mpg, aes(x = displ, y = hwy)) + geom_point() +
  ggplot(mpg, aes(x = hwy)) + geom_histogram(bins  = 9, color = "white")

Le plus souvent, les ggplots sont stockés avant d’être combinés. Voici un exemple.

p1 <- ggplot(mpg, aes(x = displ, y = hwy, col = drv)) + geom_point()
p2 <- ggplot(mpg, aes(x = hwy)) + geom_histogram(bins  = 9, color = "white")
p3 <- ggplot(mpg, aes(x = drv, y = hwy, col = drv)) + geom_boxplot(show.legend = FALSE)
p4 <- ggplot(mpg) + geom_jitter(aes(x = displ, y = ""), width = 0, height = 0.2, alpha = 0.5) + labs(y = NULL)
p1 + p2 + p3 + p4 + plot_layout(guides = "collect")
# aletrntive synatx: (p1 | p2)/(p3 + p4) + plot_layout(guides = 'collect')

(p2 | p3) / p1 + plot_layout(guides = "collect")

Pour plus de détails consultez cette page.

Graphiques interactifs: packege plotly

La fonction ggplotly() du package plotly peut être utilisée pour transformer certains ggplots des graphiques web interactifs. Cette interactivité se traduit par (i) un graphique qui réagit au passage de la souris, et (ii) une barre d’outils qui apparaît dans le coin supérieur droit, permettant de zoomer et de se déplacer autour des axes, entre autres fonctions. Ce faisant, ggplotly() modifie certains éléments du graphique, tels que la taille des points, l’échelle des axes ou l’emplacement de la légende. Voici quelques exemples.

ggplotly(p1)
ggplotly(p2)
ggplotly(p3)

Il est également possible de créer des animations avec ggpotly. Pour ce faire, utilisez l’argument aesthetic frame. Cela produit un bouton “play” et un curseur pour contrôler l’animation. La fonction animation_opts() peut être utilisée pour contrôler la vitesse des pauses et des transitions (en millisecondes). Voici un exemple

p <- ggplot(mpg, aes(x = displ, y = hwy)) + geom_point()
ggplotly(p + aes(frame = class)) |> animation_opts(frame = 15000, transition = 500)


Pour plus de détails consultez cette page.

Ressources

Si vous souhaitez en savoir plus sur ggplot, les sources suivantes peuvent vous être utiles.