Forfait ranger inclus au cœur de l'une des bibliothèques les plus populaires du langage R - Tidyverse.
L'objectif principal du package est de présenter les données sous une forme précise.
Déjà disponible sur Habré dédié à ce package, mais il date de 2015. Et je veux vous parler des changements les plus récents, annoncés il y a quelques jours par son auteur, Hedley Wickham.

SJK: Est-ce que collect() et spread() seront obsolètes ?
Hadley Wickham: Dans une certaine mesure. Nous ne recommanderons plus l’utilisation de ces fonctions et n’y corrigerons plus les bugs, mais elles continueront d’être présentes dans le package dans leur état actuel.
Teneur
Si vous êtes intéressé par l'analyse des données, vous pourriez être intéressé par mon и canaux. La plupart du contenu est dédié au langage R.
Concept TidyData
Objectif ranger - vous aider à mettre les données sous une forme dite soignée. Les données soignées sont des données où :
- Chaque variable est dans une colonne.
- Chaque observation est une chaîne.
- Chaque valeur est une cellule.
Il est beaucoup plus facile et pratique de travailler avec des données présentées de manière ordonnée lors de l'analyse.
Principales fonctions incluses dans le package Tidyr
Tidyr contient un ensemble de fonctions conçues pour transformer des tables :
fill()— remplir les valeurs manquantes dans une colonne avec les valeurs précédentes ;separate()— divise un champ en plusieurs à l'aide d'un séparateur ;unite()— effectue l'opération de combinaison de plusieurs champs en un seul, l'action inverse de la fonctionseparate();pivot_longer()— une fonction qui convertit les données du format large au format long ;pivot_wider()- une fonction qui convertit les données du format long au format large. L'opération inverse de celle effectuée par la fonctionpivot_longer().gather()obsolète — une fonction qui convertit les données du format large au format long ;spread()obsolète - une fonction qui convertit les données du format long au format large. L'opération inverse de celle effectuée par la fonctiongather().
Nouveau concept pour convertir des données du format large au format long et vice versa
Auparavant, les fonctions étaient utilisées pour ce type de transformation gather() и spread(). Au fil des années d'existence de ces fonctions, il est devenu évident que pour la plupart des utilisateurs, y compris l'auteur du package, les noms de ces fonctions et leurs arguments n'étaient pas tout à fait évidents, ce qui rendait difficile de les trouver et de comprendre laquelle de ces fonctions convertit un cadre de date du format large au format long, et vice versa.
À cet égard, dans ranger Deux nouvelles fonctions importantes ont été ajoutées, conçues pour transformer les cadres de date.
De nouvelles fonctionnalités pivot_longer() и pivot_wider() ont été inspirés par certaines des fonctionnalités du package données c, créé par John Mount et Nina Zumel.
Installation de la version la plus récente de Tidyr 0.8.3.9000
Pour installer la nouvelle version la plus récente du package ranger 0.8.3.9000, là où de nouvelles fonctionnalités sont disponibles, utilisez le code suivant.
devtools::install_github("tidyverse/tidyr")
Au moment de la rédaction, ces fonctions ne sont disponibles que dans la version dev du package sur GitHub.
Transition vers de nouvelles fonctionnalités
En fait, il n'est pas difficile de transférer d'anciens scripts pour travailler avec de nouvelles fonctions ; pour une meilleure compréhension, je prendrai un exemple de la documentation des anciennes fonctions et montrerai comment les mêmes opérations sont effectuées en utilisant les nouvelles. pivot_*() fonctions.
Convertissez le format large en format long.
Exemple de code de la documentation de la fonction de collecte
# example
library(dplyr)
stocks <- data.frame(
time = as.Date('2009-01-01') + 0:9,
X = rnorm(10, 0, 1),
Y = rnorm(10, 0, 2),
Z = rnorm(10, 0, 4)
)
# old
stocks_gather <- stocks %>% gather(key = stock,
value = price,
-time)
# new
stocks_long <- stocks %>% pivot_longer(cols = -time,
names_to = "stock",
values_to = "price")
Conversion du format long en format large.
Exemple de code de la documentation de la fonction spread
# old
stocks_spread <- stocks_gather %>% spread(key = stock,
value = price)
# new
stock_wide <- stocks_long %>% pivot_wider(names_from = "stock",
values_from = "price")
Parce que dans les exemples ci-dessus de travail avec pivot_longer() и pivot_wider(), dans le tableau d'origine les stocks aucune colonne répertoriée dans les arguments noms_à и valeurs_à leurs noms doivent être entre guillemets.
Un tableau qui vous aidera à comprendre plus facilement comment passer au travail avec un nouveau concept ranger.

Remarque de l'auteur
Tout le texte ci-dessous est adaptatif, je dirais même traduction gratuite sur le site officiel de la bibliothèque Tidyverse.
Un exemple simple de conversion de données du format large au format long
pivot_longer () — allonge les ensembles de données en réduisant le nombre de colonnes et en augmentant le nombre de lignes.

Pour exécuter les exemples présentés dans l'article, vous devez d'abord connecter les packages nécessaires :
library(tidyr)
library(dplyr)
library(readr)Disons que nous avons un tableau avec les résultats d'une enquête qui (entre autres choses) interrogeait les gens sur leur religion et leur revenu annuel :
#> # A tibble: 18 x 11
#> religion `<$10k` `$10-20k` `$20-30k` `$30-40k` `$40-50k` `$50-75k`
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Agnostic 27 34 60 81 76 137
#> 2 Atheist 12 27 37 52 35 70
#> 3 Buddhist 27 21 30 34 33 58
#> 4 Catholic 418 617 732 670 638 1116
#> 5 Don’t k… 15 14 15 11 10 35
#> 6 Evangel… 575 869 1064 982 881 1486
#> 7 Hindu 1 9 7 9 11 34
#> 8 Histori… 228 244 236 238 197 223
#> 9 Jehovah… 20 27 24 24 21 30
#> 10 Jewish 19 19 25 25 30 95
#> # … with 8 more rows, and 4 more variables: `$75-100k` <dbl>,
#> # `$100-150k` <dbl>, `>150k` <dbl>, `Don't know/refused` <dbl>Ce tableau contient les données sur la religion des répondants en lignes et les niveaux de revenus sont répartis entre les noms de colonnes. Le nombre de répondants de chaque catégorie est stocké dans les valeurs des cellules à l'intersection de la religion et du niveau de revenu. Pour remettre le tableau dans un format soigné et correct, il suffit d'utiliser pivot_longer():
pew %>%
pivot_longer(cols = -religion, names_to = "income", values_to = "count")pew %>%
pivot_longer(cols = -religion, names_to = "income", values_to = "count")
#> # A tibble: 180 x 3
#> religion income count
#> <chr> <chr> <dbl>
#> 1 Agnostic <$10k 27
#> 2 Agnostic $10-20k 34
#> 3 Agnostic $20-30k 60
#> 4 Agnostic $30-40k 81
#> 5 Agnostic $40-50k 76
#> 6 Agnostic $50-75k 137
#> 7 Agnostic $75-100k 122
#> 8 Agnostic $100-150k 109
#> 9 Agnostic >150k 84
#> 10 Agnostic Don't know/refused 96
#> # … with 170 more rowsArguments de la fonction pivot_longer()
- Premier argument cols, décrit les colonnes qui doivent être fusionnées. Dans ce cas, toutes les colonnes sauf Paisible.
- Argument noms_à donne le nom de la variable qui sera créée à partir des noms des colonnes que nous avons concaténées.
- valeurs_à donne le nom d'une variable qui sera créée à partir des données stockées dans les valeurs des cellules des colonnes fusionnées.
spécification
Il s'agit d'une nouvelle fonctionnalité du package ranger, qui n'était auparavant pas disponible lorsque vous utilisiez des fonctions héritées.
Une spécification est un bloc de données dont chaque ligne correspond à une colonne dans le nouveau bloc de dates de sortie et à deux colonnes spéciales qui commencent par :
- . Nom contient le nom de la colonne d'origine.
- .valeur contient le nom de la colonne qui contiendra les valeurs des cellules.
Les colonnes restantes de la spécification reflètent la façon dont la nouvelle colonne affichera le nom des colonnes compressées de . Nom.
La spécification décrit les métadonnées stockées dans un nom de colonne, avec une ligne pour chaque colonne et une colonne pour chaque variable combinée avec le nom de colonne, ce qui peut sembler déroutant pour le moment, mais après avoir examiné quelques exemples, cela deviendra beaucoup plus clair.
Le but de la spécification est que vous pouvez récupérer, modifier et définir de nouvelles métadonnées pour la trame de données en cours de conversion.
Pour travailler avec des spécifications lors de la conversion d'un tableau d'un format large en un format long, utilisez la fonction pivot_longer_spec().
Le fonctionnement de cette fonction est qu'elle prend n'importe quelle période et génère ses métadonnées de la manière décrite ci-dessus.
À titre d'exemple, prenons l'ensemble de données who fourni avec le package. ranger. Cet ensemble de données contient des informations fournies par l'organisation internationale de la santé sur l'incidence de la tuberculose.
who
#> # A tibble: 7,240 x 60
#> country iso2 iso3 year new_sp_m014 new_sp_m1524 new_sp_m2534
#> <chr> <chr> <chr> <int> <int> <int> <int>
#> 1 Afghan… AF AFG 1980 NA NA NA
#> 2 Afghan… AF AFG 1981 NA NA NA
#> 3 Afghan… AF AFG 1982 NA NA NA
#> 4 Afghan… AF AFG 1983 NA NA NA
#> 5 Afghan… AF AFG 1984 NA NA NA
#> 6 Afghan… AF AFG 1985 NA NA NA
#> 7 Afghan… AF AFG 1986 NA NA NA
#> 8 Afghan… AF AFG 1987 NA NA NA
#> 9 Afghan… AF AFG 1988 NA NA NA
#> 10 Afghan… AF AFG 1989 NA NA NA
#> # … with 7,230 more rows, and 53 more variablesConstruisons sa spécification.
spec <- who %>%
pivot_longer_spec(new_sp_m014:newrel_f65, values_to = "count")#> # A tibble: 56 x 3
#> .name .value name
#> <chr> <chr> <chr>
#> 1 new_sp_m014 count new_sp_m014
#> 2 new_sp_m1524 count new_sp_m1524
#> 3 new_sp_m2534 count new_sp_m2534
#> 4 new_sp_m3544 count new_sp_m3544
#> 5 new_sp_m4554 count new_sp_m4554
#> 6 new_sp_m5564 count new_sp_m5564
#> 7 new_sp_m65 count new_sp_m65
#> 8 new_sp_f014 count new_sp_f014
#> 9 new_sp_f1524 count new_sp_f1524
#> 10 new_sp_f2534 count new_sp_f2534
#> # … with 46 more rowschamps Pays, iso2, iso3 sont déjà des variables. Notre tâche est d'inverser les colonnes avec nouveau_sp_m014 sur newrel_f65.
Les noms de ces colonnes stockent les informations suivantes :
- Préfixe
new_indique que la colonne contient des données sur les nouveaux cas de tuberculose, la période actuelle contient des informations uniquement sur les nouvelles maladies, donc ce préfixe dans le contexte actuel n'a aucune signification. sp/rel/sp/epdécrit une méthode pour diagnostiquer une maladie.m/fle sexe du patient.014/1524/2535/3544/4554/65tranche d’âge des patients.
Nous pouvons diviser ces colonnes en utilisant la fonction extract()en utilisant une expression régulière.
spec <- spec %>%
extract(name, c("diagnosis", "gender", "age"), "new_?(.*)_(.)(.*)")#> # A tibble: 56 x 5
#> .name .value diagnosis gender age
#> <chr> <chr> <chr> <chr> <chr>
#> 1 new_sp_m014 count sp m 014
#> 2 new_sp_m1524 count sp m 1524
#> 3 new_sp_m2534 count sp m 2534
#> 4 new_sp_m3544 count sp m 3544
#> 5 new_sp_m4554 count sp m 4554
#> 6 new_sp_m5564 count sp m 5564
#> 7 new_sp_m65 count sp m 65
#> 8 new_sp_f014 count sp f 014
#> 9 new_sp_f1524 count sp f 1524
#> 10 new_sp_f2534 count sp f 2534
#> # … with 46 more rowsVeuillez noter la colonne . Nom devrait rester inchangé puisqu'il s'agit de notre index dans les noms de colonnes de l'ensemble de données d'origine.
Sexe et âge (colonnes le sexe и âge) ont des valeurs fixes et connues, il est donc recommandé de convertir ces colonnes en facteurs :
spec <- spec %>%
mutate(
gender = factor(gender, levels = c("f", "m")),
age = factor(age, levels = unique(age), ordered = TRUE)
) Enfin, afin d'appliquer la spécification que nous avons créée au cadre de date d'origine pour qui nous devons utiliser un argument spec en fonction pivot_longer().
who %>% pivot_longer(spec = spec)
#> # A tibble: 405,440 x 8
#> country iso2 iso3 year diagnosis gender age count
#> <chr> <chr> <chr> <int> <chr> <fct> <ord> <int>
#> 1 Afghanistan AF AFG 1980 sp m 014 NA
#> 2 Afghanistan AF AFG 1980 sp m 1524 NA
#> 3 Afghanistan AF AFG 1980 sp m 2534 NA
#> 4 Afghanistan AF AFG 1980 sp m 3544 NA
#> 5 Afghanistan AF AFG 1980 sp m 4554 NA
#> 6 Afghanistan AF AFG 1980 sp m 5564 NA
#> 7 Afghanistan AF AFG 1980 sp m 65 NA
#> 8 Afghanistan AF AFG 1980 sp f 014 NA
#> 9 Afghanistan AF AFG 1980 sp f 1524 NA
#> 10 Afghanistan AF AFG 1980 sp f 2534 NA
#> # … with 405,430 more rowsTout ce que nous venons de faire peut être schématiquement représenté comme suit :

Spécification utilisant plusieurs valeurs (.value)
Dans l'exemple ci-dessus, la colonne de spécification .valeur ne contenait qu’une seule valeur, c’est le cas dans la plupart des cas.
Mais parfois, une situation peut survenir lorsque vous devez collecter des données à partir de colonnes avec différents types de données dans les valeurs. Utiliser une fonction héritée spread() ce serait assez difficile à faire.
L'exemple ci-dessous est tiré de au colis données.table.
Créons un dataframe de formation.
family <- tibble::tribble(
~family, ~dob_child1, ~dob_child2, ~gender_child1, ~gender_child2,
1L, "1998-11-26", "2000-01-29", 1L, 2L,
2L, "1996-06-22", NA, 2L, NA,
3L, "2002-07-11", "2004-04-05", 2L, 2L,
4L, "2004-10-10", "2009-08-27", 1L, 1L,
5L, "2000-12-05", "2005-02-28", 2L, 1L,
)
family <- family %>% mutate_at(vars(starts_with("dob")), parse_date)#> # A tibble: 5 x 5
#> family dob_child1 dob_child2 gender_child1 gender_child2
#> <int> <date> <date> <int> <int>
#> 1 1 1998-11-26 2000-01-29 1 2
#> 2 2 1996-06-22 NA 2 NA
#> 3 3 2002-07-11 2004-04-05 2 2
#> 4 4 2004-10-10 2009-08-27 1 1
#> 5 5 2000-12-05 2005-02-28 2 1Le cadre de date créé contient des données sur les enfants d'une famille dans chaque ligne. Les familles peuvent avoir un ou deux enfants. Pour chaque enfant, des données sont fournies sur la date de naissance et le sexe, et les données pour chaque enfant sont dans des colonnes séparées ; notre tâche est d'amener ces données au format correct pour l'analyse.
Veuillez noter que nous disposons de deux variables avec des informations sur chaque enfant : son sexe et sa date de naissance (colonnes avec le préfixe baptême contenir la date de naissance, les colonnes avec préfixe le sexe contenir le sexe de l'enfant). Le résultat attendu est qu’ils apparaissent dans des colonnes distinctes. Nous pouvons le faire en générant une spécification dans laquelle la colonne .value aura deux significations différentes.
spec <- family %>%
pivot_longer_spec(-family) %>%
separate(col = name, into = c(".value", "child"))%>%
mutate(child = parse_number(child))
#> # A tibble: 4 x 3
#> .name .value child
#> <chr> <chr> <dbl>
#> 1 dob_child1 dob 1
#> 2 dob_child2 dob 2
#> 3 gender_child1 gender 1
#> 4 gender_child2 gender 2Examinons donc étape par étape les actions effectuées par le code ci-dessus.
pivot_longer_spec(-family)— créer une spécification qui compresse toutes les colonnes existantes à l'exception de la colonne famille.separate(col = name, into = c(".value", "child"))- diviser la colonne . Nom, qui contient les noms des champs sources, en utilisant le trait de soulignement et en saisissant les valeurs résultantes dans les colonnes .valeur и enfant.mutate(child = parse_number(child))— transformer les valeurs du champ enfant du texte au type de données numérique.
Nous pouvons maintenant appliquer la spécification résultante à la trame de données d'origine et amener la table à la forme souhaitée.
family %>%
pivot_longer(spec = spec, na.rm = T)#> # A tibble: 9 x 4
#> family child dob gender
#> <int> <dbl> <date> <int>
#> 1 1 1 1998-11-26 1
#> 2 1 2 2000-01-29 2
#> 3 2 1 1996-06-22 2
#> 4 3 1 2002-07-11 2
#> 5 3 2 2004-04-05 2
#> 6 4 1 2004-10-10 1
#> 7 4 2 2009-08-27 1
#> 8 5 1 2000-12-05 2
#> 9 5 2 2005-02-28 1Nous utilisons l'argumentation na.rm = TRUE, car la forme actuelle des données force la création de lignes supplémentaires pour les observations inexistantes. Parce que la famille 2 n'a qu'un seul enfant, na.rm = TRUE garantit que la famille 2 aura une ligne dans la sortie.
Conversion des cadres de date du format long au format large
pivot_wider() - est la transformation inverse, et vice versa augmente le nombre de colonnes du cadre de date en réduisant le nombre de lignes.

Ce type de transformation est extrêmement rarement utilisé pour mettre des données sous une forme précise. Cependant, cette technique peut être utile pour créer des tableaux croisés dynamiques utilisés dans des présentations ou pour l'intégration avec d'autres outils.
En fait les fonctions pivot_longer() и pivot_wider() sont symétriques et produisent des actions inverses les unes des autres, c'est-à-dire : df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) renverra le df original.
L'exemple le plus simple de conversion d'un tableau en format large
Pour démontrer le fonctionnement de la fonction pivot_wider() nous utiliserons l'ensemble de données rencontres_poissons, qui stocke des informations sur la manière dont différentes stations enregistrent le mouvement des poissons le long de la rivière.
#> # A tibble: 114 x 3
#> fish station seen
#> <fct> <fct> <int>
#> 1 4842 Release 1
#> 2 4842 I80_1 1
#> 3 4842 Lisbon 1
#> 4 4842 Rstr 1
#> 5 4842 Base_TD 1
#> 6 4842 BCE 1
#> 7 4842 BCW 1
#> 8 4842 BCE2 1
#> 9 4842 BCW2 1
#> 10 4842 MAE 1
#> # … with 104 more rowsDans la plupart des cas, ce tableau sera plus informatif et plus facile à utiliser si vous présentez les informations pour chaque station dans une colonne distincte.
fish_encounters %>% pivot_wider(names_from = station, values_from = seen)
fish_encounters %>% pivot_wider(names_from = station, values_from = seen)
#> # A tibble: 19 x 12
#> fish Release I80_1 Lisbon Rstr Base_TD BCE BCW BCE2 BCW2 MAE
#> <fct> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#> 1 4842 1 1 1 1 1 1 1 1 1 1
#> 2 4843 1 1 1 1 1 1 1 1 1 1
#> 3 4844 1 1 1 1 1 1 1 1 1 1
#> 4 4845 1 1 1 1 1 NA NA NA NA NA
#> 5 4847 1 1 1 NA NA NA NA NA NA NA
#> 6 4848 1 1 1 1 NA NA NA NA NA NA
#> 7 4849 1 1 NA NA NA NA NA NA NA NA
#> 8 4850 1 1 NA 1 1 1 1 NA NA NA
#> 9 4851 1 1 NA NA NA NA NA NA NA NA
#> 10 4854 1 1 NA NA NA NA NA NA NA NA
#> # … with 9 more rows, and 1 more variable: MAW <int>Cet ensemble de données n'enregistre les informations que lorsque des poissons ont été détectés par la station, c'est-à-dire si un poisson n'a pas été enregistré par une station, ces données ne figureront pas dans le tableau. Cela signifie que la sortie sera remplie de NA.
Cependant, dans ce cas, nous savons que l'absence d'enregistrement signifie que le poisson n'a pas été vu, nous pouvons donc utiliser l'argument valeurs_remplissage en fonction pivot_wider() et remplissez ces valeurs manquantes avec des zéros :
fish_encounters %>% pivot_wider(
names_from = station,
values_from = seen,
values_fill = list(seen = 0)
)#> # A tibble: 19 x 12
#> fish Release I80_1 Lisbon Rstr Base_TD BCE BCW BCE2 BCW2 MAE
#> <fct> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#> 1 4842 1 1 1 1 1 1 1 1 1 1
#> 2 4843 1 1 1 1 1 1 1 1 1 1
#> 3 4844 1 1 1 1 1 1 1 1 1 1
#> 4 4845 1 1 1 1 1 0 0 0 0 0
#> 5 4847 1 1 1 0 0 0 0 0 0 0
#> 6 4848 1 1 1 1 0 0 0 0 0 0
#> 7 4849 1 1 0 0 0 0 0 0 0 0
#> 8 4850 1 1 0 1 1 1 1 0 0 0
#> 9 4851 1 1 0 0 0 0 0 0 0 0
#> 10 4854 1 1 0 0 0 0 0 0 0 0
#> # … with 9 more rows, and 1 more variable: MAW <int>Générer un nom de colonne à partir de plusieurs variables sources
Imaginez que nous ayons un tableau contenant une combinaison de produit, de pays et d'année. Pour générer une période de test, vous pouvez exécuter le code suivant :
df <- expand_grid(
product = c("A", "B"),
country = c("AI", "EI"),
year = 2000:2014
) %>%
filter((product == "A" & country == "AI") | product == "B") %>%
mutate(value = rnorm(nrow(.)))#> # A tibble: 45 x 4
#> product country year value
#> <chr> <chr> <int> <dbl>
#> 1 A AI 2000 -2.05
#> 2 A AI 2001 -0.676
#> 3 A AI 2002 1.60
#> 4 A AI 2003 -0.353
#> 5 A AI 2004 -0.00530
#> 6 A AI 2005 0.442
#> 7 A AI 2006 -0.610
#> 8 A AI 2007 -2.77
#> 9 A AI 2008 0.899
#> 10 A AI 2009 -0.106
#> # … with 35 more rowsNotre tâche consiste à étendre le bloc de données afin qu'une colonne contienne des données pour chaque combinaison de produit et de pays. Pour ce faire, transmettez simplement l'argument noms_from un vecteur contenant les noms des champs à fusionner.
df %>% pivot_wider(names_from = c(product, country),
values_from = "value")#> # A tibble: 15 x 4
#> year A_AI B_AI B_EI
#> <int> <dbl> <dbl> <dbl>
#> 1 2000 -2.05 0.607 1.20
#> 2 2001 -0.676 1.65 -0.114
#> 3 2002 1.60 -0.0245 0.501
#> 4 2003 -0.353 1.30 -0.459
#> 5 2004 -0.00530 0.921 -0.0589
#> 6 2005 0.442 -1.55 0.594
#> 7 2006 -0.610 0.380 -1.28
#> 8 2007 -2.77 0.830 0.637
#> 9 2008 0.899 0.0175 -1.30
#> 10 2009 -0.106 -0.195 1.03
#> # … with 5 more rowsVous pouvez également appliquer des spécifications à une fonction pivot_wider(). Mais lorsqu'il est soumis à pivot_wider() la spécification fait la conversion inverse pivot_longer(): Les colonnes spécifiées dans . Nom, en utilisant les valeurs de .valeur et d'autres colonnes.
Pour cet ensemble de données, vous pouvez générer une spécification personnalisée si vous souhaitez que chaque combinaison possible de pays et de produits ait sa propre colonne, et pas seulement celles présentes dans les données :
spec <- df %>%
expand(product, country, .value = "value") %>%
unite(".name", product, country, remove = FALSE)#> # A tibble: 4 x 4
#> .name product country .value
#> <chr> <chr> <chr> <chr>
#> 1 A_AI A AI value
#> 2 A_EI A EI value
#> 3 B_AI B AI value
#> 4 B_EI B EI valuedf %>% pivot_wider(spec = spec) %>% head()#> # A tibble: 6 x 5
#> year A_AI A_EI B_AI B_EI
#> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 2000 -2.05 NA 0.607 1.20
#> 2 2001 -0.676 NA 1.65 -0.114
#> 3 2002 1.60 NA -0.0245 0.501
#> 4 2003 -0.353 NA 1.30 -0.459
#> 5 2004 -0.00530 NA 0.921 -0.0589
#> 6 2005 0.442 NA -1.55 0.594Plusieurs exemples avancés de travail avec le nouveau concept Tidyr
Nettoyage des données en utilisant l'ensemble de données du recensement américain sur les revenus et les loyers comme exemple.
Ensemble de données us_rent_ Income contient des informations sur le revenu médian et le loyer pour chaque État des États-Unis pour 2017 (ensemble de données disponible dans le package recensement bien rangé).
us_rent_income
#> # A tibble: 104 x 5
#> GEOID NAME variable estimate moe
#> <chr> <chr> <chr> <dbl> <dbl>
#> 1 01 Alabama income 24476 136
#> 2 01 Alabama rent 747 3
#> 3 02 Alaska income 32940 508
#> 4 02 Alaska rent 1200 13
#> 5 04 Arizona income 27517 148
#> 6 04 Arizona rent 972 4
#> 7 05 Arkansas income 23789 165
#> 8 05 Arkansas rent 709 5
#> 9 06 California income 29454 109
#> 10 06 California rent 1358 3
#> # … with 94 more rowsSous la forme sous laquelle les données sont stockées dans l'ensemble de données us_rent_ Income travailler avec eux est extrêmement gênant, nous aimerions donc créer un ensemble de données avec des colonnes : location, rent_moe, comment, revenu_moe. Il existe de nombreuses façons de créer cette spécification, mais le point principal est que nous devons générer chaque combinaison de valeurs de variables et estimation/moispuis générez le nom de la colonne.
spec <- us_rent_income %>%
expand(variable, .value = c("estimate", "moe")) %>%
mutate(
.name = paste0(variable, ifelse(.value == "moe", "_moe", ""))
)#> # A tibble: 4 x 3
#> variable .value .name
#> <chr> <chr> <chr>
#> 1 income estimate income
#> 2 income moe income_moe
#> 3 rent estimate rent
#> 4 rent moe rent_moeFournir cette spécification pivot_wider() nous donne le résultat que nous recherchons :
us_rent_income %>% pivot_wider(spec = spec)
#> # A tibble: 52 x 6
#> GEOID NAME income income_moe rent rent_moe
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 01 Alabama 24476 136 747 3
#> 2 02 Alaska 32940 508 1200 13
#> 3 04 Arizona 27517 148 972 4
#> 4 05 Arkansas 23789 165 709 5
#> 5 06 California 29454 109 1358 3
#> 6 08 Colorado 32401 109 1125 5
#> 7 09 Connecticut 35326 195 1123 5
#> 8 10 Delaware 31560 247 1076 10
#> 9 11 District of Columbia 43198 681 1424 17
#> 10 12 Florida 25952 70 1077 3
#> # … with 42 more rowsBanque mondiale
Parfois, amener un ensemble de données sous la forme souhaitée nécessite plusieurs étapes.
Base de données world_bank_pop contient des données de la Banque mondiale sur la population de chaque pays entre 2000 et 2018.
#> # A tibble: 1,056 x 20
#> country indicator `2000` `2001` `2002` `2003` `2004` `2005` `2006`
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 ABW SP.URB.T… 4.24e4 4.30e4 4.37e4 4.42e4 4.47e+4 4.49e+4 4.49e+4
#> 2 ABW SP.URB.G… 1.18e0 1.41e0 1.43e0 1.31e0 9.51e-1 4.91e-1 -1.78e-2
#> 3 ABW SP.POP.T… 9.09e4 9.29e4 9.50e4 9.70e4 9.87e+4 1.00e+5 1.01e+5
#> 4 ABW SP.POP.G… 2.06e0 2.23e0 2.23e0 2.11e0 1.76e+0 1.30e+0 7.98e-1
#> 5 AFG SP.URB.T… 4.44e6 4.65e6 4.89e6 5.16e6 5.43e+6 5.69e+6 5.93e+6
#> 6 AFG SP.URB.G… 3.91e0 4.66e0 5.13e0 5.23e0 5.12e+0 4.77e+0 4.12e+0
#> 7 AFG SP.POP.T… 2.01e7 2.10e7 2.20e7 2.31e7 2.41e+7 2.51e+7 2.59e+7
#> 8 AFG SP.POP.G… 3.49e0 4.25e0 4.72e0 4.82e0 4.47e+0 3.87e+0 3.23e+0
#> 9 AGO SP.URB.T… 8.23e6 8.71e6 9.22e6 9.77e6 1.03e+7 1.09e+7 1.15e+7
#> 10 AGO SP.URB.G… 5.44e0 5.59e0 5.70e0 5.76e0 5.75e+0 5.69e+0 4.92e+0
#> # … with 1,046 more rows, and 11 more variables: `2007` <dbl>,
#> # `2008` <dbl>, `2009` <dbl>, `2010` <dbl>, `2011` <dbl>, `2012` <dbl>,
#> # `2013` <dbl>, `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>Notre objectif est de créer un ensemble de données soigné avec chaque variable dans sa propre colonne. On ne sait pas exactement quelles étapes sont nécessaires, mais nous allons commencer par le problème le plus évident : l'année est répartie sur plusieurs colonnes.
Pour résoudre ce problème, vous devez utiliser la fonction pivot_longer().
pop2 <- world_bank_pop %>%
pivot_longer(`2000`:`2017`, names_to = "year")#> # A tibble: 19,008 x 4
#> country indicator year value
#> <chr> <chr> <chr> <dbl>
#> 1 ABW SP.URB.TOTL 2000 42444
#> 2 ABW SP.URB.TOTL 2001 43048
#> 3 ABW SP.URB.TOTL 2002 43670
#> 4 ABW SP.URB.TOTL 2003 44246
#> 5 ABW SP.URB.TOTL 2004 44669
#> 6 ABW SP.URB.TOTL 2005 44889
#> 7 ABW SP.URB.TOTL 2006 44881
#> 8 ABW SP.URB.TOTL 2007 44686
#> 9 ABW SP.URB.TOTL 2008 44375
#> 10 ABW SP.URB.TOTL 2009 44052
#> # … with 18,998 more rowsL'étape suivante consiste à examiner la variable indicatrice.
pop2 %>% count(indicator)
#> # A tibble: 4 x 2
#> indicator n
#> <chr> <int>
#> 1 SP.POP.GROW 4752
#> 2 SP.POP.TOTL 4752
#> 3 SP.URB.GROW 4752
#> 4 SP.URB.TOTL 4752Où SP.POP.GROW représente la croissance démographique, SP.POP.TOTL la population totale et SP.URB. * la même chose, mais uniquement pour les zones urbaines. Divisons ces valeurs en deux variables : superficie - superficie (totale ou urbaine) et une variable contenant des données réelles (population ou croissance) :
pop3 <- pop2 %>%
separate(indicator, c(NA, "area", "variable"))#> # A tibble: 19,008 x 5
#> country area variable year value
#> <chr> <chr> <chr> <chr> <dbl>
#> 1 ABW URB TOTL 2000 42444
#> 2 ABW URB TOTL 2001 43048
#> 3 ABW URB TOTL 2002 43670
#> 4 ABW URB TOTL 2003 44246
#> 5 ABW URB TOTL 2004 44669
#> 6 ABW URB TOTL 2005 44889
#> 7 ABW URB TOTL 2006 44881
#> 8 ABW URB TOTL 2007 44686
#> 9 ABW URB TOTL 2008 44375
#> 10 ABW URB TOTL 2009 44052
#> # … with 18,998 more rowsIl ne nous reste plus qu'à diviser la variable en deux colonnes :
pop3 %>%
pivot_wider(names_from = variable, values_from = value)#> # A tibble: 9,504 x 5
#> country area year TOTL GROW
#> <chr> <chr> <chr> <dbl> <dbl>
#> 1 ABW URB 2000 42444 1.18
#> 2 ABW URB 2001 43048 1.41
#> 3 ABW URB 2002 43670 1.43
#> 4 ABW URB 2003 44246 1.31
#> 5 ABW URB 2004 44669 0.951
#> 6 ABW URB 2005 44889 0.491
#> 7 ABW URB 2006 44881 -0.0178
#> 8 ABW URB 2007 44686 -0.435
#> 9 ABW URB 2008 44375 -0.698
#> 10 ABW URB 2009 44052 -0.731
#> # … with 9,494 more rowsListe de contacts
Un dernier exemple, imaginez que vous ayez une liste de contacts que vous avez copiée et collée depuis un site Web :
contacts <- tribble(
~field, ~value,
"name", "Jiena McLellan",
"company", "Toyota",
"name", "John Smith",
"company", "google",
"email", "john@google.com",
"name", "Huxley Ratcliffe"
)La tabulation de cette liste est assez difficile car il n'existe aucune variable permettant d'identifier quelles données appartiennent à quel contact. Nous pouvons résoudre ce problème en notant que les données de chaque nouveau contact commencent par « nom », nous pouvons donc créer un identifiant unique et l'incrémenter de un à chaque fois que la colonne du champ contient la valeur « nom » :
contacts <- contacts %>%
mutate(
person_id = cumsum(field == "name")
)
contacts#> # A tibble: 6 x 3
#> field value person_id
#> <chr> <chr> <int>
#> 1 name Jiena McLellan 1
#> 2 company Toyota 1
#> 3 name John Smith 2
#> 4 company google 2
#> 5 email john@google.com 2
#> 6 name Huxley Ratcliffe 3Maintenant que nous avons un identifiant unique pour chaque contact, nous pouvons transformer le champ et la valeur en colonnes :
contacts %>%
pivot_wider(names_from = field, values_from = value)#> # A tibble: 3 x 4
#> person_id name company email
#> <int> <chr> <chr> <chr>
#> 1 1 Jiena McLellan Toyota <NA>
#> 2 2 John Smith google john@google.com
#> 3 3 Huxley Ratcliffe <NA> <NA>Conclusion
Mon opinion personnelle est que le nouveau concept ranger vraiment plus intuitif et nettement supérieur en termes de fonctionnalités aux fonctions existantes spread() и gather(). J'espère que cet article vous a aidé à gérer pivot_longer() и pivot_wider().
Source: habr.com
