Chapitre 7 Structurer ses tables
7.1 Pourquoi se pencher sur la structuration des tables ?
Pour bien manipuler des données, leur structuration est fondamentale. Il faut bien savoir ce qu’est :
- une ligne de notre table,
- une colonne de notre table.
Sur une table non agrégée (un répertoire, une table d’enquête…), la structuration naturelle est une ligne par observation (un individu, une entreprise…), une colonne par variable (âge, taille…) sur cette observation.
Mais dès qu’on agrège une telle table pour construire des tables structurées par dimensions d’analyse et indicateurs, se pose toujours la question de savoir ce qu’on va considérer comme des dimensions et comme des indicateurs. Le standard tidy data définit 3 principes pour des données propres :
- chaque variable est une colonne,
- chaque observation est une ligne,
- les unités d’observations différentes sont stockées dans des tables différentes.
Le respect de ces règles va nous amener parfois à devoir changer la définition des lignes et colonnes de nos tables en entrée.
Ci-dessous un exemple simple : la population estimée par département et genre en 2019. Ce fichier est un extrait d’un tableur mis à disposition par l’Insee.
<- read_excel('extdata/estim-pop-dep-sexe-gca-2019.xls')
estim_pop estim_pop
## # A tibble: 104 × 20
## dep lib_dep Ensemble_019ans Ensemble_2039ans Ensemble_4059ans
## <chr> <chr> <dbl> <dbl> <dbl>
## 1 01 Ain 167720 150949 179476
## 2 02 Aisne 131435 115046 137405
## 3 03 Allier 67628 61986 87232
## 4 04 Alpes-de-Haute-Prove… 33883 30028 43039
## 5 05 Hautes-Alpes 30518 28633 37887
## 6 06 Alpes-Maritimes 228072 237427 282270
## 7 07 Ardèche 71385 62186 88572
## 8 08 Ardennes 61006 56583 71821
## 9 09 Ariège 31143 28962 41017
## 10 10 Aube 74510 69537 78475
## # ℹ 94 more rows
## # ℹ 15 more variables: Ensemble_6074ans <dbl>, Ensemble_75ansetplus <dbl>,
## # Ensemble_Total <dbl>, Homme_019ans <dbl>, Homme_2039ans <dbl>,
## # Homme_4059ans <dbl>, Homme_6074ans <dbl>, Homme_75ansetplus <dbl>,
## # Homme_Total <dbl>, Femme_019ans <dbl>, Femme_2039ans <dbl>,
## # Femme_4059ans <dbl>, Femme_6074ans <dbl>, Femme_75ansetplus <dbl>,
## # Femme_Total <dbl>
En quoi ce fichier n’est pas tidy ?
On retrouve 4 variables dans notre fichier : le territoire, le genre, l’âge et la population, et nos colonnes ne correspondent pas à ces variables.
Quel serait la version tidy de notre fichier ?
## # A tibble: 1,872 × 5
## dep lib_dep genre age nombre_individus
## <chr> <chr> <chr> <chr> <dbl>
## 1 01 Ain Ensemble 019ans 167720
## 2 01 Ain Ensemble 2039ans 150949
## 3 01 Ain Ensemble 4059ans 179476
## 4 01 Ain Ensemble 6074ans 102788
## 5 01 Ain Ensemble 75ansetplus 52755
## 6 01 Ain Ensemble Total 653688
## 7 01 Ain Homme 019ans 86359
## 8 01 Ain Homme 2039ans 75242
## 9 01 Ain Homme 4059ans 89278
## 10 01 Ain Homme 6074ans 49523
## # ℹ 1,862 more rows
Comment passer facilement d’un format non tidy à un format tidy ? C’est là qu’intervient le package {tidyr}
.
7.2 Les deux fonctions clefs de {tidyr}
pivot_longer()
permet d’empiler plusieurs colonnes (correspondant à des variables quantitatives). Elles sont repérées par création d’une variable qualitative, à partir de leurs noms. Le résultat est une table au format long.
pivot_wider()
fait l’inverse. Cette fonction crée autant de colonnes qu’il y a de modalités d’une variable qualitative, en remplissant chacune par le contenu d’une variable numérique. Le résultat est une table au format large.
Pour avoir un aperçu illustré de ces fonctions, voir cette animation
Reprenons notre table Insee d’estimation de population. Comment faire pour passer cette table dans le format tidy ?
Première étape, retrouvons notre colonne population
. Pour cela, il nous faut passer notre table au format long, grâce à pivot_longer()
.
<- estim_pop %>%
estim_pop_tidy pivot_longer(-c(dep, lib_dep), values_to = "nombre_individus", names_to = "genre_age")
datatable(estim_pop_tidy)
Si nous voulions retrouver le format large, nous pourrions utiliser pivot_wider()
<- estim_pop_tidy %>%
estim_pop_nontidy pivot_wider(names_from = genre_age, values_from = nombre_individus)
datatable(estim_pop_nontidy)
Nous n’avons pas encore retrouvé nos deux variables genre
et age
, mais une seule variable mélange les deux.
Pour cela, nous pouvons utiliser separate()
du package {tidyr}
.
<- estim_pop_tidy %>%
estim_pop_tidy separate(genre_age, sep = "_", into = c("genre", "age"))
datatable(estim_pop_tidy)
Mais pivot_longer()
permet d’aller encore plus loin en spécifiant sur nos colonnes un moyen de distinguer nos deux variables directement avec l’argument names_sep
.
<- estim_pop %>%
estim_pop_tidy pivot_longer(-c(dep, lib_dep), names_sep = "_", names_to = c("genre", "age"),
values_to = "nombre_individus")
datatable(estim_pop_tidy)
Et pivot_wider()
permet également d’utiliser deux variables pour définir les modalités à convertir en colonnes.
%>%
estim_pop_tidy pivot_wider(names_from = c(genre, age), values_from = nombre_individus) %>%
datatable()
Vous retrouverez une introduction complète à {tidyr}
dans un article très bien fait de la documentation du package (en anglais).
{tidyr}
permet également de transformer des données sous forme de listes en dataframe tidy très simplement.