Ce document accompagne la présentation Visualisation_ggplot2_RaQ2019.pdf.

Instructions

  • Ouvrir ce document en RStudio (version 1.0 ou plus récente). Il s’agit d’un fichier R Markdown.

  • Si les accents s’affichent mal, allez dans le menu « File > Reopen with Encoding… », sélectionnez « UTF-8 », puis cliquez sur « OK ».

  • Cliquez sur le petit triangle vert en haut à droite d’un bloc de code pour faire rouler le code qu’il contient.

print("Ceci est un test")
## [1] "Ceci est un test"
  • Si le résultat produit par le code ne s’affiche pas directement dans le fichier (s’il s’affiche plutôt dans la console R), veuillez :

    • vous assurer que « Chunk Output Inline » est sélectionné dans les options du fichier (roue d’engrenage dans la barre dans le haut du fichier);

    • si ça ne fonctionne toujours pas, allez dans le menu « Tools > Global Options… > R Markdown » et cochez « Show output inline for all R Markdown documents », puis cliquez sur « OK ».

  • Si RStudio plante (ne répond plus), c’est parce que vous utilisez une version de RStudio qui comporte malheureusement un bogue. Mettez à jour votre version de RStudio par la suivante : https://s3.amazonaws.com/rstudio-ide-build/desktop/windows/RStudio-1.2.1518.exe (Source : https://github.com/rstudio/rstudio/issues/4759).

Remarque : Vous pouvez aussi consulter le fichier HTML obtenu de la compilation du présent fichier R Markdown \(\rightarrow\) Visualisation_ggplot2_RaQ2019_Exemples.html

Données utilisées dans les exemples

Data frame quakes du package datasets (chargé par défaut lors de l’ouverture de session), auquel on ajoute deux variables catégoriques comme suit :

quakes$magFactor <- factor(floor(quakes$mag))               # classe de magnitude
quakes$region <- factor(quakes$long >= 175, labels = c("Ouest", "Est"))  # région
str(quakes)
## 'data.frame':    1000 obs. of  7 variables:
##  $ lat      : num  -20.4 -20.6 -26 -18 -20.4 ...
##  $ long     : num  182 181 184 182 182 ...
##  $ depth    : int  562 650 42 626 649 195 82 194 211 622 ...
##  $ mag      : num  4.8 4.2 5.4 4.1 4 4 4.8 4.4 4.7 4.3 ...
##  $ stations : int  41 15 43 19 11 12 43 15 35 19 ...
##  $ magFactor: Factor w/ 3 levels "4","5","6": 1 1 2 1 1 1 1 1 1 1 ...
##  $ region   : Factor w/ 2 levels "Ouest","Est": 2 2 2 2 2 2 1 2 2 2 ...

Premiers pas avec ggplot2

Il faut d’abord charger le package ggplot2.

library(ggplot2)

Voici notre premier exemple.

ggplot(data = quakes) + geom_point(mapping = aes(x = mag, y = stations))

Références :

Syntaxes équivalentes

On peut initialiser un graphique, que l’on stocke dans un objet.

monGraph <- ggplot(data = quakes)

Puis lui ajouter des couches.

monGraph <- monGraph + geom_point(mapping = aes(x = mag, y = stations))

On peut observer le contenu de l’objet.

str(monGraph)
summary(monGraph)
## data: lat, long, depth, mag, stations, magFactor, region [1000x7]
## faceting: <ggproto object: Class FacetNull, Facet, gg>
##     compute_layout: function
##     draw_back: function
##     draw_front: function
##     draw_labels: function
##     draw_panels: function
##     finish_data: function
##     init_scales: function
##     map_data: function
##     params: list
##     setup_data: function
##     setup_params: function
##     shrink: TRUE
##     train_scales: function
##     vars: function
##     super:  <ggproto object: Class FacetNull, Facet, gg>
## -----------------------------------
## mapping: x = ~mag, y = ~stations 
## geom_point: na.rm = FALSE
## stat_identity: na.rm = FALSE
## position_identity

Et enfin produire un graphique à partir de l’objet, simplement en l’affichant.

monGraph # ou print(monGraph)

Pour enregistrer le graphique dans un fichier externe, on utilise la fonction ggsave.

ggsave(file = "quakes_stations_vs_mag.png", plot = monGraph)

Référence :

Ajout d’un titre et de noms d’axes

ggplot(data = quakes) + 
  geom_point(mapping = aes(x = mag, y = stations)) +
  labs(title = "1000 séismes près de Fiji") +          # ou ggtitle("...") +
  labs(x = "magnitude du séisme") +                    # ou xlab("...") +
  labs(y = "nombre de stations rapportant le séisme")  # ou ylab("...")

Vous avez envie de centrer le titre du graphique ? Voici comment faire.

ggplot(data = quakes) + 
  geom_point(mapping = aes(x = mag, y = stations)) +
  labs(title = "1000 séismes près de Fiji") +
  theme(plot.title = element_text(hjust = 0.5)) +     # permet de centrer le titre du graphique
  labs(x = "magnitude du séisme") +
  labs(y = "nombre de stations rapportant le séisme")

Références :

Ajout de variables

Variable associée à une propriété visuelle autre qu’un axe

Le graphique précédent représente deux variables. Ajoutons une troisième variable au graphique, qui fera varier la couleur des points. Si la palette de couleur utilisée par défaut ne nous plaît pas, on peut la changer.

scatterplot <- ggplot(data = quakes) + 
  geom_point(mapping = aes(
    x = mag, 
    y = stations, 
    colour = depth  # permet de faire varier la couleur des points en fonction de la var. depth
  )) +
  labs(title = "1000 séismes près de Fiji") +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(x = "magnitude du séisme") +
  labs(y = "nombre de stations rapportant le séisme") +
  labs(colour = "profondeur") +                     # permet de modifier le titre de la légende
  scale_colour_continuous(type = "viridis")   # permet d'utiliser la palette de couleur viridis

scatterplot

Référence :

Graphiques côte à côte selon les niveaux d’une variable catégorique

Ajoutons maintenant une quatrième variable au graphique, celle-ci catégorique, en créant des graphiques disjoints selon le niveau de la variable.

scatterplot + 
  facet_wrap(facets = ~ region)   # permet de créer un panneau par niveau de la variable region

Référence :

Création de graphiques côte à côte

Nous pourrions même facilement ajouter une cinquième variable en créant une grille de graphiques côte à côte (panneaux) comme suit.

scatterplot +
  facet_grid(magFactor ~ region)  # ou facet_grid(rows = vars(magFactor), cols = vars(region))

Référence :

Modification des libellés des niveaux d’une variable catégorique

Les libellés des niveaux d’un facteur peuvent être modifiés ainsi.

# Création d'un vecteur faisant office de « lookup table », contenant l'association entre 
# - les niveaux d'un facteur (nom des éléments dans le vecteur) et
# - leurs étiquettes à afficher dans le graphique (éléments du vecteur)
magFactor_labels <- c(
  "4" = "mag 4",
  "5" = "mag 5",
  "6" = "mag 6"
)
# Production du graphique
scatterplot +
  facet_grid(
    magFactor ~ region, 
    labeller = labeller(magFactor = magFactor_labels)
  )

Références :

Apprendre par des exemples

Représentation de variables catégoriques

Diagramme à barres

La fonction geom_bar calcule les fréquences des niveaux de facteurs et produit des diagrammes à barres.

ggplot(data = quakes) + 
  geom_bar(mapping = aes(x = magFactor)) +
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences")  

Si nous avons déjà en main les fréquences, il faut plutôt utiliser la fonction geom_col pour produire le diagramme en barres.

quakes_mag <- as.data.frame(xtabs(~ magFactor, data = quakes))
str(quakes_mag)
## 'data.frame':    3 obs. of  2 variables:
##  $ magFactor: Factor w/ 3 levels "4","5","6": 1 2 3
##  $ Freq     : int  802 193 5
ggplot(data = quakes_mag) + 
  geom_col(mapping = aes(x = magFactor, y = Freq)) +  # aesthetic y ajoutée
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences")  

Pour obtenir des barres horizontales plutôt que verticales, il faut inverser les deux axes avec coord_flip.

ggplot(data = quakes) + 
  geom_bar(mapping = aes(x = magFactor)) +
  coord_flip() +                               # permet d'inverser les axes
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences")

La fonction geom_text permet d’ajouter des annotations textuelles dans le graphique.

ggplot(data = quakes, mapping = aes(x = magFactor)) + # aesthetics communs ici
  geom_bar() +
  geom_text(
    mapping = aes(label=stat(count)),      # texte ajouté = fréquences
    stat = "count",                        # calcul des fréquences demandé ici 
    vjust = -0.2                           # ajustement vertical
  ) +
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences")  

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

ggplot(data = quakes) + 
  geom_bar(mapping = aes(x = magFactor, fill = region)) +  # aesthetic fill ajoutée
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences") +
  labs(fill = "région") 

Pour avoir des bâtons groupés plutôt qu’empilés, il faut modifier la valeur de l’argument position.

ggplot(data = quakes) + 
  geom_bar(
    mapping = aes(x = magFactor, fill = region), 
    position = "dodge"                            # position des bâtons modifiée
  ) +
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences") +
  labs(fill = "région")

Afin de présenter des fréquences relatives plutôt que brutes.

ggplot(data = quakes) + 
  geom_bar(
    mapping = aes(
      x = magFactor, 
      y = stat(prop), # permet le calcul de fréquences relatives (proportions)
      group = region, # pour avoir les fréq. relatives de mag conditionnelles à region
      fill = region), 
    position = "dodge"
  ) +
  labs(title = "Proportions de séismes par classe de magnitude selon la région") +
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences relatives") +
  labs(fill = "région")

Références :

Diagramme en secteurs

Les auteurs de ggplot2 n’offrent pas de fonction conviviale pour la création de diagrammes en secteurs, probablement parce qu’ils ne recommandent pas leur utilisation. Malgré tout, tenter de tracer un diagramme en secteurs avec ggplot2 aide à comprendre davantage les possibilités du package.

Pour produire un diagramme en secteurs avec ggplot2, il faut d’abord produire un diagramme à barres empilées, puis demander l’utilisation d’un système de coordonnées polaires par un appel à la fonction coord_polar.

ggplot(data = quakes) +
  geom_bar(mapping = aes(x = 1, fill = magFactor)) +
  coord_polar(theta = "y") +                     # coordonnées polaires
  theme_void() +                                 # thème vide
  labs(fill = "classe de\nmagnitude")

Pour inverser l’ordre des niveaux d’un facteur, la fonction fct_rev du package forcats est pratique.

library(forcats)
ggplot(data = quakes) +
  geom_bar(mapping = aes(x = 1, fill = fct_rev(magFactor))) +
  coord_polar(theta = "y") +
  theme_void() +
  labs(fill = "classe de\nmagnitude")

Si la variable n’avait pas été stockée sous forme de facteur, la fonction factor aurait été utile.

# Créons une copie de quakes, contenant une version numérique de la classe de magnitude
quakes2 <- quakes
quakes2$magFloor <- floor(quakes2$mag)
str(quakes2)
# Production d'un diagramme en secteurs
ggplot(data = quakes2) +
  geom_bar(mapping = aes(x = 1, fill = factor(magFloor))) +
  coord_polar(theta = "y") +  
  theme_void() + 
  labs(fill = "classe de\nmagnitude")

Références :

Représentation bivariée d’une variable numérique et d’une variable catégorique

Courbes de densité à noyau

Il est facile avec ggplot2 de superposer des histogrammes ou des courbes de densités à noyau (comme ci-dessous).

ggplot(data = quakes) + 
  geom_density(
    mapping = aes(x = mag, fill = region), 
    alpha = 0.5        # niveau d'opacité (0 = transparent, 1 = complètement opaque)
  ) +
  labs(x = "magnitude du séisme") +
  labs(y = "densité") +
  labs(fill = "région")

Référence :

Violin plot

Un autre outil, dérivé des courbes de densités à noyau, permettant d’explorer l’association potentielle entre une variable numérique et d’une variable catégorique est le violin plot.

violinplots <- ggplot(data = quakes) + 
  geom_violin(mapping = aes(x = region, y = mag)) +
  labs(x = "région") +
  labs(y = "magnitude du séisme")

violinplots

Référence :

Boxplots

Le violin plot est en fait d’un mélange entre les courbes de densité à noyau et les diagrammes en boîtes (boxplots).

boxplots <- ggplot(data = quakes) + 
  geom_boxplot(mapping = aes(x = region, y = mag)) +
  labs(x = "région") +
  labs(y = "magnitude du séisme")

boxplots

Référence :

Solutions aux observations superposées (overplotting)

Dans le diagramme de dispersion du nombre de stations rapportant le séisme en fonction de la magnitude du séisme (premier exemple), plusieurs points représentent en fait plus d’une observation. Cet overplotting est dû au fait que la variable stations ne prend que des valeurs entières (il s’agit d’un dénombrement) et la précision de mesure de la variable mag est limitée au dixième.

Solution 1 : Ajout de jitter aux observations

Ajouter du jitter à des observations signifie de leur ajouter de petites quantités aléatoires, parfois appelées du bruit blanc.

ggplot(data = quakes) + 
  geom_jitter(                             # geom_jitter est utilisé au lieu de geom_point
    mapping = aes(x = mag, y = stations),
    colour = "blue", 
    alpha = 0.3
  ) +
  labs(title = "1000 séismes près de Fiji") +
  labs(x = "magnitude du séisme") +
  labs(y = "nombre de stations rapportant le séisme")

Référence :

Solution 2 : Estimation à noyau de densité 2D

ggplot(
  data = quakes, 
  mapping = aes(x = mag, y = stations)                  # aesthetics communs placées ici
) +
  stat_density_2d(                                      # ajout de l'estimation de densité 2D
    aes(fill = stat(density)),
    geom = "tile",
    contour = FALSE
  ) +
  geom_point(
    shape = 20,                                         # pour modifier le symbole des points
    colour = "dodgerblue4"
    ) +
  labs(title = "1000 séismes près de Fiji") +
  labs(x = "magnitude du séisme") +
  labs(y = "nombre de stations rapportant le séisme") +
  labs(fill = "densité") +
  scale_fill_continuous(                                # pour modifier l'échelle de couleur
    low = "white", 
    high = "dodgerblue3"
  ) +  
  theme_classic()                                       # pour avoir rapidement un fond blanc

Références :

Autres solutions

D’autres solutions sont proposées ici : https://ggplot2.tidyverse.org/reference/geom_point.html#overplotting

Ajouts et mises en forme diverses

Représentation graphique d’une fonction

# Statistique dont on aura besoin
moy <- mean(quakes$mag)
et <- sd(quakes$mag)
ggplot(data = quakes, mapping = aes(x = mag)) + 
  geom_histogram(
    mapping = aes(y = stat(density)), 
    binwidth = 0.1, 
    colour = "black", 
    fill = "white"
  ) +
  labs("Densité empirique des magnitudes dans le jeu de données quakes") +
  labs(x = "magnitude du séisme") + 
  labs(y = "densité") +
  stat_function(                       # ajout d'une courbe de densité normale 
    fun = dnorm, 
    args = list(mean = moy, sd = et),  # avec paramètres estimés à partir des données
    xlim = c(3.95, 6.45)
  )

Référence :

Ajout manuel d’une légende

ggplot(data = quakes, mapping = aes(x = mag)) + 
  geom_histogram(
    mapping = aes(y = stat(density)), 
    binwidth = 0.1, 
    colour = "black", 
    fill = "white"
  ) +
  labs("Densité empirique des magnitudes dans le jeu de données quakes") +
  labs(x = "magnitude du séisme") + 
  labs(y = "densité") +
  geom_density(
    aes(colour = "Densité à noyau"),
  ) +
  stat_function(
    aes(colour = "Densité normale"),
    fun = dnorm, 
    args = list(mean = moy, sd = et),
    xlim = c(3.95, 6.45)
  ) +
  scale_colour_manual(
    name = "",
    values = c("blue", "red"),
    labels = c("Densité à noyau", "Densité normale")
  )

Référence :

Mise en forme d’une légende

ggplot(data = quakes) + 
  geom_bar(
    mapping = aes(
      x = magFactor, 
      y = stat(prop), # permet le calcul de fréquences relatives (proportions)
      group = region, # pour avoir les fréq. relatives de mag conditionnelles à region
      fill = region), 
    position = "dodge"
  ) +
  labs(title = "Proportions de séismes par classe de magnitude selon la région") +
  labs(x = "classe de magnitude du séisme") +
  labs(y = "fréquences relatives") +
  labs(fill = "région") +
  theme(
    legend.position="top",
    legend.background = element_rect(size=0.5, linetype="solid", colour ="black")
  )

Références :

Packages souvent utilisés avec ggplot2 et extensions de ggplot2

Packages du Tidyverse

library(dplyr)

Situation courante : vouloir produire un graphique à partir d’un sous-ensemble des données plutôt qu’avec le jeu de données complet. Il est alors pratique d’utiliser l’opérateur %>% et la fonction filter de dplyr comme suit :

quakes %>%
  filter(region == "Ouest") %>%
  ggplot(mapping = aes(x = mag, y = stations)) +
  geom_jitter(colour = "blue", alpha = 0.3) +
  labs(x = "magnitude du séisme") +
  labs(y = "nombre de stations rapportant le séisme")

Extensions de ggplot2

Package ggthemes

library(ggthemes)
scatterplot + 
  theme_economist()

scatterplot + 
  theme_excel()

Référence :

Package cowplot

library(cowplot)
plot_grid(
    violinplots + ggtitle("Violin plots"), 
    boxplots + ggtitle("Boxplots")
  )

title <- ggdraw() + draw_label("Lesquels préférez-vous ?", fontface='bold')
plot_grid(
  title, 
  plot_grid(
    violinplots + ggtitle("Violin plots"), 
    boxplots + ggtitle("Boxplots")
  ),
  ncol=1, rel_heights=c(0.1, 1)
)

detach("package:cowplot", unload=TRUE)

Référence :

Package ggExtra

library(ggExtra)
ggMarginal(scatterplot, type = "histogram")

Référence :

Package GGally

library(GGally)
ggpairs(quakes)

Référence :

Package ggiraph

library(ggiraph)
g <- ggplot(quakes, aes(x = long, y = lat, color = depth)) + 
  coord_quickmap() # coord_quickmap() permet d'avoir des axes sur la même échelle
my_gg <- g + 
  geom_point_interactive(
    mapping = aes(tooltip = stations), 
    size = 2
  )

ggiraph(code = print(my_gg), 
        tooltip_extra_css = "background-color:gray;color:white;font-style:italic;padding:10px;border-radius:10px 20px 10px 20px;",
        tooltip_opacity = 0.75)

Référence :

Package maps

library(maps)
monde <- map_data("world")  # va chercher des données provenant du package maps ou mapdata
ggplot() + 
  geom_polygon(
    data = monde,
    aes(x = long, y = lat, group = group), 
    fill = "gray90", 
    col = "black"
  ) +
  geom_point(
    data = quakes, 
    aes(x = long, y = lat, colour = region), 
    alpha = .3
  ) +
  coord_fixed(
    xlim = c(115, 190),  
    ylim = c(-50, 0), 
    ratio = 1.3
  ) +
  labs(x = "longitude", y = "latitude", colour = "région") +
  theme_bw()

Référence :