Retour à la leçon·Leçon 4 sur 8·Faire entrer les données
Obtenir un tableau ordonné
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
- La règle
- À quoi ressemble le désordre dans ce secteur
- Format long et format large
- Joindre une liste à son parent
- Prouvez que la jointure a fait ce que vous aviez annoncé
- Le registre est déjà ordonné
- La suite
Notes du présentateur
Restructurer les groupes répétés aplatis en une ligne par observation, joindre une liste de membres à son ménage, et prouver que la jointure n'a pas modifié votre charge de cas en silence.La règle
- Une ligne par observation, une colonne par variable, une table par type d'objet.
Notes du présentateur
Une ligne par observation, une colonne par variable, une table par type d'objet. La règle est ancienne et elle fait encore l'essentiel du travail. Il vaut la peine d'en dire la raison, car « ordonné » évoque le rangement plutôt que l'ingénierie. Dans un tableau ordonné, chaque opération souhaitée — filtrer, grouper, joindre, représenter — est la même opération quelle que soit la variable traitée. Dans un tableau désordonné, chaque variable exige du code sur mesure, et c'est dans ce code sur mesure que vivent les erreurs.À quoi ressemble le désordre dans ce secteur
- Groupes répétés aplatis — CommCare exporte une ligne par soumission, donc une visite de ménage ayant dépisté trois…
Notes du présentateur
Trois formes couvrent la quasi-totalité des cas. Groupes répétés aplatis. CommCare exporte une ligne par soumission, donc une visite de ménage ayant dépisté trois enfants devient :À quoi ressemble le désordre dans ce secteur — Exemple
form_id,commune,child_1_id,child_1_muac,child_2_id,child_2_muac,child_3_id,child_3_muac F0012,Gonaives,CH00854,133,CH00855,118,, F0013,Verrettes,CH01439,143,,,,À quoi ressemble le désordre dans ce secteur
- Des valeurs dans les en-têtes de colonnes — Un tableau croisé DHIS2 dispose les périodes en haut :
Notes du présentateur
Une ligne est un formulaire. Vous voulez une ligne par enfant. Le nombre de colonnes change en outre d'un export à l'autre, ce qui signifie que tout code nommant explicitement les colonnes cassera le mois prochain. Des valeurs dans les en-têtes de colonnes. Un tableau croisé DHIS2 dispose les périodes en haut :À quoi ressemble le désordre dans ce secteur — Exemple
org_unit,janv-2024,févr-2024,mars-2024 Gonaives,412,388,401À quoi ressemble le désordre dans ce secteur
- Plusieurs objets dans une même table — Un export d'enquête où les caractéristiques du ménage sont répétées sur chaque…
Notes du présentateur
Le mois est une donnée — c'est une valeur d'une variable nomméepériode— mais il loge dans un en-tête. Plusieurs objets dans une même table. Un export d'enquête où les caractéristiques du ménage sont répétées sur chaque ligne de membre. Rien de grave, jusqu'à ce que quelqu'un calcule une taille moyenne de ménage et obtienne un chiffre pondéré par la taille des ménages.Format long et format large — En Python (suite)
import pandas as pd large = pd.read_csv("data/raw/commcare-screening-export.csv") long = large.melt( id_vars=["form_id", "commune"], var_name="champ", value_name="valeur", ) # child_1_muac -> enfant 1, champ muac parties = long["champ"].str.extract(r"^child_(?P<rang>\d+)_(?P<attribut>.+)$") long = pd.concat([long, parties], axis=1).dropna(subset=["rang"]) enfants = ( long.pivot(index=["form_id", "commune", "rang"], columns="attribut", values="valeur")Notes du présentateur
Passer de l'un à l'autre est la compétence mécanique la plus utile de cette formation.Format long et format large — En Python (suite)
.reset_index() .dropna(subset=["id"]) ) print(enfants.head())Format long et format large — En R (suite)
library(dplyr) library(tidyr) library(readr) large <- read_csv("data/raw/commcare-screening-export.csv") enfants <- large |> pivot_longer( cols = starts_with("child_"), names_to = c("rang", "attribut"), names_pattern = "child_(\\d+)_(.+)", values_to = "valeur", values_transform = as.character ) |> pivot_wider(names_from = attribut, values_from = valeur) |> filter(!is.na(id))Format long et format large
- Repérez le rang par une expression régulière, jamais en énumérant les colonnes. La liste change d'un export à…
- Supprimez les rangs vides. Un formulaire ayant dépisté un seul enfant produit malgré tout des colonnes pour les…
Notes du présentateur
Deux détails portent l'essentiel : Vérifiez ensuite l'arithmétique. Si l'export comptait 1 600 formulaires et que le plus large portait trois enfants, la restructuration produit 4 800 lignes candidates, dont seules les vraies survivent à la suppression. Ce nombre survivant est votre charge de cas, et il doit correspondre à ce que le programme pense avoir dépisté.Joindre une liste à son parent — En Python
menages = pd.read_excel("data/raw/kobo-export.xlsx", sheet_name="household") membres = pd.read_excel("data/raw/kobo-export.xlsx", sheet_name="member") fusion = membres.merge( menages[["_index", "commune", "interview_date"]], left_on="_parent_index", right_on="_index", how="left", validate="many_to_one", indicator=True, ) print(fusion["_merge"].value_counts())Notes du présentateur
KoboToolbox place les répétitions dans leur propre feuille, reliée par_parent_index.Joindre une liste à son parent — En R
library(readxl) menages <- read_excel("data/raw/kobo-export.xlsx", sheet = "household") membres <- read_excel("data/raw/kobo-export.xlsx", sheet = "member") fusion <- membres |> left_join( menages |> select(`_index`, commune, interview_date), by = join_by(`_parent_index` == `_index`), relationship = "many-to-one", unmatched = "error" ) nrow(fusion) == nrow(membres)Notes du présentateur
validate="many_to_one"sous pandas etrelationship = "many-to-one"sous dplyr sont les arguments importants, et presque personne ne les emploie. Ils déclenchent une erreur si la relation que vous avez affirmée n'est pas celle des données — c'est-à-dire exactement la défaillance qui multiplie sinon votre nombre de lignes et se découvre trois étapes plus loin sous la forme d'une charge de cas surestimée de 14 %.Prouvez que la jointure a fait ce que vous aviez annoncé — En Python
avant = len(membres) apres = len(fusion) assert apres == avant, f"la jointure a changé le nombre de lignes : {avant} -> {apres}" orphelins = (fusion["_merge"] == "left_only").sum() assert orphelins == 0, f"{orphelins} membres sans ménage" assert fusion["child_id"].is_unique, "identifiants dupliqués après jointure"Notes du présentateur
Trois vérifications, à chaque fois. Elles prennent une minute et ont détecté plus d'erreurs qu'aucune autre technique de cette formation.Prouvez que la jointure a fait ce que vous aviez annoncé — En R
stopifnot(nrow(fusion) == nrow(membres)) stopifnot(!any(is.na(fusion$commune))) stopifnot(!any(duplicated(fusion$child_id)))Prouvez que la jointure a fait ce que vous aviez annoncé
Une jointure qui modifie votre nombre de lignes n'est pas un problème de données à corriger en aval. C'est le signe que vous avez mal compris l'une des deux tables, et la correction se situe en amont de la jointure.
Notes du présentateur
La vérification du nombre de lignes est celle à intégrer. Une jointure à gauche ne peut que laisser le nombre de lignes inchangé ou l'augmenter. S'il a augmenté, la table de droite comportait des clés dupliquées, et chaque clé dupliquée a discrètement multiplié ses lignes. Dans un tableau de charge de cas, c'est une surestimation que vous rapporterez à un bailleur.Le registre est déjà ordonné — En Python
muac.head()Notes du présentateur
Le registre de dépistage PB utilisé par cette formation comporte une ligne par enfant, ce qui permet de le travailler directement :Le registre est déjà ordonné — En R
head(muac)Notes du présentateur
C'est délibéré. La restructuration est une compétence réelle et vous en aurez besoin, mais ce n'est pas là que se situent les décisions intéressantes. Ces décisions commencent à la leçon suivante, lorsque vous regarderez ce que contiennent réellement ces 4 218 lignes.La suite
- Le tableau a la bonne forme.
Notes du présentateur
Le tableau a la bonne forme. La leçon suivante établit ce qui ne va pas dedans — méthodiquement, avec une non-réponse ventilée par site et par semaine, car une non-réponse qui se concentre est un problème d'une tout autre nature qu'une non-réponse dispersée.