library(tidyverse) #<-- Au préalable install.packages("tidyverse")9 Tidyverse
Une grande partie du travail en analyse de données consiste à préparer, nettoyer et réorganiser les données afin de les rendre exploitables pour les étapes suivantes, comme la visualisation, la modélisation ou l’interprétation.
Pour accomplir ces tâches, au-delà des techniques de base abordées dans le chapitre précédent, R propose des outils bien plus puissants et spécialisés. Parmi les plus populaires figurent :
- Tidyverse, qui offre une syntaxe claire et cohérente pour manipuler les données de manière intuitive — c’est le sujet de ce chapitre ;
- Le package data.table, reconnu pour sa rapidité et son efficacité sur de grands volumes de données — que nous explorerons dans le chapitre suivant.
Tidyverse est une collection de packages conçus pour simplifier et harmoniser le traitement des données en R. Il comprend notamment les packages suivants : tibble, qui propose une alternative moderne aux dataframes classiques, readr pour l’importation de données, dplyr destiné à faciliter la manipulation des données, tidyr utilisé pour leur organisation et leur restructuration, ainsi que ggplot2, dédié à la visualisation graphique — ce dernier fera d’ailleurs l’objet d’un chapitre à part entière. Ces outils partagent une philosophie de conception cohérente, ce qui rend leur apprentissage ainsi que leur utilisation particulièrement intuitifs.
Les principaux packages du tidyverse peuvent être installés et chargés en une seule fois, comme s’il s’agissait d’un seul package :
Toutefois, chaque package peut également être chargé/installé individuellement selon les besoins sans importer l’ensemble de tidyverse.
9.1 Manipuler les données avec dplyr
“dplyr” vient de “data pliers” (pliers signifie pince), suggérant un outil conçu pour manipuler ou travailler les données de manière intuitive et conviviale.
Les fonctions principales de dplyr sont :
select(): sélectionner des colonnes.
mutate(): ajouter, supprimer ou modifier des colonnes.
filter(): filtrer les lignes selon des conditions.arrange(): trier les lignes.
summarise(): résumer les données, souvent en combinaison avecgroup_by()pour produire des statistiques par groupe.
Dans la suite, ces fonctionnalités seront illustrées à l’aide du jeu de données suivant (déjà utilisé précédemment) :
Taille <- c(167, 192, 173, 174, 172, 167, 171, 185, 163, 170)
Poids <- c(86, 74, 83, 50, 78, 66, 66, 51, 50, 55)
Prog <- c("Bac", "Bac", "Master", "Bac", "Bac", "Master", "Master", NA, "Bac", "Bac")
Sexe <- c("H", "H", "F", "H", "H", "H", "F", "H", "H", "H") |> factor()
df <- data.frame(Taille, Poids, Prog, Sexe)
df Taille Poids Prog Sexe
1 167 86 Bac H
2 192 74 Bac H
3 173 83 Master F
4 174 50 Bac H
5 172 78 Bac H
6 167 66 Master H
7 171 66 Master F
8 185 51 <NA> H
9 163 50 Bac H
10 170 55 Bac H
La présentation qui suit offre une introduction aux concepts fondamentaux. Pour des informations plus complètes, consultez la documentation officielle : https://dplyr.tidyverse.org/.
Sélectionner des colonnes avec select()
select(df, 1:2) # Sélection par position : colonnes 1 et 2
select(df, c(Poids, Prog)) # Sélection par noms
select(df, Poids, Prog) # Idem
select(df, -c(Poids, Prog)) # Exclusion par noms
select(df, !c(Poids, Prog)) # IdemOutput
Taille Poids
1 167 86
2 192 74
3 173 83
4 174 50
5 172 78
6 167 66
7 171 66
8 185 51
9 163 50
10 170 55
Poids Prog
1 86 Bac
2 74 Bac
3 83 Master
4 50 Bac
5 78 Bac
6 66 Master
7 66 Master
8 51 <NA>
9 50 Bac
10 55 Bac
Poids Prog
1 86 Bac
2 74 Bac
3 83 Master
4 50 Bac
5 78 Bac
6 66 Master
7 66 Master
8 51 <NA>
9 50 Bac
10 55 Bac
Taille Sexe
1 167 H
2 192 H
3 173 F
4 174 H
5 172 H
6 167 H
7 171 F
8 185 H
9 163 H
10 170 H
Taille Sexe
1 167 H
2 192 H
3 173 F
4 174 H
5 172 H
6 167 H
7 171 F
8 185 H
9 163 H
10 170 H
La fonction select() s’accompagne d’un ensemble d’outils qui permettent de cibler les colonnes à sélectionner de manière expressive, flexible et cohérente. Par example, des fonctions comme starts_with(), ends_with(), contains() ou where() facilitent la sélection des colonnes selon des critères liés à leurs noms ou à leur type. Exemple :
# Sélectionner toutes les colonnes numériques
1select(df, where(is.numeric))
# Sélectionne toutes les colonnes dont le nom contient "o"
select(df, contains("o"))- 1
-
Cela fonctionne aussi avec d’autres tests/fonctions comme
is.character(),is.logical(),is.double(), etc; voir l’aide dewhere().
Output
Taille Poids
1 167 86
2 192 74
3 173 83
4 174 50
5 172 78
6 167 66
7 171 66
8 185 51
9 163 50
10 170 55
Poids Prog
1 86 Bac
2 74 Bac
3 83 Master
4 50 Bac
5 78 Bac
6 66 Master
7 66 Master
8 51 <NA>
9 50 Bac
10 55 Bac
Pour voir les options de sélection disponibles, consultez l’aide de la fonction (?select) ainsi que dans sa documentation officielle en ligne.
Transfomer des colonnes avec mutate()
La fonction mutate() permet de créer de nouvelles colonnes ou de modifier des colonnes existantes. Contrairement à la fonction de base transform(), mutate() autorise l’utilisation immédiate des variables nouvellement créées. Exemple :
df |> mutate(
Taille.m = 0.01 * Taille,
Poids = Poids * 1000,
Taille = NULL,
imc = (Poids / 1000) / Taille.m^2
) Poids Prog Sexe Taille.m imc
1 86000 Bac H 1.67 30.83653
2 74000 Bac H 1.92 20.07378
3 83000 Master F 1.73 27.73230
4 50000 Bac H 1.74 16.51473
5 78000 Bac H 1.72 26.36560
6 66000 Master H 1.67 23.66524
7 66000 Master F 1.71 22.57105
8 51000 <NA> H 1.85 14.90139
9 50000 Bac H 1.63 18.81892
10 55000 Bac H 1.70 19.03114
Il est fréquent de veloir appliquer une même transformation à plusieurs variables. La fonction across() simplifie cette opération. Elle prend deux arguments principaux : (i) le sous-ensemble de colonnes de la dataframe; (ii) une ou plusieurs fonctions à appliquer aux colonnes sélectionnées. Exemple :
# Applique log() aux colonnes Taille et Poids
1mutate(df, across(.cols = c(Taille, Poids), .fns = log))
# Applique log() à toutes les colonnes numériques
mutate(df, across(where(is.numeric), log))
# Applique log() et log10() à toutes les colonnes numériques
mutate(df, across(where(is.numeric), list(log10 = log10, log = log)))- 1
-
L’utilisation de
across()exige de spécifier à la fois les colonnes à sélectionner ET la ou les fonctions à appliquer à l’intérieur des parenthèses. Ainsi, le code suivant génère une erreur :mutate(df, across(c(Taille, Poids)), log)car la fonctionlog()est placée en dehors deacross().
Output
Taille Poids Prog Sexe
1 5.117994 4.454347 Bac H
2 5.257495 4.304065 Bac H
3 5.153292 4.418841 Master F
4 5.159055 3.912023 Bac H
5 5.147494 4.356709 Bac H
6 5.117994 4.189655 Master H
7 5.141664 4.189655 Master F
8 5.220356 3.931826 <NA> H
9 5.093750 3.912023 Bac H
10 5.135798 4.007333 Bac H
Taille Poids Prog Sexe
1 5.117994 4.454347 Bac H
2 5.257495 4.304065 Bac H
3 5.153292 4.418841 Master F
4 5.159055 3.912023 Bac H
5 5.147494 4.356709 Bac H
6 5.117994 4.189655 Master H
7 5.141664 4.189655 Master F
8 5.220356 3.931826 <NA> H
9 5.093750 3.912023 Bac H
10 5.135798 4.007333 Bac H
Taille Poids Prog Sexe Taille_log10 Taille_log Poids_log10 Poids_log
1 167 86 Bac H 2.222716 5.117994 1.934498 4.454347
2 192 74 Bac H 2.283301 5.257495 1.869232 4.304065
3 173 83 Master F 2.238046 5.153292 1.919078 4.418841
4 174 50 Bac H 2.240549 5.159055 1.698970 3.912023
5 172 78 Bac H 2.235528 5.147494 1.892095 4.356709
6 167 66 Master H 2.222716 5.117994 1.819544 4.189655
7 171 66 Master F 2.232996 5.141664 1.819544 4.189655
8 185 51 <NA> H 2.267172 5.220356 1.707570 3.931826
9 163 50 Bac H 2.212188 5.093750 1.698970 3.912023
10 170 55 Bac H 2.230449 5.135798 1.740363 4.007333
Filtrer des lignes avec filter()
La fonction filter() permet de sélectionner uniquement les lignes d’un dataframe qui répondent à une ou plusieurs conditions logiques. Lorsque plusieurs conditions sont fournies séparément, filter() les combine implicitement à l’aide d’un opérateur logique ET (&).
filter(df, Sexe == "H") # Hommes uniquement
filter(df, is.na(Prog)) # Lignes où 'Prog' est manquant
filter(df, Sexe == "H" & Poids < mean(Poids)) # Hommes avec poids sous la moyenne
filter(df, Sexe == "H", Poids < mean(Poids)) # IdemOutput
Taille Poids Prog Sexe
1 167 86 Bac H
2 192 74 Bac H
3 174 50 Bac H
4 172 78 Bac H
5 167 66 Master H
6 185 51 <NA> H
7 163 50 Bac H
8 170 55 Bac H
Taille Poids Prog Sexe
1 185 51 <NA> H
Taille Poids Prog Sexe
1 174 50 Bac H
2 185 51 <NA> H
3 163 50 Bac H
4 170 55 Bac H
Taille Poids Prog Sexe
1 174 50 Bac H
2 185 51 <NA> H
3 163 50 Bac H
4 170 55 Bac H
Notez que filter(), comme la plupart des fonctions du tidyverse, adopte un mécanisme d’évaluation non standard permettant d’utiliser directement les noms de colonnes sans les préfixer par $, car les expressions sont évaluées dans le contexte du dataframe fourni. Ce comportement ressemble à celui de certaines fonctions du R de base comme subset(), mais le tidyverse repose sur une approche différente appelé tidy evaluation.
Ordonner les lignes avec arange()
La fonction arrange() permet d’ordonner les lignes d’un tableau en fonction des valeurs d’une ou plusieurs colonnes. Lorsque plusieurs colonnes sont indiquées, le tri se fait d’abord selon la première, puis — en cas de valeurs identiques — selon la deuxième, et ainsi de suite. Pour trier en ordre décroissant, on utilise la fonction desc() à l’intérieur de arrange(). Exemple :
arrange(df, Taille, desc(Poids)) Taille Poids Prog Sexe
1 163 50 Bac H
2 167 86 Bac H
3 167 66 Master H
4 170 55 Bac H
5 171 66 Master F
6 172 78 Bac H
7 173 83 Master F
8 174 50 Bac H
9 185 51 <NA> H
10 192 74 Bac H
Résumer et agréger avec summarize() et group_by()
Agréger des données consiste à regrouper et à résumer des informations issues de plusieurs observations, généralement selon une ou plusieurs variables clés. Cela permet de produire des valeurs synthétiques — telles que des moyennes, des totaux ou des médianes — qui facilitent l’analyse comparative et la synthèse globale.
La fonction summarise() permet justement de créer ces résumés statistiques, à partir d’une ou plusieurs colonnes. Exemple :
# Moyennes de Taille et Poids
summarise(df, mean.Taille = mean(Taille), mean.Poids = mean(Poids))
# Moyennes et écarts-types de toutes les variables numériques
summarise(df, across(where(is.numeric), list(mean = mean, sd = sd))) mean.Taille mean.Poids
1 173.4 65.9
Taille_mean Taille_sd Poids_mean Poids_sd
1 173.4 8.758488 65.9 13.96384
La fonction group_by() permet, quant à elle, de regrouper les observations (lignes) en fonction des valeurs d’une ou plusieurs variables. Exemple :
group_by(df, Sexe)# A tibble: 10 × 4
# Groups: Sexe [2]
Taille Poids Prog Sexe
<dbl> <dbl> <chr> <fct>
1 167 86 Bac H
2 192 74 Bac H
3 173 83 Master F
4 174 50 Bac H
5 172 78 Bac H
6 167 66 Master H
7 171 66 Master F
8 185 51 <NA> H
9 163 50 Bac H
10 170 55 Bac H
group_by() ne modifie pas les données, mais ajoute une mention Groups dans l’affichage du tableau pour signaler qu’en interne, les données sont désormais divisées/taguées par groupe. Toutes les opérations suivantes — comme summarise(), mutate() ou filter() — seront alors exécutées séparément au sein de chaque groupe. Exemple :
# Moyennes de taille et poids par Sexe
df |> group_by(Sexe) |>
summarise(mean.Taille = mean(Taille), mean.Poids = mean(Poids))
# Taille relative à la moyenne du groupe
df |> group_by(Sexe) |>
mutate(TAILLE = Taille / mean(Taille))
# Individus plus petits que la moyenne du groupe
df |> group_by(Sexe) |>
filter(Taille < mean(Taille))Output
# A tibble: 2 × 3
Sexe mean.Taille mean.Poids
<fct> <dbl> <dbl>
1 F 172 74.5
2 H 174. 63.8
# A tibble: 10 × 5
# Groups: Sexe [2]
Taille Poids Prog Sexe TAILLE
<dbl> <dbl> <chr> <fct> <dbl>
1 167 86 Bac H 0.961
2 192 74 Bac H 1.11
3 173 83 Master F 1.01
4 174 50 Bac H 1.00
5 172 78 Bac H 0.990
6 167 66 Master H 0.961
7 171 66 Master F 0.994
8 185 51 <NA> H 1.06
9 163 50 Bac H 0.938
10 170 55 Bac H 0.978
# A tibble: 6 × 4
# Groups: Sexe [2]
Taille Poids Prog Sexe
<dbl> <dbl> <chr> <fct>
1 167 86 Bac H
2 172 78 Bac H
3 167 66 Master H
4 171 66 Master F
5 163 50 Bac H
6 170 55 Bac H
Dans ce contexte, une fonction bien utile est n(). Elle permet de compter le nombre d’observations. Elles est souvent utilisée avec summarise() :
# Nombre total d'observations
summarise(df, eff = n())
# Nombre total d'observations par Sexe
df |> group_by(Sexe) |>
summarise(eff = n())
# Calcule l'effectif par Sexe et ajoute les pourcentages
df |> group_by(Sexe) |>
summarise(eff = n()) |>
mutate(pourcentage = eff / sum(eff) * 100) eff
1 10
# A tibble: 2 × 2
Sexe eff
<fct> <int>
1 F 2
2 H 8
# A tibble: 2 × 3
Sexe eff pourcentage
<fct> <int> <dbl>
1 F 2 20
2 H 8 80
Une façon alternative et souvent plus pratique d’effectuer des comptages consiste à utiliser la fonction count(). Cette fonction permet de calculer directement le nombre d’occurrences d’une ou plusieurs variables, sans passer par group_by() suivi de summarise(). Exemple :
df |> count(Sexe) |> mutate(pourcentage = n / sum(n) * 100)
df |> count(Sexe, Prog) Sexe n pourcentage
1 F 2 20
2 H 8 80
Sexe Prog n
1 F Master 2
2 H Bac 6
3 H Master 1
4 H <NA> 1
Introduit dans dplyr 1.1.0, l’argument .by offre une syntaxe plus concise pour effectuer des opérations par groupe, sans avoir à recourir à group_by(). Il permet de spécifier directement les variables de regroupement à l’intérieur de fonctions comme summarise(), mutate() ou filter().
df |> summarise(mean.Taille = mean(Taille), mean.Poids = mean(Poids), .by = Sexe)
df |> mutate(TAILLE = Taille / mean(Taille), .by = Sexe)
df |> filter(Taille < mean(Taille), .by = Sexe)
df |> count(Sexe, Prog) |> mutate(pourcentage = n / sum(n) * 100, .by = Sexe) Sexe mean.Taille mean.Poids
1 H 173.75 63.75
2 F 172.00 74.50
Taille Poids Prog Sexe TAILLE
1 167 86 Bac H 0.9611511
2 192 74 Bac H 1.1050360
3 173 83 Master F 1.0058140
4 174 50 Bac H 1.0014388
5 172 78 Bac H 0.9899281
6 167 66 Master H 0.9611511
7 171 66 Master F 0.9941860
8 185 51 <NA> H 1.0647482
9 163 50 Bac H 0.9381295
10 170 55 Bac H 0.9784173
Taille Poids Prog Sexe
1 167 86 Bac H
2 172 78 Bac H
3 167 66 Master H
4 171 66 Master F
5 163 50 Bac H
6 170 55 Bac H
Sexe Prog n pourcentage
1 F Master 2 100.0
2 H Bac 6 75.0
3 H Master 1 12.5
4 H <NA> 1 12.5
Notez que group_by() et l’argument .by peuvent être utilisés avec plusieurs variables simultanément. Pour cela, on utilise la syntaxe group_by(var1, var2, ...) ou .by = c(var1, var2, ...); voir ?dplyr_by pour plus de détails.
9.2 Remodeler un tableu avec tidyr
Les données ne sont pas toujours organisées de manière optimale pour l’analyse statistique ou la visualisation. Il est donc souvent nécessaire de modifier la structure d’un tableau de données pour rendre celui-ci plus exploitable. Le package tidyr du tidyverse propose des fonctions simples et puissantes pour effectuer ces transformations.
Parmi les plus courantes :
pivot_longer()permet de convertir un tableau large en format long, en regroupant plusieurs colonnes sous une même variable.pivot_wider()fait l’inverse : il étale les valeurs d’une variable sur plusieurs colonnes pour obtenir un format plus large.
Voyons comment remodeler un jeu de données à travers un exemple concret. Voici, à titre d’exemple, notre dataframe de départ (en format long, où chaque observation occupe une ligne et chaque variable (unique) occupe une colonne) :
df <- data.frame(
Contry = c(rep("A", 3), rep("B", 3), rep("C", 3)),
Year = rep(c(2000, 2010, 2020), 3),
Metric = c(10, 13, 15, 20, 23, 25, 30, 33, 35)
)
df Contry Year Metric
1 A 2000 10
2 A 2010 13
3 A 2020 15
4 B 2000 20
5 B 2010 23
6 B 2020 25
7 C 2000 30
8 C 2010 33
9 C 2020 35
pivot_wider()
dfW <- pivot_wider(df,
names_from = Year, # Crée des colonnes à partir de `Year`
values_from = Metric, # Remplit ces colonnes avec les valeurs de `Metric`
names_prefix = "Yr_" # Ajoute le préfixe "Yr_" aux noms de colonnes
) |> print()# A tibble: 3 × 4
Contry Yr_2000 Yr_2010 Yr_2020
<chr> <dbl> <dbl> <dbl>
1 A 10 13 15
2 B 20 23 25
3 C 30 33 35
Dans dfW, la variable Year se trouve étalée sur plusieurs colonnes : c’est ce qu’on appelle le format wide (ou format large).
pivot_longer()
pivot_longer(dfW,
cols = starts_with("Yr"), # Sélectionne les colonnes à transformer en lignes (celles commençant par "Yr")
names_to = "Year", # Crée une colonne "Year" contenant les noms des colonnes sélectionnées
values_to = "Metric", # Crée une colonne "Metric" contenant les valeurs correspondantes
names_prefix = "Yr_" # Supprime le préfixe "Yr_" des noms avant de les insérer dans "Year"
)# A tibble: 9 × 3
Contry Year Metric
<chr> <chr> <dbl>
1 A 2000 10
2 A 2010 13
3 A 2020 15
4 B 2000 20
5 B 2010 23
6 B 2020 25
7 C 2000 30
8 C 2010 33
9 C 2020 35
Les fonctions pivot_longer() et pivot_wider() en particulier, ainsi que le package tidyr de manière générale, offrent de nombreuses options pour restructurer les données selon les besoins. Pour explorer davantage leurs fonctionnalités, consulter des exemples concrets et découvrir d’autres cas d’usage, il est recommandé de se référer à la documentation officielle https://tidyr.tidyverse.org/.