Prise en main de ggplot2
- - - - - - - -1 Objectifs du TP
-L’objectif de ce TP vise à se familiariser avec le package ggplot2
-de R. Il s’agit de faire des manipulations graphiques élémentaires et
-d’interpréter les résultats de ces visualisations.
Dans un premier temps, vous pouvez suivre l’exemple introductif en -répliquant le code fourni. Dans un deuxième temps, il convient de -réaliser l’exercice point par point.
-2 Prérequis
--
-
- Avoir installer
Rici.
- - Avoir installer un IDE, par exemple
RStudio-ici.
- - Créer un nouveau projet (
File, puisNew Projet) dans un dossier -sur votre ordinateur.
- - Télécharger ici -les fichiers nécessaires au TD. -
Vous pouvez ensuite écrire vos codes soit :
--
-
- En ouvrant un nouveau script
.R;
- - En ouvrant le ouvrant le rapport Rmarkdown
3-td_ggplot2 - enonce. -Certains codes sont partiels et sont à compléter (indication???). -N’oubliez pas de modifier l’optioneval = TRUEpour que les -calculs puissent être réalisés.
-
3 Exemple introductif
-Pour illustrer cette première partie, nous reprenons l’exemple
-introductif fourni par @wickham2023 sur le jeu de données penguins du
-package palmerpenguins. Ce jeu de données s’intèresse des mesures
-réalisées sur des manchots sur 3 îles de l’archipelle Palmer.
3.1 Données
-Dans un premier temps, il faut installer le package et le charger.
- -Ce jeu de données contient 344 observations où chaque ligne correspond à -un individu.
- -On se concentre plus particulièrement sur les variables suivantes :
--
-
species: l’espèce de manchot ;
-flipper_length_mm: la longueur de la nageoire en mm ;
-body_mass_g: la masse en gramme.
-
Pour plus détails, voir l’aide ?penguins.
3.2 But de la visualisation
-On s’intéresse au lien entre le masse et la taille des nageoires des -manchots :
--
-
- ceux dont les nageoires sont les plus longues sont-ils plus lourds -que les manchots aux nageoires courtes ? -
- si oui quelle est le type de relation (linéaire, croissante, -décroissante, …) ? -
- quels facteurs influencent également cette relation (lieu, l’espèce, -… ) ? -
On cherche à recréer la figure suivante.
-
3.3 Création de la figure étape par étape
-Etape 1 : Scatterplot
-On commence par créer un scatterplot pour examiner la relation entre la -masse et la taille de la nageoire.
-ggplot(
- data = penguins,
- mapping = aes(x = flipper_length_mm, y = body_mass_g)
-) +
- geom_point()Cette figure fait clairement apparaître une relation croissante et a -priori linéaire entre les deux variables.
-Un message d’erreur apparaît pour deux individus avec des données -manquantes. Ils sont automatiquement exclus.
-Etape 2 : Ajout d’élements esthétiques
-On cherche à présent exhiber le rôle de l’espèce à partir d’une couleur. -Trois espèces sont présents, ainsi l’ajout de 3 couleurs à la figure ne -devrait pas surcharger le graphique.
-ggplot(
- data = penguins,
- mapping = aes(x = flipper_length_mm, y = body_mass_g, color = species)
-) +
- geom_point()Compte tenu du nombre important de points, nous pouvons renforcer les -différences par espèce en ajoutant une variation de forme aux points.
-ggplot(
- data = penguins,
- mapping = aes(x = flipper_length_mm, y = body_mass_g)
-) +
- geom_point(
- mapping = aes(
- color = species,
- shape = species
- )
- )Etape 3 : Ajout d’une géométrie
-Voyons à présent comment interpréter la nature de la relation entre -masse et longueur de la nageoire. Pour ce faire, nous essayons d’ajout -des courbes de tendance. Nous commençons par une tendance linéaire.
-ggplot(
- data = penguins,
- mapping = aes(x = flipper_length_mm, y = body_mass_g)
-) +
- geom_point(
- mapping = aes(
- color = species,
- shape = species
- )
- ) +
- geom_smooth(method = "lm")La même figure peut être générée par espèce en déplaçant l’argument
-color = species.
ggplot(
- data = penguins,
- mapping = aes(x = flipper_length_mm, y = body_mass_g, color = species)
-) +
- geom_point(
- mapping = aes(
- shape = species
- )
- ) +
- geom_smooth(method = "lm")Les pentes entre les espèces ne sont pas si éloignées. Nous décidons que -conserver une relation commune pour toutes espèces. Pour tester si la -nature linéaire de la relation est a priori une bonne hypothèse, nous -considérons un lissage non-paramétrique.
-ggplot(
- data = penguins,
- mapping = aes(x = flipper_length_mm, y = body_mass_g)
-) +
- geom_point(
- mapping = aes(
- color = species,
- shape = species
- )
- ) +
- geom_smooth(method = "loess")L’ajout d’un lissage non-paramétrique permet d’affiner l’adéquation aux -données, mais sans pour autant clairement remettre en cause la tendance -linéaire qui sera donc conservée.
-Etape 4 : Ajout des titres et changement de thème
-Afin de finaliser la figure, nous ajouter :
--
-
- un titre ; -
- un sous-titre ; -
- des titres aux axes ; -
- un titre à la légende. -
Ces informations sont ajoutées avec labs().
De plus, nous modifions le thème avec la commande theme_bw().
ggplot(
- data = penguins,
- mapping = aes(x = flipper_length_mm, y = body_mass_g)
-) +
- geom_point(aes(color = species, shape = species)) +
- geom_smooth(method = "lm") +
- labs(
- title = "Masse et taille de la nageoire",
- subtitle = "Manchots d'Adelie, a
- jugulaire et de Gentoo",
- x = "Longueur de la nageoire (mm)",
- y = "Masse (g)",
- color = "Espece",
- shape = "Espece"
- ) +
- scale_color_colorblind() +
- theme_bw()-
4 Exercice
-4.1 Données
-Nous travaillons avec les jeux de données FreMTPL2freq et
-FreMTPL2sev du package Casdatasets. Ces données ont été
-préalablement pré-formatées et regroupées.
Ce jeux de données regroupent les caractéristiques de 677 991 polices de -responsabilité civile automobile, observées principalement sur une -année. Dans les données regroupées, on dispose des numéros de sinistre -par police, des montants de sinistre correspondants, des -caractéristiques du risque et du nombre de sinistres.
-On présente ci-dessous un aperçu des données.
-# Folds
-fold <- getwd()
-
-# Load data
-load(paste0(fold, "/data/datafreMPTL.RData"))
-# load(paste0(fold, "/M2/Data Visualisation/tp1", "/data/datafreMPTL.RData"))
-paged_table(dat, options = list(rows.print = 15))Le tableau suivant présente une définition des variables.
-kableExtra::kable(
- data.frame(
- Variable = c(
- "IDpol",
- "Exposure",
- "VehPower",
- "VehAge",
- "DrivAge",
- "BonusMalus",
- "VehBrand",
- "VehGas",
- "Area",
- "Density",
- "Region",
- "ClaimTotal",
- "ClaimNb"
- ),
- Description = c(
- "Identifiant de la police",
- "Exposition au risque",
- "Puissance du véhicule",
- "Age du véhicule en année",
- "Age du conducteur en année",
- "Coefficient de bonus-malus",
- "Marque du véhicule",
- "Carburant du véhicule",
- "Catégorie correspondant à la densité de la zone assurée",
- "Densité de population",
- "Region (selon la classication 1970-2015)",
- "Montant total des sinistres",
- "Nombre de sinistres sur la période"
- ),
- Type = c(
- rep("Reel", 2),
- rep("Entier", 4),
- rep("Cat", 3),
- "Entier",
- "Cat",
- rep("Reel", 2)
- )
- ),
- booktabs = TRUE
-)| Variable | -Description | -Type | -
|---|---|---|
| IDpol | -Identifiant de la police | -Reel | -
| Exposure | -Exposition au risque | -Reel | -
| VehPower | -Puissance du véhicule | -Entier | -
| VehAge | -Age du véhicule en année | -Entier | -
| DrivAge | -Age du conducteur en année | -Entier | -
| BonusMalus | -Coefficient de bonus-malus | -Entier | -
| VehBrand | -Marque du véhicule | -Cat | -
| VehGas | -Carburant du véhicule | -Cat | -
| Area | -Catégorie correspondant à la densité de la zone assurée | -Cat | -
| Density | -Densité de population | -Entier | -
| Region | -Region (selon la classication 1970-2015) | -Cat | -
| ClaimTotal | -Montant total des sinistres | -Reel | -
| ClaimNb | -Nombre de sinistres sur la période | -Reel | -
## 'data.frame': 135601 obs. of 13 variables:
-## $ IDpol : num 5089457 2215917 2202141 1077071 3044896 ...
-## $ Exposure : num 0.21 0.25 1 0.07 0.09 0.08 1 1 0.49 0.8 ...
-## $ VehPower : int 7 5 7 7 7 7 13 4 7 4 ...
-## $ VehAge : int 10 2 6 4 7 4 3 14 8 2 ...
-## $ DrivAge : int 36 40 79 42 45 53 53 32 31 42 ...
-## $ BonusMalus: int 50 85 54 57 100 53 50 60 71 50 ...
-## $ VehBrand : Factor w/ 11 levels "B1","B2","B3",..: 1 3 10 2 7 2 1 2 3 9 ...
-## $ VehGas : Factor w/ 2 levels "Diesel","Regular": 2 2 1 1 1 1 2 2 2 2 ...
-## $ Area : Factor w/ 6 levels "A","B","C","D",..: 5 5 3 5 6 3 5 4 5 2 ...
-## $ Density : int 8 8 6 8 10 5 8 7 9 4 ...
-## $ Region : Factor w/ 21 levels "Alsace","Aquitaine",..: 21 7 7 21 12 20 7 16 21 7 ...
-## $ ClaimTotal: num 0 0 0 0 0 0 0 0 0 0 ...
-## $ ClaimNb : num 0 0 0 0 0 0 0 0 0 0 ...
-Pour plus de détails, consulter l’aide ?CASdatasets::freMTPL2freq.
-
4.2 But de la visualisation
-Nous effectuons une première analyse descriptive de données et cherchons -à étudier la relation entre :
--
-
- la fréquence, calculée avec les variables
ClaimNbetExposure-(période d’exposition en année).
- - les variables
AreaetDrivAge.
-
Le but de la visualisation est de fait ressortir les liens entre la -fréquence et ces deux variables.
-Etape 1 : Visualisation de la fréquence et de l’exposition
-A partir des données dat :
-
-
- afficher les statistiques descriptives du nombre de sinistres
-
ClaimNbet de la variableExposure;
- - afficher des histogrammes pour visualiser leur distribution ; -
- afficher les figures côte a côte avec la fonction
plot_grid().
-
Essayer de choisir un thème de couleur et un écartement des barres de -l’histogramme facilitant sa lisibilité.
-On pourra développer une fonction qui utilise geom_histogram() sous la
-package ggplot2.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
-## 0.00000 0.00000 0.00000 0.03919 0.00000 3.00000
-
-## Min. 1st Qu. Median Mean 3rd Qu. Max.
-## 0.002732 0.170000 0.490000 0.527782 0.990000 1.000000
-p1 <- ggplot(dat) +
- geom_histogram(
- aes(x = ClaimNb),
- binwidth = 0.25,
- fill = "lightblue",
- color = "black"
- ) +
- labs(
- title = "Distribution du nombre de sinistres",
- x = "Nombre de sinistres",
- y = "Effectif"
- ) +
- theme_bw()
-
-p2 <- ggplot(dat) +
- geom_histogram(
- aes(x = Exposure),
- binwidth = 0.05,
- fill = "lightblue",
- color = "black"
- ) +
- labs(title = "Exposition", x = "Nombre de sinistres", y = "Effectif") +
- theme_bw()
-
-plot_grid(p1, p2, ncol = 2)Etape 2 : Calculer la fréquence
-Construire un tableau présentant l’exposition cumulée et le nombre -d’observations avec 0 sinistre, 1 sinistre, …
-dat |>
- group_by(ClaimNb) |>
- summarise(n = n(), Exposure = round(sum(Exposure), 0)) |>
- kable(
- col_names = c(
- "Nombre de sinistres",
- "Nombres d'observations",
- "Exposition totale"
- )
- ) |>
- kable_styling(full_width = FALSE)| -ClaimNb - | --n - | --Exposure - | -
|---|---|---|
| -0 - | --130563 - | --68095 - | -
| -1 - | --4771 - | --3294 - | -
| -2 - | --258 - | --172 - | -
| -3 - | --9 - | --6 - | -
## [1] 0.0743
-Ce calcul de fréquence sera ensuite utile pour l’affichage des -résultats.
-Etape 3 : Calculer l’exposition et la fréquence par variable
-Pour la variable DrivAge, présenter :
-
-
- un histogramme de l’exposition en fonction de cette variable. -
- un histogramme de la fréquence moyenne de sinistres en fonction de -cette variable. -
Remplacer ensuite le second histogramme par un scatter plot avec une -courbe de tendance. Est-ce plus clair ?
-Indice
-On pourra développer une fonction qui utilise geom_bar() sous la
-package ggplot2.
# On regroupe selon les modalites de la DrivAge
-# l'exposition, le nombre de sinistres et la frequence
-df_plot <- dat |>
- group_by(DrivAge) |>
- summarize(
- exp = sum(Exposure),
- nb_claims = sum(ClaimNb),
- freq = sum(ClaimNb) / sum(Exposure)
- )
-
-# Histogramme exposition
-p1 <- ggplot(df_plot, aes(x = DrivAge, y = exp)) +
- geom_bar(stat = "identity", fill = "grey", color = "black", alpha = 0.5) +
- labs(x = "Age du conducteur", y = "Exposition en années") +
- theme_bw()
-
-# Histogramme frequence
-p2 <- ggplot(df_plot, aes(x = DrivAge, y = freq)) +
- geom_bar(stat = "identity", fill = "grey", color = "black", alpha = 0.5) +
- labs(x = "Age du conducteur", y = "Frequence") +
- theme_bw()
-
-plot_grid(p1, p2, labels = c("A", "B"), label_size = 12)df_plot <- dat |>
- group_by(DrivAge) |>
- summarize(
- exp = sum(Exposure),
- nb_claims = sum(ClaimNb),
- freq = sum(ClaimNb) / sum(Exposure)
- )
-
-# Scatter plot frequence
-p3 <- ggplot(df_plot, aes(x = DrivAge, y = freq)) +
- geom_point() +
- geom_smooth() +
- labs(x = "Age du conducteur", y = "Frequence") +
- theme_bw()
-p3Etape 4 : Examiner l’intéraction avec une autre variable
-A partir du scatter plot réalisé à l’étape précédente, distinguer les
-évolutions de fréquence en fonction de DrivAge et de BonusMalus.
Ce graphique vous paraît-il transmettre un message clair ? Proposez des
-améliorations en modifiant les variables DrivAge et BonusMalus.
# On regroupe selon les modalites de la DrivAge et de Area
-# l'exposition, le nombre de sinistres et la frequence
-df_plot <- dat |>
- group_by(DrivAge, BonusMalus) |>
- summarize(
- exp = sum(Exposure),
- nb_claims = sum(ClaimNb),
- freq = sum(ClaimNb) / sum(Exposure)
- )
-
-p4 <- ggplot(df_plot, aes(x = DrivAge, y = freq, color = BonusMalus)) +
- geom_point() +
- geom_smooth() +
- labs(x = "Age du conducteur", y = "Frequence", color = "Bonus-Malus") +
- theme_bw()
-p4On propose 4 ajustements :
--
-
- Exclure les âges extrêmes au-delà de 85 ans pour lesquels -l’exposition est très faible. -
- Faire des classes d’âges. -
- Limiter le Bonus-Malus à 125. -
- Faire des classes de Bonus-Malus. -
# Classes d'âges pour Bonus-Malus
-lim_classes <- c(50, 75, 100, 125, Inf)
-
-# Exclusion des donnees "extremes" et faire les regroupement
-df_plot <- dat |>
- filter(DrivAge <= 85, BonusMalus <= 125) |>
- # regroupement en classes d'ages de 5 ans
- mutate(DrivAge = ceiling(pmin(DrivAge, 85) / 5) * 5) |>
- mutate(
- BonusMalus = cut(BonusMalus, breaks = lim_classes, include.lowest = TRUE)
- )
-
-# On regroupe selon les modalites de la DrivAge et de Area
-# l'exposition, le nombre de sinistres et la frequence
-df_plot <- df_plot |>
- group_by(DrivAge, BonusMalus) |>
- summarize(
- exp = sum(Exposure),
- nb_claims = sum(ClaimNb),
- freq = sum(ClaimNb) / sum(Exposure)
- )
-
-# Scatter plot frequence
-p5 <- ggplot(df_plot, aes(x = DrivAge, y = freq, color = BonusMalus)) +
- geom_point() +
- geom_smooth() +
- labs(x = "Age du conducteur", y = "Frequence", color = "Bonus-Malus") +
- theme_bw()
-p5Conclure
-Comparer à présenter comment l’exposition se répartie entre âge et -bonus-malus.
-# Histogramme plot frequence
-p6 <- ggplot(df_plot, aes(x = DrivAge, y = exp, fill = BonusMalus)) +
- geom_bar(stat = "identity", color = "black", alpha = 0.5) +
- scale_x_continuous(breaks = seq(20, 85, 20), limits = c(20, 85)) +
- labs(x = "Age du conducteur", y = "Exposition en années") +
- theme_bw()
-
-
-# Ajustement des legendes pour faire un graphique multiple
-p5 <- p5 +
- theme(
- legend.position = "bottom"
- ) +
- labs(color = "BonusMalus")
-p6 <- p6 +
- theme(
- legend.position = "bottom"
- ) +
- labs(fill = "BonusMalus")
-
-# Creation d'un graphique avec deux figures et une légende commune
-plot_grid(p6, p5, ncol = 2)Bonus - Analyse des couples
-En traitant toutes les variables comme des variables catégorielles, -analyser graphiquement comment évolue la fréquence de sinistres selon -les couples de variables.
-Compléter pour cela la fonction suivante et appliquer la à différents -couples.
-# Fonction d'analyse bivariée
-# df : nom du data.frame
-# var1 : nom de la variable explicative 1
-# var2 : nom de la variable explicative 2
-plot_pairwise_disc <- function(df, var1, var2) {
- df <- rename(df, "varx" = all_of(var1), "vary" = all_of(var2))
-
- # replace variable vname by the binning variable
- if (is.numeric(df$varx)) {
- df <- df |>
- mutate(varx = ntile(varx, 5))
- }
-
- if (is.numeric(df$vary)) {
- df <- df |>
- mutate(vary = ntile(vary, 5), vary = factor(vary))
- }
-
- df |>
- group_by(varx, vary) |>
- summarize(exp = sum(Exposure),
- nb_claims = sum(ClaimNb),
- freq = sum(ClaimNb) / sum(Exposure), .groups = "drop") |>
- ggplot(aes(x = varx, y = freq, colour = vary, group = vary), alpha = 0.3) +
- geom_point() + geom_line() + theme_bw() +
- labs(x = var1, y = "Frequence", colour = var2)
-}p1 <- plot_pairwise_disc(dat, "DrivAge", "BonusMalus")
-p2 <- plot_pairwise_disc(dat, "VehAge", "BonusMalus")
-p3 <- plot_pairwise_disc(dat, "BonusMalus", "VehBrand")
-p4 <- plot_pairwise_disc(dat, "VehBrand", "Area")
-p5 <- plot_pairwise_disc(dat, "BonusMalus", "VehGas")
-p6 <- plot_pairwise_disc(dat, "BonusMalus", "Area")
-p7 <- plot_pairwise_disc(dat, "DrivAge", "Area")
-p8 <- plot_pairwise_disc(dat, "VehPower", "VehGas")
-grid.arrange(p1, p2, p3, p4, p5, p6, p7, p8, ncol = 2)Informations de session
-sessionInfo() -```
-5 Références
-:::
-