Pivoter les données
Le principe de tidy data (une ligne = une observation, une colonne = une variable, une cellule = une valeur) paraît tellement évident que l’on peut se demander comment un jeu de données peut ne pas être tidy. Malheureusement, la plupart des données que vous allez rencontrer ne seront pas tidy. Et ce, pour deux raisons :
- Beaucoup de gens ne connaissent pas le principe de tidy data et il n’est pas évident de le réinventer soi-même à moins de travailler beaucoup de temps avec des données.
- Les données sont souvent organisées pour faciliter d’autres utilations que leur analyse. Par exemple, pour que leur saisie soit la plus simple possible sur le terrain.
Cela signifie que, très souvent, il faudra ranger les données, en amont de l’analyse.
La première étape est toujours d’identifier les variables et les observations.
Parfois, c’est évident.
Parfois, pas du tout et il faudra se creuser la tête un peu plus.
La seconde étape est de résoudre ces problèmes courants :
- Une variable qui est répartie sur plusieurs colonnes
- Une observation qui est répartie sur plusieurs lignes
En général, un jeu de données n’aura qu’un de ces deux problèmes. Il faudrait vraiment ne pas avoir de chance pour avoir les deux !
Heureusement, les fonctions pivot_longer()
et pivot_wider()
du package tidyr sont là !
Plus long
Parfois, les valeurs d’une variable se retrouvent dans le nom des colonnes.
Dans la table suivante, les colonnes qui s’appelent 1999
et 2000
sont en fait les valeurs d’une variable annee
qui n’apparaît pas.
Les valeurs qui sont contenues dans les colonnes 1999
et 2000
représentent les valeurs d’une variable nombre_de_cas
.
Ce qui fait que chaque ligne contient deux observations au lieu d’une seule.
jeu_court <- tribble(
~pays, ~`1999`, ~`2000`,
"Afghanistan", 745, 2666,
"Brésil", 37737, 80488,
"Chine", 212258, 213766,
)
jeu_court
## # A tibble: 3 × 3
## pays `1999` `2000`
## <chr> <dbl> <dbl>
## 1 Afghanistan 745 2666
## 2 Brésil 37737 80488
## 3 Chine 212258 213766
Pour passer un jeu de données comme ceci en format plus long, il faut pivoter les colonnes fautives dans une nouvelle paire de variables.
Trois paramètres sont nécessaires pour procéder à cette opération :
- L’ensemble des colonnes dont les noms sont des valeurs et pas des variables. (Ici :
1999
et2000
) - Le nom de la variable qui contiendra le nom de ces dernières. (Ici :
annee
) - Le nom de la variable qui contiendra les valeurs. (Ici :
nombre_de_cas
)
On appelle la fonction pivot_longer()
de la manière suivante :
pivot_longer(jeu_court, c(`1999`, `2000`), names_to = "annee", values_to = "nombre_de_cas")
## # A tibble: 6 × 3
## pays annee nombre_de_cas
## <chr> <chr> <dbl>
## 1 Afghanistan 1999 745
## 2 Afghanistan 2000 2666
## 3 Brésil 1999 37737
## 4 Brésil 2000 80488
## 5 Chine 1999 212258
## 6 Chine 2000 213766
Pour décrire les colonnes à pivoter, on utilise la notation de dplyr::select()
.
Dans ce cas, les deux colonnes sont listées individuellement, mais il y a bien d’autres manières de sélectionner des colonnes (allez voir l’aide de select()
).
Notons que 1999
et 2000
ne sont pas des noms syntaxiquement valide pour des noms de colonnes (car ne commencent pas par une lettre), il faut donc les entourer de `
(accent grave).
Les variables annee
et nombre_de_cas
n’existent pas dans le jeu de données jeu_court
, leur nom doit donc être entouré de guillements "
.
Dans le résultat final, les colonnes pivotées sont supprimées et de nouvelles colonnes annee
et nombre_de_cas
sont apparues.
Les relations entre les autres variables sont préservées.
pivot_longer()
rend le tableau de données plus long en augmentant le nombre de lignes et en diminuant le nombre de colonnes. Le terme “format long” n’a pas trop de sens finalement, car c’est assez relatif. Il serait plus exact de dire que le tableau A est plus long que le tableau B.
Il existe tout un tas de variantes pour l’utilisation de cette fonction (par exemple, plusieurs variables sont contenues dans le nom des colonnes à pivoter), n’hésitez par à regarder les exemples dans l’aide de la fonction pour se faire une meilleure idée de toutes ses potentialités !
Plus court
pivot_wider()
fait l’inverse de pivot_longer()
. On l’utilise quand une obervation est répartie sur plusieurs lignes (dans le but de faire une analyse multivariée par exemple).
Dans la table suivante, une observation est une combinaison de pays par année, mais chacune est représentée sur deux lignes.
jeu_long <- tibble(
pays = rep(c("Afghanistan", "Brésil", "Chine"), each = 4),
annee = rep(1999:2000, times = 3, each = 2),
type = rep(c("cas", "population"), times = 6),
nombre = c(745, 19987071, 2666, 20595360, 37737, 172006362, 80488, 174504898, 212258, 1272915272, 213766, 1280428583)
)
jeu_long
## # A tibble: 12 × 4
## pays annee type nombre
## <chr> <int> <chr> <dbl>
## 1 Afghanistan 1999 cas 745
## 2 Afghanistan 1999 population 19987071
## 3 Afghanistan 2000 cas 2666
## 4 Afghanistan 2000 population 20595360
## 5 Brésil 1999 cas 37737
## 6 Brésil 1999 population 172006362
## 7 Brésil 2000 cas 80488
## 8 Brésil 2000 population 174504898
## 9 Chine 1999 cas 212258
## 10 Chine 1999 population 1272915272
## 11 Chine 2000 cas 213766
## 12 Chine 2000 population 1280428583
Pour passer un jeu de données comme ceci en format plus court, deux arguments soont nécessaires cette fois :
- Le nom de la colonne qui contient le nom des futures variables. (Ici :
type
) - Le nom de la colonne qui contient les valeurs. (Ici :
nombre
)
Ceci étant trouvé, la fonction pivot_wider()
s’utilise ainsi :
pivot_wider(jeu_long, names_from = type, values_from = nombre)
## # A tibble: 6 × 4
## pays annee cas population
## <chr> <int> <dbl> <dbl>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brésil 1999 37737 172006362
## 4 Brésil 2000 80488 174504898
## 5 Chine 1999 212258 1272915272
## 6 Chine 2000 213766 1280428583
Et visuellement, cela donne :
Les deux fonctions pivot_wider()
et pivot_longer()
sont donc complémentaires.
pivot_longer()
rend les tables plus étroites et plus longues, tandis que pivot_wider()
les rend plus courtes et larges.
Exercices
- Pourquoi
pivot_wider()
etpivot_longer()
ne sont-elles pas parfaitement symétriques ? Condidérez attentivement l’exemple suivant :
stocks <- tibble(
annee = c(2015, 2015, 2016, 2016),
semestre = c(1, 2, 1, 2),
resultat = c(1.88, 0.59, 0.92, 0.17)
)
stocks_pluscourt <- pivot_wider(stocks, names_from = annee, values_from = resultat)
pivot_longer(stocks_pluscourt, `2015`:`2016`, names_to = "annee", values_to = "resultat")
## # A tibble: 4 × 3
## semestre annee resultat
## <dbl> <chr> <dbl>
## 1 1 2015 1.88
## 2 1 2016 0.92
## 3 2 2015 0.59
## 4 2 2016 0.17
(Indice : Regardez la nature de chaque variable)
Donne deux manières de modifier le type de la variable
annee
.Quelle est l’erreur dans ce code ?
pivot_longer(jeu_court, c(1999, 2000), names_to = "year", values_to = "cases")
## Error in `pivot_longer()`:
## ! Can't select columns past the end.
## ℹ Locations 1999 and 2000 don't exist.
## ℹ There are only 3 columns.
- Que va-t-il se passer si vous raccourcissez cette table ? Pourquoi ? Comment pourriez-vous rajouter une colonne pour identifier chaque observation de manière unique ?
people <- tribble(
~name, ~names, ~values,
#-----------------|--------|------
"Phillip Woods", "age", 45,
"Phillip Woods", "height", 186,
"Phillip Woods", "age", 50,
"Jessica Cordero", "age", 37,
"Jessica Cordero", "height", 156
)
- Ranger cette petite table de façon à obtenir une ligne par sexe. Faut-il la rendre plus longue ou plus courte ? Quelles sont les variables ?
preg <- tribble(
~pregnant, ~male, ~female,
"yes", NA, 10,
"no", 20, 12
)
Indice : Obtenez cette table
## # A tibble: 2 × 3
## sexe nombre_personnes_enceintes nombre_personnes
## <chr> <dbl> <dbl>
## 1 male NA 20
## 2 female 10 22
Traduction librement interprétée issue de R for data science de Hadley Wickham : r4ds.had.co.nz/tidy-data.