cassionAnalyse de données

Retour à la leçonLeçon 7 sur 8Restructurer 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.

Diapositives · PDFDiapositives · PowerPoint

  1. Diapositive 1 / 22

    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.
  2. Diapositive 2 / 22

    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  m
    Notes 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.
  3. Diapositive 3 / 22

    pivot_longer() avec .value — En R

    library(tidyr)
    
    long <- wide |>
      pivot_longer(
        starts_with("member_"),
        names_to = c("member", ".value"),
        names_pattern = "member_(\\d+)_(.*)"
      )
  4. Diapositive 4 / 22

    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 m
  5. Diapositive 5 / 22

    pivot_longer() avec .value

    • Le motif
    Notes du présentateur
    Une ligne par personne, et age et sex sont des colonnes distinctes avec leurs propres types. C'est la forme qu'attend tout ce qui suit. La sentinelle .value est la pièce à comprendre. Dans names_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. Ainsi member_1_age se scinde en member = "1" et une valeur appartenant à une colonne nommée age. Sans .value, vous obtiendriez une unique colonne value mêlant nombres et texte, et une colonne name qu'il faudrait ensuite scinder et pivoter à nouveau. names_pattern est une expression régulière comportant un groupe de capture par entrée de names_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 :
  6. Diapositive 6 / 22

    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
    Le values_drop_na = TRUE de la seconde compte : un ménage avec trois emplacements de culture et deux cultures en a un vide, et une ligne NA par emplacement inutilisé est un bruit qui change tous les décomptes.
  7. Diapositive 7 / 22

    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.
  8. Diapositive 8 / 22

    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.
  9. Diapositive 9 / 22

    pivot_wider() et l'avertissement qui veut dire quelque chose — En R

    by_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 :
  10. Diapositive 10 / 22

    pivot_wider() et l'avertissement qui veut dire quelque chose — Exemple

    Warning: 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 :
  11. Diapositive 11 / 22

    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 pas values_fn = sum pour 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.
  12. Diapositive 12 / 22

    pivot_wider() et l'avertissement qui veut dire quelque chose — En R

    by_commune_month |> count(commune, month) |> filter(n > 1)
  13. Diapositive 13 / 22

    pivot_wider() et l'avertissement qui veut dire quelque chose

    • values_fill
    Notes du présentateur
    Voilà le diagnostic, et il doit précéder le pivot plutôt que suivre l'avertissement.
  14. Diapositive 14 / 22

    pivot_wider() et l'avertissement qui veut dire quelque chose — En R

    pivot_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.
  15. Diapositive 15 / 22

    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"))
  16. Diapositive 16 / 22

    Séparer et réunir des colonnes — Exemple

    # A tibble: 2 × 2
      year  month
      <chr> <chr>
    1 2024  01
    2 2024  02
  17. Diapositive 17 / 22

    Sé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'ancien separate(), 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 :
  18. Diapositive 18 / 22

    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 est unite(), utile pour bâtir une clé composite avant une jointure : remove = FALSE conserve les colonnes sources, dont vous avez presque toujours encore besoin.
  19. Diapositive 19 / 22

    L'imbrication, brièvement — En R

    by_commune <- muac |>
      tidyr::nest(.by = commune)
    
    by_commune$data[[1]]      # le tibble complet de la premiere commune
    Notes 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 .by de summarise() y mène avec moins de machinerie.
  20. Diapositive 20 / 22

    Où cela rejoint le cours Python

    • Le cours Python couvre la même restructuration sous melt et pivot.
    Notes du présentateur
    Le cours Python couvre la même restructuration sous melt et pivot. 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.
  21. Diapositive 21 / 22

    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.
  22. Diapositive 22 / 22

    La suite

    Lire la leçon complète, avec le code exécutable Retour à la leçon