Retour à la leçon·Leçon 7 sur 8·Restructurer et répéter
Défaire un groupe répété aplati
Le même diaporama que les téléchargements, rendu sous forme de page. Lancez le diaporama pour le présenter en plein écran — les flèches ou un clic avancent d'une diapositive, Échap quitte.
Ce que couvre cette leçon
- Ce qu'une plateforme de collecte fait d'un groupe répété
pivot_longer()avec.value- Vérifiez le nombre de lignes obtenu
pivot_wider()et l'avertissement qui veut dire quelque chose- Séparer et réunir des colonnes
- L'imbrication, brièvement
- Où cela rejoint le cours Python
- Ce qui vient ensuite
Notes du présentateur
pivot_longer() avec .value, l'appel unique qui retransforme un export CommCare ou Kobo en une ligne par personne — plus l'avertissement de pivot_wider() qui signifie que votre clé n'en est pas une.Ce qu'une plateforme de collecte fait d'un groupe répété — Exemple
hh member_1_age member_1_sex member_2_age member_2_sex H1 34 f 8 mNotes du présentateur
Un questionnaire ménage interroge sur chaque membre. Sous CommCare, KoboToolbox ou ODK, les réponses reviennent aplaties — une ligne par ménage, le groupe répété étalé sur des colonnes numérotées : Rien dans cette forme n'est analysable. Vous ne pouvez ni calculer un âge moyen, ni filtrer sur les enfants, ni joindre quoi que ce soit, parce qu'une personne n'est pas une ligne.pivot_longer()avec.value— En Rlibrary(tidyr) long <- wide |> pivot_longer( starts_with("member_"), names_to = c("member", ".value"), names_pattern = "member_(\\d+)_(.*)" )pivot_longer()avec.value— Exemple# A tibble: 2 × 4 hh member age sex <chr> <chr> <dbl> <chr> 1 H1 1 34 f 2 H1 2 8 mpivot_longer()avec.value- Le motif
Notes du présentateur
Une ligne par personne, etageetsexsont des colonnes distinctes avec leurs propres types. C'est la forme qu'attend tout ce qui suit. La sentinelle.valueest la pièce à comprendre. Dansnames_to, un nom ordinaire —"member"— devient une nouvelle colonne portant cette partie de l'ancien nom de colonne.".value"est différent : il dit cette partie du nom est le nom de la colonne de sortie. Ainsimember_1_agese scinde enmember = "1"et une valeur appartenant à une colonne nomméeage. Sans.value, vous obtiendriez une unique colonnevaluemêlant nombres et texte, et une colonnenamequ'il faudrait ensuite scinder et pivoter à nouveau.names_patternest une expression régulière comportant un groupe de capture par entrée denames_to, dans l'ordre."member_(\\d+)_(.*)"capture le numéro puis tout ce qui suit le second tiret bas. Deux variantes lorsque les noms sont plus simples :pivot_longer()avec.value— En R# Separateur fixe, sans expression reguliere. pivot_longer(wide, starts_with("member_"), names_to = c("member", ".value"), names_sep = "_(?=[a-z]+$)") # Une seule colonne de valeurs, nom conserve entier. pivot_longer(wide, starts_with("crop_"), names_to = "slot", names_prefix = "crop_", values_to = "crop", values_drop_na = TRUE)Notes du présentateur
Levalues_drop_na = TRUEde la seconde compte : un ménage avec trois emplacements de culture et deux cultures en a un vide, et une ligneNApar emplacement inutilisé est un bruit qui change tous les décomptes.Vérifiez le nombre de lignes obtenu — En R
stopifnot(nrow(long) == sum(!is.na(wide$member_1_age)) + sum(!is.na(wide$member_2_age)))Notes du présentateur
Un pivot qui produit le mauvais nombre de lignes est l'erreur la plus facile à commettre et la plus difficile à voir, parce que le résultat paraît correct.Vérifiez le nombre de lignes obtenu — En R
long |> count(hh, name = "members_found") |> left_join(households |> select(hh, hh_size), by = "hh") |> filter(members_found != hh_size)Notes du présentateur
Plus concrètement, comptez les personnes par ménage et comparez à la taille de ménage que le formulaire a enregistrée : Un résultat vide, c'est le contrôle qui passe. Un résultat non vide est une liste de ménages où la composition et la taille déclarée divergent — un constat de qualité des données avant d'être un problème de pivot.pivot_wider()et l'avertissement qui veut dire quelque chose — En Rby_commune_month |> pivot_wider(names_from = month, values_from = cases, values_fill = 0)Notes du présentateur
L'opération inverse construit le tableau large qu'attend un rapport :pivot_wider()et l'avertissement qui veut dire quelque chose — ExempleWarning: Values from `v` are not uniquely identified; output will contain list-cols.Notes du présentateur
Si plusieurs lignes partagent la même clé, tidyr ne lève pas d'erreur :pivot_wider()et l'avertissement qui veut dire quelque chose- Cet avertissement signifie que votre clé n'en est pas une — La cellule contient désormais une liste des valeurs entrées…
Notes du présentateur
Cet avertissement signifie que votre clé n'en est pas une. La cellule contient désormais une liste des valeurs entrées en collision, et toute opération en aval échoue étrangement ou opère silencieusement sur une liste. N'ajoutez pasvalues_fn = sumpour faire taire l'avertissement sans avoir d'abord cherché la cause des doublons. Il s'agit généralement de l'un de trois cas : un formulaire resoumis, une formation sanitaire rapportant deux fois dans le mois, ou une variable de regroupement oubliée. Seul le premier se somme sans risque.pivot_wider()et l'avertissement qui veut dire quelque chose — En Rby_commune_month |> count(commune, month) |> filter(n > 1)pivot_wider()et l'avertissement qui veut dire quelque chosevalues_fill
Notes du présentateur
Voilà le diagnostic, et il doit précéder le pivot plutôt que suivre l'avertissement.pivot_wider()et l'avertissement qui veut dire quelque chose — En Rpivot_wider(..., values_fill = 0)Notes du présentateur
Sans risque pour un décompte, où une combinaison absente valait réellement zéro. Faux pour un taux, où l'absence signifie « non calculé » et non « zéro pour cent » — une commune sans dépistage en mars a un taux de MAG indéfini, non un taux de 0 %, et le remplir par zéro tire toutes les moyennes vers le bas.Séparer et réunir des colonnes — En R
tibble(x = c("2024-01", "2024-02")) |> separate_wider_delim(x, delim = "-", names = c("year", "month"))Séparer et réunir des colonnes — Exemple
# A tibble: 2 × 2 year month <chr> <chr> 1 2024 01 2 2024 02Séparer et réunir des colonnes — En R
separate_wider_delim(x, "-", names = c("year", "month"), too_few = "align_start")Notes du présentateur
separate_wider_delim()a remplacé l'ancienseparate(), et le progrès tient à sa rigueur : une ligne au mauvais nombre de morceaux est une erreur plutôt qu'une troncature silencieuse. Là où une entrée irrégulière est attendue, dites-le :Séparer et réunir des colonnes — En R
unite(df, "key", district, community, sep = "-", remove = FALSE)Notes du présentateur
L'opération inverse estunite(), utile pour bâtir une clé composite avant une jointure :remove = FALSEconserve les colonnes sources, dont vous avez presque toujours encore besoin.L'imbrication, brièvement — En R
by_commune <- muac |> tidyr::nest(.by = commune) by_commune$data[[1]] # le tibble complet de la premiere communeNotes du présentateur
Un groupe répété peut aussi rester imbriqué plutôt qu'aplati : C'est la forme adaptée pour exécuter le même modèle ou le même résumé par commune sans boucle. Il vaut la peine de savoir que cela existe ; pour l'essentiel du rapportage de programme, le.bydesummarise()y mène avec moins de machinerie.Où cela rejoint le cours Python
- Le cours Python couvre la même restructuration sous
meltetpivot.
Notes du présentateur
Le cours Python couvre la même restructuration sousmeltetpivot. Le vocabulaire diffère, les modes de défaillance non : un groupe répété qui doit devenir des lignes, une clé qui s'avère non unique, et une valeur de remplissage juste pour un décompte et fausse pour un taux.- Le cours Python couvre la même restructuration sous
Ce qui vient ensuite
- Les données ont la bonne forme.
Notes du présentateur
Les données ont la bonne forme. La dernière leçon transforme tout ce qui précède en une fonction qu'un autre chargé pourra exécuter sur l'export du trimestre prochain sans rien modifier d'autre que ses arguments.