class: title-slide, center # Visualiser avec .hex[![ggplot2](img/06-ggplot2_hex.png)] ## .doana-title[![](img/logoDoAna.png)] ### DoAna - Statistiques Réunion ### 2024 --- layout: true .my-footer[![](img/logoDoAna.png) .footer-title[Visualiser des données avec ggplot2]] --- background-image: url(img/06-ggplot2_gallery.png) background-size: contain --- ## Objectif *** <img src="06-ggplot2_files/figure-html/obj-1.png" width="70%" style="display: block; margin: auto;" /> ??? parler de l'importance de représenter les données --- name: plan ## Sommaire *** .pull-left[ 1) Commencer sans pression - Démarrage - **esquisse** 2) Décortiquer notre première commande - Se munir de la **cheatsheet** - Principe : empilement de couches - Mise en place : `ggplot()` et `aes()` - Les calques : `geom_machin()` - Les échelles : `scale_truc()` - Les labels : `labs()` - Les thèmes existants : `theme_bidule()` - Personnaliser son thème : `theme()` - Les sous-graphiques : `facet_chose()` ] .pull-right[ 3) Aller plus loin - L'argument position - Les coordonnées : `coord_chouette()` - Ajout rapide : `annotate()` - Plusieurs graphes : `ggarrange()` - Calculs : `stat = "summary"` - Sauvegardes : `ggsave()` - Ressources supplémentaires ] --- class: inverse, middle, center # Commencer sans pression --- ## Démarrage *** .pull-left[ - Ecrire dans un nouveau script : ``` r library(readr) library(dplyr) sols <- read_csv("donnees/sols-petit.csv") ``` ] -- .pull-right[ - Installer **esquisse**, si ce n'est pas encore fait - Ouvrir : `Addins > Esquisse > 'ggplot2' builder` ![](img/06-ggplot2_esquisse-1.png) ] --- ## **esquisse** *** .pull-left[ - Exploration aisée d’un jeu de données - Ecriture automatique du script Deux limitations majeures : - Variable quanti ∼ variable quali → que des boxplot et PAS de scatterplot - Une seule variable à la fois dans la même «boîte» > MAIS à partir du moment où le début du script est écrit, le plus dur est passé ! ] .pull-right[ ![](img/06-ggplot2_esquisse-2.png) ] --- ## Exercice : Obtenez ceci avec **esquisse** *** <img src="06-ggplot2_files/figure-html/esquisse-1.png" width="70%" style="display: block; margin: auto;" /> --- ## Ce que l'on exporte dans le script *** ``` r library(ggplot2) ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant) + geom_boxplot() + scale_fill_hue(direction = 1) + labs( title = "Carbone par plante et système de culture", y = "Carbone(1/1000)", x = "Système de culture", fill = "Plante" ) + theme_minimal() + facet_wrap(vars(site)) ``` -- Organisation du script : `library(ggplot2)` à ranger ??? Qu'est ce que ça veut dire tout ça ? --- template: plan --- class: inverse, middle, center # Décortiquer notre première commande --- ## Se munir de la *cheatsheet* *** Disponible en [EN](https://github.com/rstudio/cheatsheets/raw/master/data-visualization-2.1.pdf) et [FR](https://thinkr.fr/pdf/ggplot2-french-cheatsheet.pdf). .tidy[![](https://d33wubrfki0l68.cloudfront.net/21d683072b0c21cbd9b41fc0e37a587ad26b9525/cbf41/wp-content/uploads/2018/08/data-visualization-2.1.png)] --- ## Principe : empilement de couches *** .tidy[![](img/06-ggplot2_couches.png)] --- name: place ## Mise en place : `ggplot()` et `aes()` *** {{content}} --- template: place ``` r *ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant) + geom_boxplot() + scale_fill_hue(direction = 1) + labs(x = "Système de culture", y = "Carbone (1/1000)", title = "Carbone par plante et système de culture", fill = "Plante") + theme_minimal() + facet_wrap(vars(site)) ``` -- → Choix du jeu de données -- → Création d’une fenêtre graphique vierge -- → Les `"+"` pour ajouter des consignes au graphique de base : `ggplot(sols)` --- template: place ``` r ggplot(sols) + *aes(x = syst, y = c.pourmil, fill = plant) + geom_boxplot() + scale_fill_hue(direction = 1) + labs(x = "Système de culture", y = "Carbone (1/1000)", title = "Carbone par plante et système de culture", fill = "Plante") + theme_minimal() + facet_wrap(vars(site)) ``` -- → `aesthetics` : propriétés esthétiques -- → un **rôle** pour chaque variable d’intérêt, -- → et ce, pour toute la suite. --- template: place → Donner un rôle à chacune des variables d’intérêt, et ce pour toute la suite. Principaux `aesthetics` : aes()|Rôle ---|--- `x`|Abscisse `y`|Ordonnée `colour` ou `color`|Couleur des points et des contours `fill`|Couleur de remplissage `group`|Regroupement des données par modalité `alpha`|Taux de transparence (entre 0 et 1) `size` et `linewidth`|Taille des éléments ...|... --- name: calque ## Les calques : `geom_machin()` *** {{content}} --- template: calque ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant) + *geom_boxplot() + scale_fill_hue(direction = 1) + labs(x = "Système de culture", y = "Carbone (1/1000)", title = "Carbone par plante et système de culture", fill = "Plante") + theme_minimal() + facet_wrap(vars(site)) ``` -- → Les calques du graphique -- → que l’on peut superposer ! --- background-image: url(img/06-ggplot2_familles.png) --- template: calque → Les calques du graphiques, que l’on peut superposer ! <small> |geom |Graphique |Arguments intéressants : | |:---------------------------|:--------------------------------------|:------------------------------------------------| |`geom_point` |Nuage de points |x, y, size, shape, colour | |`geom_jitter` |Nuage de points avec du bruit |x, y, size, shape, colour, **width**, **height** | |`geom_line` |Trajectoires |x, y, size, linetype, colour, **group** | |`geom_bar` |Diagramme en bâtons (nombre de cas) |x, fill, position | |`geom_col` |Diagramme en bâtons (valeurs choisies) |x, **y**, fill, position | |`geom_histogram` |Histogramme (barres) |x (continue), **bins**, fill, position | |`geom_freqpoly` |Histogramme (lignes) |x (continue) | |`geom_density` |Density plot |x, fill, position, stat | |`geom_boxplot` |Boîtes à moustaches |x, y, fill, alpha, **outliers**, varwidth | |`geom_label` ou `geom_text` |Nuage de texte. NB : `ggrepel` |x, y, label, angle, colour, **hjust**, **vjust** | |... |... |... | </small> --- name: scale ## Les échelles : `scale_*_truc()` *** {{content}} --- template: scale ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant) + geom_boxplot() + *scale_fill_hue(direction = 1) + labs(x = "Système de culture", y = "Carbone (1/1000)", title = "Carbone par plante et système de culture", fill = "Plante") + theme_minimal() + facet_wrap(vars(site)) ``` -- → Ici : la palette de couleurs (`brewer`) de l’aesthetic `fill` (`*`) est définie par la palette `"Dark2"` -- → **Une** (et une seule) échelle associée à chaque rôle/aes Ex : calcul des graduations de l'axe des x ou choix des couleurs de remplissage d'un boxplot -- > Pour choisir la palette parfaite : [r-graph-gallery.com/color-palette-finder](https://r-graph-gallery.com/color-palette-finder) --- template: scale → Une échelle associée à chaque rôle/aes <small> |scale |Transforme |Arguments | |:--------------------|:-------------------------------------------------------------------------------------------------------|:-------------------------------------------| |`scale_*_discrete` |Les échelles **discrètes** (`x` et `y`, ex : dans un barplot) |limits, breaks, name, labels, position, ... | |`scale_*_continuous` |Les échelles **continues** (`x` et `y`, ex : dans un histogramme) |limits, breaks, name, labels, position, ... | |`scale_*_date` |L’échelle en date (`x` et `y`) |date_labels, date_breaks, ... | |`scale_*_log10` |En échelle logarithmique (`x` et `y`) | | |`scale_*_reverse` |Retourne l’échelle (`x` et `y`) | | |`scale_*_manual` |Manuellement les couleurs **discrètes** (`fill` et `color`) ou la forme des points (`shape`) |**values**, labels, ... | |`scale_*_brewer` |Une palette **discrète** existante de couleurs (`fill` et `color`) `RColorBrewer::display.brewer.all()` |**palette**, aesthetics, ... | |`scale_*_gradient` |Un gradient de couleurs **continu** (`fill` et `color`) |**low**, **high**, mid, ... | |... |... |... | </small> --- ## Les labels : `labs()` *** ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant) + geom_boxplot() + scale_fill_hue(direction = 1) + *labs(x = "Système de culture", y = "Carbone (1/1000)", title = "Carbone par plante et système de culture", fill = "Plante") + theme_minimal() + facet_wrap(vars(site)) ``` -- → Change les titres des axes et des légendes (`guides`). -- → Pour les autres libellés (ex. : nom des modalités), utiliser les fonctions `scale` --- ## Les thèmes existants : `theme_bidule()` *** ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant) + geom_boxplot() + scale_fill_hue(direction = 1) + labs(x = "Système de culture", y = "Carbone (1/1000)", title = "Carbone par plante et système de culture", fill = "Plante") + *theme_minimal() + facet_wrap(vars(site)) ``` -- → Choisir un thème de fond : `theme_gray()`, `theme_bw()`, `theme_linedraw()`, `theme_light()`, `theme_dark()`, `theme_minimal()`, `theme_classic()`, `theme_void()` -- → Et encore plus de thèmes tout prêts dans le package **ggthemes** ! --- ## Personnaliser son thème : `theme()` *** **Thème** : tout ce qui ne concerne pas VOS données directement. -- Beaucoup beaucoup d’arguments différents pour le gérer finement : - le format des textes, - la forme et les couleurs de la grille de fond et des axes, - la couleur de fond, - … -- Exemple pour enlever la légende (ou modifier son emplacement) : `theme(legend.position = "none")` -- Attention : `element_text()`, `element_line()` et `element_rect()` à utiliser pour compléter certains arguments de la fonction theme. N’hésitez pas à fouiller dans l’aide et à jouer avec leurs arguments pour comprendre à quoi ils servent !! --- ## Les sous-graphiques : `facet_chose()` *** ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant) + geom_boxplot() + scale_fill_hue(direction = 1) + labs(x = "Système de culture", y = "Carbone (1/1000)", title = "Carbone par plante et système de culture", fill = "Plante") + theme_minimal() + *facet_wrap(vars(site)) ``` -- → Découpage en **sous-graphiques** selon une ou plusieurs variables discrètes : - `facet_wrap(vars(site))` : arrange les sites dans une mise en page rectangulaire - `facet_grid(cols = vars(site))` : les met sur une seule ligne - `facet_grid(rows = vars(site))` : les met sur une seule colonne - `facet_grid(vars(site), vars(plant))` : met les sites en ligne et les plantes en colonne -- L’argument `scales` : gère les échelles en x et en y pour tous les sous-graphiques. --- template: plan --- class: inverse, middle, center # Aller plus loin --- ## Exercice : améliorez votre graphique *** .pull-left[ <img src="06-ggplot2_files/figure-html/ex1-1.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right[ <img src="06-ggplot2_files/figure-html/ex2-1.png" width="100%" style="display: block; margin: auto;" /> ] --- ## Solution *** ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, fill = plant, colour = plant) + geom_boxplot( outliers = FALSE, position = position_dodge(width = 0.8), colour = "black", alpha = 0.2, width = 0.5) + geom_point(position = position_dodge(width = 0.8)) + labs(x = "Système de culture", y = "Carbone (‰)", title = "Carbone par plante et système de culture", fill = "Plante", colour = "Plante") + scale_fill_manual( aesthetics = c("colour", "fill"), values = c(mais = "orange", pdt = "brown", riz = "blue", soja = "darkgreen", "grey"), labels = c(mais = "Maïs", pdt = "Pomme de terre", riz = "Riz", soja ="Soja")) + scale_x_discrete(labels = c("Labour", "Desmodium", "Kikuyu", "Résidus")) + theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1)) + facet_wrap(~ site, scales = "free_x") ``` ??? on peut enlever `theme_grey()` qui est le theme par défaut --- ## L'argument `position` *** On l'utilise dans les fonctions `geom_*()`. -- - `geom_bar` : - `position_dodge` : arranger les éléments côte à côte .aligner[![](img/06-ggplot2_position-dodge.png)] - `position_fill` : empiler les éléments en normalisant la hauteur .aligner[![](img/06-ggplot2_position-fill.png)] - `position_stack` : empiler les éléments sans normaliser la hauteur .aligner[![](img/06-ggplot2_position-stack.png)] -- - `geom_point` : - `position_jitter` : produire la même chose que `geom_jitter()` .aligner[![](img/06-ggplot2_position-jitter.png)] -- - `geom_label` : - `position_nudge` : décaler les labels des points .aligner[![](img/06-ggplot2_position-nudge.png)] --- name: coord ## Les coordonnées : `coord_chouette()` *** {{content}} --- template: coord ``` r ggplot(sols) + ... + coord_cartesian(ylim = c(0, max(sols$c.pourmil))) ``` <img src="06-ggplot2_files/figure-html/cartesian2-1.png" width="70%" style="display: block; margin: auto;" /> --- template: coord ``` r ggplot(sols) + ... + coord_flip() ``` <img src="06-ggplot2_files/figure-html/flip2-1.png" width="70%" style="display: block; margin: auto;" /> --- template: coord ``` r ggplot(sols) + ... + coord_polar() ``` <img src="06-ggplot2_files/figure-html/polar2-1.png" width="70%" style="display: block; margin: auto;" /> --- ## Les coordonnées : `coord_chouette()` *** ``` r ggplot(sols) + ... + coord_trans(y = "sqrt", ylim = c(0, max(sols$c.pourmil))) ggplot(sols) + ... + scale_y_sqrt(limits = c(0, max(sols$c.pourmil))) ``` .pull-left[ <img src="06-ggplot2_files/figure-html/trans2-1.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right[ <img src="06-ggplot2_files/figure-html/trans3-1.png" width="100%" style="display: block; margin: auto;" /> ] --- name: annotate ## Ajout rapide : `annotate()` *** {{content}} --- template: annotate ``` r ggplot(sols) + ... + annotate("rect", xmin = 0.55, xmax = 1.45, ymin = 25, ymax = 35) ``` <img src="06-ggplot2_files/figure-html/rect2-1.png" width="70%" style="display: block; margin: auto;" /> --- template: annotate ``` r ggplot(sols) + ... + annotate("text", x = 1:4, y = 40, label = "toto") ``` <img src="06-ggplot2_files/figure-html/text2-1.png" width="70%" style="display: block; margin: auto;" /> --- template: annotate ``` r ggplot(sols) + ... + annotate("segment", x = 1, xend = 2, y = 30, yend = 50, linewidth = 3) ``` <img src="06-ggplot2_files/figure-html/segment2-1.png" width="70%" style="display: block; margin: auto;" /> --- ## Plusieurs graphes : `ggarrange()` *** ``` r library(ggpubr) premier <- ggplot(sols) + … deuxieme <- ggplot(sols) + … ggarrange(premier, deuxieme, ncol = 2, labels = LETTERS[1:2]) ``` <img src="06-ggplot2_files/figure-html/ggarrange2-1.png" width="100%" style="display: block; margin: auto;" /> --- name: stat ## Calculs : `stat = "summary"` *** --- template: stat <img src="06-ggplot2_files/figure-html/stat3-1.png" width="70%" style="display: block; margin: auto;" /> --- template: stat ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, colour = plant, group = plant) + geom_point(position = position_jitterdodge(dodge.width = 0.8, jitter.width = 0.2), shape = 10) + geom_pointrange( stat = "summary", fun.data = "mean_cl_boot", aes(shape = "IC à 95%"), # affichage de la légende position = position_dodge(width = 0.8), color = "black") + scale_color_manual( values = c(mais = "orange", pdt = "brown", riz = "blue", soja = "darkgreen", "grey"), labels = c(mais = "Maïs", pdt = "Pomme de terre", riz = "Riz", soja ="Soja")) + labs(x = "Système de culture", y = "Carbone (‰)", title = "Carbone par plante et système de culture", colour = "Plante", shape = "") + scale_x_discrete(labels = c("Labour", "Desmodium", "Kikuyu", "Résidus")) + theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1)) + facet_wrap(vars(site), scales = "free_x") ``` --- template: stat ``` r ggplot(sols) + aes(x = syst, y = c.pourmil, colour = plant, group = plant) + geom_point(position = position_jitterdodge(dodge.width = 0.8, jitter.width = 0.2), shape = 10) + geom_pointrange( stat = "summary", * fun.data = "mean_cl_boot", aes(shape = "IC à 95%"), # affichage de la légende position = position_dodge(width = 0.8), color = "black") + scale_color_manual( values = c(mais = "orange", pdt = "brown", riz = "blue", soja = "darkgreen", "grey"), labels = c(mais = "Maïs", pdt = "Pomme de terre", riz = "Riz", soja ="Soja")) + labs(x = "Système de culture", y = "Carbone (‰)", title = "Carbone par plante et système de culture", colour = "Plante", shape = "") + scale_x_discrete(labels = c("Labour", "Desmodium", "Kikuyu", "Résidus")) + theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1)) + facet_wrap(vars(site), scales = "free_x") ``` --- ## Sauvegardes : `ggsave()` *** ``` r ggsave(filename = "graphiques/monjoligraphe.png") ggsave(filename = "graphiques/monjoligraphe.pdf", plot = last_plot()) ``` ![](img/06-ggplot2_ggsave.png) --- ## Ressources supplémentaires - [ggplot2-book.org](https://ggplot2-book.org/) : **`#LABASE`** - [ggplot2.tidyverse.org](https://ggplot2.tidyverse.org/) : doc en ligne (en anglais) - [data-to-viz.com](https://www.data-to-viz.com) : plein d’exemples de visualisation - [www.yihanwu.ca/post/geoms-and-aesthetic-parameters/](https://www.yihanwu.ca/post/geoms-and-aesthetic-parameters/) : sur les *geometries* -- De nombreux packages utilisent **ggplot2** : rajout de couches et d’options avec des `+` : - **factoextra** pour les analyses multivariées - **ggtree** pour les arbres phylogénétiques - **ggiraph** pour les graphiques interactifs - … → Allez voir : [exts.ggplot2.tidyverse.org](https://exts.ggplot2.tidyverse.org/gallery/) ! -- > Et surtout, n’oubliez pas de poser vos questions sur votre moteur de recherche préféré ! --- class: inverse, bottom, center ### Pratiquez pratiquez pratiquez #### Le gra(phique)s, c'est la vie -- -- -- ### ☺ -- -- -- [Accueil](/)