Un outil essentiel de l'exploration et l'analyse de données est la visualisation graphique. Le langage R dispose d'une myriade de fonctions à cet effet.
De nombreuses page web sont dédiées aux graphiques avec R. Une référence complète en libre accès (en anglais) est disponible ici.
Nous montrons ici comment réaliser les graphiques les plus courants qui vous seront utiles pour vos rapports dans ce cours et dans les autres !
Remarque. Avoir des graphiques présentables (lisibles, compréhensibles et légendés) est essentiel pour produire une analyse de données. Il vous arrivera souvent d'avoir oublié comment effectuer telle ou telle représentation en R. Vous pouvez vous servir de références de base (comme celle-ci dessus), mais n'hésitez surtout pas à vous aidez de recherches Internet ! Il est très improbable que le souci que vous ayez n'ait jamais été rencontré (et résolu) par quelqu'un d'autre.
La fonction plot()
est la fonction élémentaire de graphique en R. Elle, permet (entre autres) de faire des nuages de points à partir de vecteurs.
x <- seq(-5, 5, by = 0.2) # Création d'un vecteur x
y <- x ^ 2 + 3 * x - 2 # Vecteur y, de même longueur que x
plot(x, y) # Le premier élément donne l'abscisse, le second l'ordonnée
# Tracé des données de iris
plot(iris$Sepal.Length, iris$Sepal.Width)
Quand une des variables est catégorielle, R le detecte et fait un boxplot à la place d'un nuage de points.
plot(x = iris$Species, y = iris$Sepal.Length)
Pour faire un hitsogramme d'une variable quantitative, on utilise la fonction hist()
.
hist(iris$Sepal.Length) # On peut gérer le nombre de classes (voir help(hist))
Le package ggplot2
implémente une vision unifiée des graphiques en R (gg signifie grammar of graphics). Il est le principal package utilisé pour faire de la visualisation de données, vous trouverez donc énormément d'aide sur internet ainsi que beaucoup d'extensions (ggforce, ggridges, **ggthemes*...).
library(ggplot2)
L'idée derrière ggplot2
est qu'un graphique peut toujours être pensé en découplant les différentes informations qui le composent :
Toutes ces informations seront décomposées en plusieurs couches dans ggplot2, dans une syntaxe séquentielle.
Supposons que l'on veuille représenter le jeu de données iris
.
Commençons par créer un nuage de points comme précédemment.
ggplot(iris) # On spécifie les données
Comme on ne sait pas ce que l'on va afficher, on a simplement un rectangle vide.
Mais au fait, que veut on représenter ?
Par exemple, on veut représenter la largeur des sépales en fonction de leur longueur. On spécifie alors les variables d'intérêt (ou esthétiques) dans une fonction dédiée, la fonction aes()
.
ggplot(iris) + # On spécifie les données
aes(x = Sepal.Length, y = Sepal.Width) # On spécifie abscisses et ordonnées
La fonction aes()
peut prendre plusieurs arguments pour faire correspondre les données et les représnetasions. Les deux plus courants sont x
(l'abscisses) et y
(l'ordonnée). On utilisera plus bas d'autres arguments comme color
, fill
ou shape
.
L'échelle est apparue mais il faut encore dire à ggplot()
comment on veut représenter nos variables. Par exemple sous la forme de points. La forme de représentation sera toujours spécifiée dans une fonction commençant par geom_
:
ggplot(iris) + # On spécifie les données
aes(x = Sepal.Length, y = Sepal.Width) + # On spécifie abscisses et ordonnées
geom_point() # Sous forme de point, avec le prefixe geom_
Il est possible de spécifier d'autres paramètres esthétiques, comme la couleur ou la forme des points.
ggplot(iris) + # On spécifie les données
aes(x = Sepal.Length, y = Sepal.Width, # On spécifie abscisses et ordonnées
color = Species) + # L'esthétique de couleur sera donné par l'espèce
geom_point() # Sous forme de point, avec le prefixe geom_
Il est intéressant de mettre de la redondance dans la légende (la couleur et la forme sont toutes deux associées à l'espèce) pour faciliter la lecture aux personnes daltoniennes ou après une impression en noir et blanc.
ggplot(iris) + # On spécifie les données
aes(x = Sepal.Length, y = Sepal.Width, # On spécifie abscisses et ordonnées
color = Species, shape = Species) + # Forme et couleur données par l'espèce
geom_point() # Sous forme de point, avec le prefixe geom_
Avec le jeu de données mtcars
, représentez la consommation (sous la forme miles per gallon, colonne mpg
) en fonction du poids des véhicules (colonne wt
). Dans un second temps, vous modifierez la taille des points (esthétique size
) en fonction du nombre de cylindes (colonne cyl
).
ggplot(data = mtcars) # Complétez!
# Premier indice
# On précise les esthétiques avec + aes(x = ..., y = ...)
# Et on précise qu'on veut des points avec + geom_point()
# Second indice
# dans aes, ajoutez size = cyl
# Solution
ggplot(mtcars) +
aes(x = wt, y = mpg, size = cyl) +
geom_point()
geom_
On dispose évidemment de toute la palette graphique usuelle.
geom_boxplot()
permet de tracer des boîtes à moustaches.ggplot(iris) + # Données
aes(x = Species, y = Sepal.Length) + # Variables à représenter (esthétiques)
geom_boxplot() # Représentation
geom_histogram()
permet de tracer des histogrammes.ggplot(iris) + # Données
aes(x = Sepal.Length) + # Variables à représenter (esthétiques)
geom_histogram() # Représentation
geom_bar
permet de tracer des diagrammes en bâtons en comptant les effectifs à notre place.ggplot(carData::TitanicSurvival) + # Données (passagers du Titanic)
aes(x = passengerClass) + # Variables à représenter (esthétiques)
geom_bar() # Représentation (l'ordonnée est le nombre dans chaque classe)
geom_col()
permet de tracer des diagrammes en bâtons dont on connaît déjà la hauteur.library(dplyr)
mtcars %>%
mutate(ID = row_number()) %>% # Crée une variable correspondant au numéro de l'observation
ggplot() +
aes(x = ID, y = hp) + # On regarde la puissance de chaque voiture
geom_col() # sous la forme d'un diagramme en bâton
Pour représenter les comptages avec geom_col
, on doit d'abord calculer l'effectif dans chaque groupe, via la fonction count()
, avant de l'assigner à l'axe y
.
count(mtcars, gear) # Rappel : count() compte le nombre d'occurence
gear n
1 3 15
2 4 12
3 5 5
Une fois la hauteur de chaque bâton obtenue, on utilise geom_col()
.
mtcars %>% # On manipule le data.frame en amont
count(gear) %>%
ggplot() + # On fournit à ggplot le nombre d'occurence tel quel
aes(x = gear, y = n) + # chaque barre sera sur gear et aura n comme hauteur
geom_col(color = "black")
Ici, on a utilisé l'opérateur pipe %>%
pour effectuer une transformation du data.frame
sans avoir besoin de l'assigner à une nouvelle variable.
Représentez l'histogramme de la distribution de la largeur des sépales (colonne Sepal.Width
) des iris. Dans un second temps, vous ne mettrez que 10 bins (option bins = ...
dans geom_histogram
). Ensuite, vous colorerez les histogrammes en fonction de l'espèce d'iris (en utilisant l'esthétique fill = Species
dans l'aes
).
ggplot(iris)
# Solution
ggplot(iris) + # Données
aes(x = Sepal.Width, fill = Species) + # Variables à représenter (esthétiques)
geom_histogram(bins = 10) # Représentation
# Si on veut éviter la superposition, on pourra ajouter position = "dodge"
Evidemment, on peut représenter les couleurs selon les goûts de chacun.
# col est la couleur du contour, fill est la couleur de remplissage
ggplot(iris) + # Données
aes(x = Sepal.Length) + # Variables à représenter (esthétiques)
geom_histogram(fill = "grey", col = "black") # Représentation
Ces couleurs ne dépendent pas des données, c'est pour cela qu'elles ne sont pas précisées dans la fonction aes()
mais directement dans le geom_
.
Ainsi, pour les passagers du Titanic, on peut regarder les effectifs par classe et par sexe.
ggplot(carData::TitanicSurvival) + # Données (passagers du Titanic)
aes(x = passengerClass, fill = sex) + # Variables à représenter (esthétiques)
geom_bar() # Représentation (l'ordonnée est le nombre dans chaque classe)
Cette représentation pouvant être faite côte à côte.
ggplot(carData::TitanicSurvival) + # Données (passagers du Titanic)
aes(x = passengerClass, fill = sex) + # Variables à représenter (esthétiques)
geom_bar(position = "dodge") # Position relative des bâtons
Un graphique présentable se doit d'avoir un titre et des légendes lisibles et compréhensibles. Par exemple, dans un rapport, on ne voudra pas voir l'axe des abscisses légendé par Sepal.Length
(d'autant moins si le rapport est en français). Ceci se fait avec la fonction labs()
qui prend comme argument des noms (chaînes de caractères) associés aux esthétiques.
ggplot(iris) + # Données
aes(x = Sepal.Length, y = Sepal.Width, color = Species) + # Esthétiques
geom_point() + # Représentation
labs(x = "Longueur des sépales", y = "Largeur des sépales",
color = "Espèce", # Nom de chacun des axes : abscisses, ordonnées et couleurs
title = "Taille des sépales de différentes espèces d'iris") # Titre
Ainsi, tout paramètre esthétique présent dans aes()
doit avoir son alter ego dans labs()
.
Dans le cas du Titanic, le tableau de données est en anglais. Quand on souhaite faire la représentation dans un rapport en français, on voudra, pour les besoins du graphiques, écrire, les choses en français. Pour cela, il est souvent utile de renommer les facteurs (voir la Session 1).
Faites-le avant le graphique, grâce au %>%
!
carData::TitanicSurvival %>% # Données initiales
# mutate() permet de modifier une colonne, ici sex et passengerClass
mutate(sex = factor(sex, labels = c("Femme", "Homme")), # Renommage des modalités
passengerClass = factor(passengerClass,
labels = c("1ère", "2ème", "3ème"))) %>%
ggplot() + # On va représenter ces données modifiées
aes(x = passengerClass, fill = sex) + # Variables à représenter (esthétiques)
geom_bar(position = "dodge") + # Position relative des bâtons
labs(x = "Classe de voyage", y = "Effectif", fill = "Sexe", # Titre des axes
title = "Répartition des passagers du Titanic") # Titre du graphique
Dans un esprit similaire à celui du renommage, il arrive parfois qu'une variable catégorielle soit codée comme numérique. La représentation graphique est alors mauvaise.
ggplot(mtcars) +
aes(x = hp, y = mpg, size = cyl, # La taille des points est une esthétique
color = am) + # am vaut soit 0 soit 1
geom_point() + # mais est considéré comme continu !
labs(x = "Puissance", y = "Consommation (Miles/Gallon)",
size = "Nombre de cylindres", color = "Transmission",
title = "Consommation des véhicules")
Il est alors nécessaire de la repasser en facteur, on va manipuler le data.frame
en amont avec dplyr.
mtcars %>%
mutate(am = factor(am, # On transforme am en facteur
labels = c("Automatique", "Manuelle"))) %>% # Noms des niveaux
ggplot() + # Les données transformées servent d'entrée à ggplot
aes(x = hp, y = mpg, size = cyl, color = am) + # Esthétiques
geom_point() + # Représentation
labs(x = "Puissance", y = "Consommation (Miles/Gallon)",
size = "Nombre de cylindres", color = "Transmission",
title = "Consommation des véhicules")
On a ici quatre "axes" sur lesquels sont représentés les données : l'abscisse, l'ordonnée, la couleur et la taille. On aurait pu également rajouter une autre variable sur la forme des points mais il faut faire attention à ne pas surcharger les graphiques.
Il est possible d'avoir une fenêtre graphique par modalité d'une variable qualitative (ici l'espèce) avec facet_grid()
ou facet_wrap()
.
Un graphique par colonne...
ggplot(iris) +
aes(x = Sepal.Length, fill = Species) + # Le remplissage dépend de l'espèce
geom_histogram(color = "black", show.legend = FALSE) + # Le contour est commun
# On ne montre pas la légende
facet_grid(Species ~ .) + # Species en ligne, le point signifie l'absence de variable en colonne
labs(x = "Longueur des sépales", y = "Effectif",
title = "Distribution des longueurs de sépale par espèce d'iris")
... ou par ligne !
ggplot(iris) +
aes(x = Sepal.Length, fill = Species) + # Le remplissage dépend de l'espèce
geom_histogram(color = "black", show.legend = FALSE) + # Le contour est commun
# On ne montre pas la légende
facet_grid(. ~ Species) + # Species en ligne, le point signifie l'absence de variable en ligne
labs(x = "Longueur des sépales", y = "Effectif",
title = "Distribution des longueurs de sépale par espèce d'iris")
Pour des raison esthétiques ou d'économie d'encre, on peut changer le thème de fond.
ggplot(iris) +
aes(x = Petal.Length, y = Petal.Width, color = Species) +
geom_point() +
theme_bw() # Thème blanc
ggplot(iris) +
aes(x = Petal.Length, y = Petal.Width, color = Species) +
geom_point() +
theme_minimal() # Le même mais sans le cadre
ggplot(iris) +
aes(x = Petal.Length, y = Petal.Width, color = Species) +
geom_point() +
ggthemes::theme_economist() # Le thème utilisé par The Economist
On peut changer le thème qui sera appliqué par défaut via theme_set()
.
theme_set(theme_minimal())
Parfois, la légende est redondante avec l'axe. On peut la retirer dans les options de theme()
.
ggplot(iris) +
aes(x = Species, y = Sepal.Width, fill = Species) + # Le remplissage se choisit avec fill
geom_boxplot() +
theme(legend.position = "none")
Ou on peut aussi la mettre dans le graphique pour gagner de la place.
ggplot(iris) +
aes(x = Petal.Width, y = Petal.Length, color = Species) +
geom_point() +
theme(legend.position = c(0.8, 0.2))
ggplot2 fonctionnant en couches, il est possible de combiner des geom_
, en les assemblant avec des +
.
ggplot(iris) +
aes(x = Sepal.Length, y = Petal.Length, color = Species) +
geom_point() +
geom_vline(xintercept = 7) +
geom_hline(yintercept = 3, color = "red", linetype = "dashed")
Il est également possible de combiner plusieurs data.frame
. Ceci peut être utilisé pour ajouter les moyennes sur des boîtes à moustaches par exemple.
iris_mean <- # On calcule les moyennes
iris %>%
group_by(Species) %>%
summarise(Mean = mean(Petal.Width))
`summarise()` ungrouping output (override with `.groups` argument)
ggplot(iris) +
aes(x = Species, y = Petal.Width) +
geom_boxplot() + # On trace les boxplots
geom_point(data = iris_mean, mapping = aes(y = Mean), # On ajoute le data.frame des moyennes
color = "red", size = 4, shape = "X") # Représentées par des croix rouges
cowplot
cowplot est un package qui permet d'arranger des graphiques sans lien entre eux dans une même image.
p1 <-
ggplot(iris) +
aes(x = Sepal.Width, y = Sepal.Length) +
geom_point()
p2 <-
ggplot(iris) +
aes(x = Petal.Width, y = Petal.Length) +
geom_point()
cowplot::plot_grid(p1, p2)