4.6 Différents moteurs graphiques
Depuis le début, l’ensemble des graphiques que nous vous avons proposés utilise la fonction chart()
du package {chart}. Cependant, il ne s’agit pas de la seule fonction permettant de réaliser des graphiques dans R, loin de là. En fait {chart} est tout récent et a été développé pour homogénéiser autant que possible les graphiques issus de trois moteurs graphiques différents : {ggplot2}, {lattice} et les graphiques de base. La fonction chart()
a d’autres avantages également :
- Un thème par défaut qui est le plus proche possible d’un rendu typique d’une publication scientifique.
- La possibilité d’utiliser l’interface formule avec {ggplot2}.
- La cohérence des objets graphiques obtenus qui peuvent tous être combinés en une figure composée, même si ils sont produits avec des moteurs graphiques différents.
- Un libellé automatique des axes et autres éléments du graphique en fonction des attributs
label
etunits
des variables (pour l’instant, seulement les graphiques de type {ggplot2}).
# # A data.table: 421 x 19
# # Language: FR
# origin diameter1 diameter2 height buoyant_weight weight solid_parts
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 Pêcherie 9.9 10.2 5 NA 0.522 0.478
# 2 Pêcherie 10.5 10.6 5.7 NA 0.642 0.589
# 3 Pêcherie 10.8 10.8 5.2 NA 0.734 0.677
# 4 Pêcherie 9.6 9.3 4.6 NA 0.370 0.344
# 5 Pêcherie 10.4 10.7 4.8 NA 0.610 0.559
# 6 Pêcherie 10.5 11.1 5 NA 0.610 0.551
# 7 Pêcherie 11 11 5.2 NA 0.672 0.605
# 8 Pêcherie 11.1 11.2 5.7 NA 0.703 0.628
# 9 Pêcherie 9.4 9.2 4.6 NA 0.413 0.375
# 10 Pêcherie 10.1 9.5 4.7 NA 0.449 0.398
# # … with 411 more rows, and 12 more variables: integuments <dbl>,
# # dry_integuments <dbl>, digestive_tract <dbl>, dry_digestive_tract <dbl>,
# # gonads <dbl>, dry_gonads <dbl>, skeleton <dbl>, lantern <dbl>, test <dbl>,
# # spines <dbl>, maturity <int>, sex <fct>
4.6.1 {ggplot2}
Le moteur graphique {ggplot2} est écrit pas Hadley Wickham, un personnage emblématique de la “révolution tidyverse” (même si ggplot est antérieur et n’utilise pas la syntaxe commune aux packages tidyverse) qui propose une surcouche moderne au-dessus de R. {ggplot2} implémente une “grammaire graphique” particulièrement puissante et flexible, proposée et popularisée par le statisticien Leland Wilkinson. Par défaut, chart()
crée en réalité un graphique {ggplot2} adapté. Voici la version {ggplot2} standard du même graphique représenté à la Fig. 4.23 :
En comparant les Figs. 4.23 et 4.24 (en faisant abstraction des instructions R utilisées pour l’instant), plusieurs éléments sautent immédiatement aux yeux :
Le thème par défaut de {ggplot2} est très reconnaissable avec un quadrillage blanc sur fond gris clair. On aime ou on n’aime pas, mais il est évident que (1) ce n’est pas une présentation “standard” d’un graphique scientifique, et (2) le thème tord un peu le cou à une règle importante pour réaliser un graphique de qualité : minimiser la quantité d’“encre” nécessaire pour représenter un graphique, autrement dit, plus le graphique est simple et sobre, mieux c’est. Le thème par défaut de
chart()
respecte mieux tout ceci13.La taille des caractères est légèrement plus grande dans la Fig. 4.23 réalisée avec
chart()
(surtout pour les nombres sur les axes). Le manque de lisibilité des parties textuelles dans un graphique est un défaut fréquent, dépendant de la résolution et de la taille de reproduction du graphique dans le document final. Le choix dechart()
recule un peu ce risque.chart()
est capable d’aller lire les métadonnées (libellés en français et unités des variables) et les utilise automatiquement pour proposer des libellés corrects et complets des axes par défaut.ggplot()
ne peut pas le faire, et il faut utiliser la fonctionlabs()
pour l’indiquer manuellement.
De manière générale, par rapport à ggplot()
,
chart()
a été conçu pour produire le graphique le plus
proche d’un rendu final impeccable avec tous les paramètres par
défaut.
Quelques règles simples vous permettent de passer des instructions ggplot()
à chart()
et vice versa14 :
On peut toujours remplacer
ggplot()
parchart()
dans les instructions R (à condition que le package {chart} soit chargé bien sûr, par exemple viaSciViews::R
). Dans ce cas, le thème par défaut diffère, et le libellé automatique des axes (non disponible avecggplot()
) est activé.Avec
chart()
on peut utiliseraes()
pour spécifier les “esthétiques” (éléments à visualiser sur le graphique) comme pourggplot()
, mais on peut aussi utiliser une interface formule plus compacte. Cette interface formule rapproche la versionchart()
des graphiques {ggplot2} d’un autre moteur de graphique dans R : {lattice}.Outre les esthétiques classiques
x
ety
, l’interface formule dechart()
permet d’en inclure d’autres directement dans la formule à l’aide d’opérateurs spécifiques%<esth>%=
. Par exemple,aes(x = weight, y = height, col = origin)
dans la Fig. 4.24 se traduit en la formule plus conciseheight ~ weight %col=% origin
avecchart()
(notez la position inversée dex
ety
dans la formule puisqu’on ay ~ x
). Tous les esthétiques de {ggplot2} sont supportés de cette manière.Partout où
aes()
est utilisé pour les instructions {ggplot2}, on peut utiliser à la placef_aes()
et y spécifier plutôt une formule de typechart()
.Avec
ggplot()
les facettes doivent être spécifiées à l’aide defacet_XXX()
. À condition d’utiliserchart()
, il est possible d’inclure les spécifications des facettes les plus utilisées directement dans la formule en utilisant l’opérateur|
. Cette façon de procéder est identique à ce qui se fait dans {lattice} (voir plus loin).
Le point (5) mérite une petite démonstration pour comparaison :
a <- chart(data = urchin, height ~ weight | origin) +
geom_point()
b <- ggplot(data = urchin, mapping = aes(x = weight, y = height)) +
geom_point() +
facet_grid( ~ origin)
combine_charts(list(a, b))
Enfin, pour ceux qui n’aiment pas la notation utilisant le +
(car elle fait trop penser à une addition, ce qu’elle ne fait pas ici), vous pouvez aussi utiliser la fonction gg()
du package {chart}. Cette fonction transforme toutes les commandes {ggplot2} / {chart} qui doivent être combinées à l’aide de +
en commandes pouvant être combinées à l’aide de l’opérateur de pipe de R de base |>
. Ce dernier opérateur est typiquement utilisé pour composer une instruction complexe à l’aide de plusieurs instructions simples (les blocs de construction). Il est donc plus logique ici. De l’aveu même de son auteur, {ggplot2} aurait utilisé |>
à la place de +
si cet opérateur existait à l’époque où ggplot a été conçu. Donc, gg()
vient en quelque sorte corriger le tir. Pour utiliser gg()
, vous remplacez le +
par |>
, et vous débutez le nom de votre fonction {ggplot2} par gg$
. C’est tout. Don,c, vous écrirez :
De plus, vous bénéficiez pleinement de l’aide via la complétion de RStudio avec gg()
. En effet, lorsque vous avez entré gg$
dans l’éditeur ou à la fenêtre console de RStudio, une liste apparaît avec toutes les options possibles.
Exercez-vous
Afin de vous exercer à réaliser des graphiques
chart()
/ggplot()
, proposez trois graphiques
inédits (qui n’ont pas été vu jusqu’ici) dans vos différents projets
GitHub Classroom. Employez par exemple les liens suivants pour vous
inspirer :
Pour en savoir plus
Chapitre Data visualisation de R for Data Science qui utilise
ggplot()
.Site rassemblant des extensions pour ggplot2
La suite de cette section est facultative : elle est importante pour comprendre les différents types de graphiques que vous allez rencontrer avec R. Cependant, si vous vous cantonnez aux graphiques chart()
/ggplot()
vous pouvez déjà réaliser énormément de visualisations différentes sans forcément connaitre les autres moteurs graphiques existants dans R.
4.6.2 {lattice}
Autant {ggplot2} est complètement modulable en ajoutant littéralement à l’aide de l’opérateur +
des couches successives sur le graphique, autant {lattice} vise à réaliser les graphiques en une seule instruction. {lattice} utilise également abondamment l’interface formule pour spécifier les variables à utiliser dans le graphique. La version {lattice} du graphique d’exemple est présentée à la Fig. 4.27.
Et voici la version chart()
utilisant le moteur {lattice}. Notez la façon d’appeler la fonction xyplot()
de {lattice} via chart$xyplot()
:
theme_sciviews_lattice(n = 2)
a <- chart$xyplot(height ~ weight, data = urchin, groups = origin,
auto.key = list(space = "right", title = "Origine", cex.title = 1, columns = 1),
ylab = "Hauteur du test [mm]", xlab = "Masse totale [g]",
par.settings = list(superpose.symbol = list(col = scales::hue_pal()(2))))
b <- chart(data = urchin, height ~ weight %col=% origin) +
geom_point()
combine_charts(list(a, b))
La quantité d’instructions nécessaires pour rendre la version {lattice} proche de la version {ggplot2} devrait disparaître dans les prochaines versions de chart()
. Un autre objectif est aussi de gommer le plus possible les différences entre les rendus des différents moteurs de graphiques R, et en particulier entre {ggplot2} et {lattice}. Comparez la Fig. 4.28A avec la Fig. 4.27 pour apprécier le gain déjà obtenu en matière d’homogénéisation.
Par rapport à {ggplot2}, les graphiques {lattice} sont moins flexibles du fait qu’ils doivent être spécifiés en une seule instruction. Cependant, ils sont beaucoup plus rapides à générer (appréciable quand il y a beaucoup de points à tracer) ! {lattice} offre également quelques types de graphiques non supportés par {ggplot2} comme les graphiques en 3D à facettes, par exemple.
Voici un graphique à facettes réalisé avec chart()
et le moteur {lattice}. Notez que la formule utilisée est identique à celle employée pour la version {ggplot2} avec chart()
.
chart$xyplot(data = urchin, height ~ weight | origin,
scales = list(alternating = 1),
xlab = "Masse totale [g]", ylab = "Hauteur du test [mm]")
Mis à part les instructions additionnelles encore nécessaires dans cette version de chart()
, l’appel et le rendu sont très similaires par rapport à la version {ggplot2} du même graphique avec chart()
:
chart$xyplot(data = urchin, height ~ weight | origin,
scales = list(alternating = 1),
ylab = "Hauteur du test [mm]", xlab = "Masse totale [g]")
Vous noterez que pour réaliser un graphique {lattice} à l’aide de chart()
, vous devez rajouter $nom_de_function_lattice
après chart$
. Aussi, le thème spécifique SciViews et les labels et unités automatiques ne sont pas encore supportés. Les graphiques {lattice} ne supportant pas l’opérateur +
pour ajouter des couches comme pour {ggplot2}, vous devez spécifier l’ensemble des options comme arguments de la fonction chart$fun()
. Cela peut devenir pénible s’il y en a beaucoup. Toutefois {lattice} peut rendre d’énormes services pour des graphiques très compliqués, grâce à sa vitesse nettement supérieure à {ggplot2}.
4.6.3 Graphiques de base
Comme son nom le suggère, le moteur graphique de base est celui qui est implémenté de manière native dans R. Il est donc utilisé un peu partout. Il est vieillissant et est plus difficile à manipuler que {ggplot2} certainement, et même que {lattice}. Néanmoins, il est très flexible et rapide, et encore très utilisé… mais son rendu par défaut n’est plus vraiment au goût du jour. Voici notre graphique d’exemple rendu avec le moteur graphique R de base :
plot(urchin$weight, urchin$height,
col = c("red", "darkgreen")[urchin$origin], pch = 1)
legend(x = 80, y = 10, legend = c("Culture", "Pêcherie"),
col = c("red", "darkgreen"), pch = 1)
Vous rencontrerez très fréquemment la fonction plot()
. C’est une fonction dite générique dont le comportement change en fonction de l’objet fourni en premier argument. Ainsi, elle réalise le graphique le plus pertinent à chaque fois en fonction du contexte. Notez tout de suite les instructions un peu confuses nécessaires pour spécifier la couleur souhaitée en fonction de l’origine des oursins. Le moteur graphique de base ne gère pas automatiquement des aspects plus complexes du graphique, tels que le positionnement d’une légende. Donc, à moins d’avoir prévu la place suffisante avant de tracer le graphique, nous ne pouvons que l’inclure à l’intérieur du cadre du graphique dans un second temps à l’aide de la fonction legend()
. Comme cette dernière ne comprend rien à ce qui a été réalisé jusqu’ici, il faut lui respécifier les couleurs, formes et tailles de points utilisés ! C’est un des aspects pénibles du moteur graphique R de base.
Voici maintenant une version chart()
de ce graphique de base :
chart$base({
par(mar = c(5.1, 4.1, 4.1, 6.1))
plot(urchin$weight, urchin$height,
col = scales::hue_pal()(2)[urchin$origin], pch = 19, cex = 0.8,
xlab = "Masse totale [g]", ylab = "Hauteur du test [mm]")
legend(x = 105, y = 20, legend = c("Culture", "Pêcherie"), title = "Origine",
col = scales::hue_pal()(2), pch = 19, bty = "n", cex = 0.8, y.intersp = 2)
})
Vous ne le voyez pas dans le bookdown, mais vous le réaliserez si
vous utilisez ce genre de code dans vos propres documents R Markdown :
le graphique est en réalité généré deux fois : une première fois dans un
format propre aux graphiques R de base, et ensuite, il est traduit en
une forme compatible avec les autres graphiques {ggplot2} et {lattice}
(et au passage, il gagne la grille en traits grisés). Dans le chunck,
nous devons spécifier fig.keep = 2
si nous voulons éviter
d’imprimer la première version dans le rapport lorsqu’on utilise
chart$base()
.
Pour l’instant, le seul avantage de chart()
avec les graphiques de base est qu’il les convertit en une forme combinable avec les autres graphiques dans une figure composite (sinon, ce n’est pas possible). À part cela, il faut fournir à chart$base()
tout le code nécessaire pour tracer et personnaliser le graphique. Comme on peut le voir sur cet exemple, cela demande une quantité considérable de code. C’est aussi un autre aspect pénible de ce moteur graphique : il est très flexible, mais l’interface n’est pas optimale. Pour finir, les graphiques de base ont plus de mal avec les facettes, mais ils peuvent quand même générer les versions les plus simples, par exemple à l’aide de la fonction coplot()
qui accepte une formule très similaire à ce que nous avons employé jusqu’ici, mais avec un rendu différent :
À l’issue de cette comparaison, vous pourrez décider du moteur graphique que vous préférerez utiliser. Dans le cadre de ce cours, nous n’utiliserons en tous cas que quasi exclusivement des graphiques {ggplot2} créés à l’aide la fonction chart()
.
Pour en savoir plus
Comparaison de lattice et ggplot2. Cette page fait aussi référence à un ensemble de graphiques différents générés en {lattice} et en {ggplot2} pour comparaison (en anglais).
Divers exemples de graphiques réalisés avec le moteur de base
ggplot2 comparé aux graphiques R de base. Un point de vue différent d’un utilisateur habitué aux graphiques R de base (en anglais).
Notez que plusieurs thèmes existent dans ggplot2. Il est facile d’en changer et de les personnaliser… mais c’est toujours appréciable d’avoir un rendu impeccable dès le premier essai.↩︎
Étant donné l’abondante littérature écrite sur {ggplot2}, il est utile de pouvoir convertir des exemples {ggplot2} en graphiques
chart()
, si vous êtes convaincu par cette nouvelle interface.↩︎