cassionAnalyse de données

Leçon 8 sur 8

Unité · La trace qui vous survit

Le journal qui répond à la question avant qu'elle soit posée

Une ligne par règle appliquée — laquelle, combien de lignes touchées, ce qui a changé, qui a validé. Produit par le code plutôt que rédigé après coup, et livré comme l'annexe qui met fin au débat.

PythonR75 minNorme humanitaire fondamentale (CHS)Critères d'évaluation du CAD de l'OCDE

La question qui vous sera posée

Elle arrive sous l’une de trois formes et elle arrive toujours.

  • Lors d’une visite de suivi d’un bailleur — « Votre charge de cas a baissé de 4 % entre le projet et le rapport final. Qu’est-ce qui a changé ? »
  • Par le responsable de programme — « Le trimestre dernier Gros-Morne était deuxième plus touchée. Elle est maintenant quatrième. Y a-t-il eu une amélioration ? »
  • Par votre successeur, dans un courriel — « Il y a ici un script qui supprime des lignes. Savez-vous pourquoi ? »

Chacune trouve réponse en trente secondes avec un journal de nettoyage, et pas du tout sans. Cette leçon est ce journal.

Un journal est un tableau, pas un récit

Le réflexe est d’écrire un paragraphe dans la section méthodologie. Un paragraphe ne se compte pas, ne se compare pas au trimestre précédent et ne se vérifie pas.

Une ligne par règle appliquée. Chaque ligne porte un compte.

règle gravité lignes action effet sur l’indicateur décidé par date
muac-range error 7 exclues MAG 8,62 % à 8,63 % R. Cassion 2026-07-14
exact-duplicate error 12 un exemplaire gardé charge 366 à 360 R. Cassion 2026-07-14
re-registration warning 6 fusionnées après relecture charge 360 à 354 M. Joseph, superviseur 2026-07-16
oedema-yn-coding warning 25 recodées en false MAG inchangée R. Cassion 2026-07-14
age-missing note 226 gardées, signalées tableau par âge seulement R. Cassion 2026-07-14
district-mapping warning 75 rattachées à HT07 Nord-Ouest 14,7 % à 15,0 % A. Pierre, bureau terrain 2026-07-15

Lisez la colonne lignes de haut en bas et vous avez toute l’histoire de ce fichier. Lisez la colonne effet sur l'indicateur et vous avez la réponse à la question du bailleur, par avance.

Les sept colonnes, et ce qui justifie chacune

  • règle — l’identifiant de la table de règles de la leçon 5, pour que le journal et le code emploient le même nom. Si le journal dit muac-range et le code implausible_muac, le lien casse dès qu’un tiers regarde.
  • gravité — ce que le contrôle signifiait, pour qu’un lecteur puisse survoler jusqu’aux erreurs.
  • lignes — le compte. Ni « quelques-unes », ni « des valeurs aberrantes ». Un nombre.
  • action — exclues, corrigées, recodées, fusionnées, gardées et signalées. Cinq verbes couvrent presque tout, et employer toujours les mêmes cinq rend le journal survolable.
  • effet sur l’indicateur — l’avant et l’après. C’est la colonne que l’on saute et la seule qu’un bailleur lise.
  • décidé par — une personne. Pas « l’équipe ». La règle sans nom en face est celle qui se révèle fausse.
  • date — quand, pour que le journal se lise en regard de la version du résultat qu’il a produite.

Produisez-le à partir du code

Un journal rédigé après coup, de mémoire, est une fiction, et il est toujours plus court que la vérité. Faites en sorte que chaque étape de nettoyage renvoie sa propre ligne de journal.

LOG = []


def apply_step(df, rule, mask, action, note=""):
    before = indicator(df)
    if action == "exclude":
        out = df[~mask]
    elif action == "flag":
        out = df.assign(**{f"flag_{rule}": mask})
    else:
        raise ValueError(action)
    after = indicator(out)

    LOG.append({
        "rule": rule,
        "rows": int(mask.sum()),
        "action": action,
        "before": before,
        "after": after,
        "effect": round(after - before, 4),
        "note": note,
    })
    return out


muac = apply_step(muac, "muac-range", ~muac["muac_mm"].between(80, 220), "exclude")
muac = apply_step(muac, "age-missing", muac["age_months"].isna(), "flag",
                  "kept; age-disaggregated tables only")

log = pd.DataFrame(LOG)
log.to_csv("outputs/cleaning-log.csv", index=False)
LOG <- list()

apply_step <- function(df, rule, mask, action, note = "") {
  before <- indicator(df)
  out <- switch(action,
    exclude = df[!mask, ],
    flag    = dplyr::mutate(df, "flag_{rule}" := mask),
    stop("unknown action: ", action)
  )
  after <- indicator(out)

  LOG[[length(LOG) + 1]] <<- tibble::tibble(
    rule = rule, rows = sum(mask, na.rm = TRUE), action = action,
    before = before, after = after, effect = round(after - before, 4), note = note
  )
  out
}

muac <- apply_step(muac, "muac-range", !dplyr::between(muac$muac_mm, 80, 220), "exclude")
muac <- apply_step(muac, "age-missing", is.na(muac$age_months), "flag",
                   "kept; age-disaggregated tables only")

readr::write_csv(dplyr::bind_rows(LOG), here::here("outputs", "cleaning-log.csv"))

Ce montage garantit deux choses que la seule discipline ne garantit pas.

Une étape ne peut pas avoir lieu sans être consignée, puisque consigner est ce que fait la fonction. Le tentant df = df[df.muac_mm > 80] glissé à 18 heures un jour d’échéance est exactement la modification qui n’atteint jamais un journal écrit ; ici, il n’existe pas de manière plus courte de le faire que la manière consignée.

L’effet est mesuré, pas estimé. before et after proviennent de la même fonction indicator(), évaluée sur les mêmes données à un instant d’écart. Personne n’a à se souvenir de ce que valait le chiffre.

Le tableau avant-après est le livrable

Agrégez le journal en trois lignes et il devient exploitable par un lecteur non technique.

print(f"Records received:  {len(raw):>6,}")
print(f"Excluded:          {len(raw) - len(analysis):>6,}")
print(f"Analysed:          {len(analysis):>6,}")
print(f"GAM, raw:          {indicator(raw):>6.1%}")
print(f"GAM, cleaned:      {indicator(analysis):>6.1%}")
cat(sprintf("Records received: %6d\n", nrow(raw)))
cat(sprintf("Excluded:         %6d\n", nrow(raw) - nrow(analysis)))
cat(sprintf("Analysed:         %6d\n", nrow(analysis)))
cat(sprintf("GAM, raw:         %6.1f%%\n", 100 * indicator(raw)))
cat(sprintf("GAM, cleaned:     %6.1f%%\n", 100 * indicator(analysis)))

Si les chiffres brut et nettoyé sont proches, dites-le — c’est la phrase la plus forte dont vous disposiez, car elle signifie que le constat ne dépend pas de votre jugement. S’ils sont éloignés, dites-le aussi, et attendez-vous à la discussion. Un nettoyage qui déplace un indicateur de trois points n’est pas un défaut de l’analyse ; c’est un constat sur la collecte des données, et le dissimuler est la seule version de tout ceci qui relève de la faute.

Ce qui ne doit pas figurer dans le journal

Le journal est une annexe. Il est envoyé par courriel, joint à des rapports et transféré, ce qui veut dire qu’il voyage plus loin que le jeu de données.

  • Aucun identifiant direct. Ni noms, ni numéros de téléphone, ni coordonnées GPS. Une ligne disant fusion de CH03315 dans CH09241 convient, ce sont des pseudonymes ; fusion de Jean B. (Ti Rivyè) dans… est un incident de protection.
  • Aucun petit effectif dans une catégorie sensible. « 3 lignes recodées, catégorie VBG viol, Marmelade » identifie des personnes dans une petite commune. Agrégez la règle au niveau que vous publieriez, ou écrivez « 3 lignes, une commune ».
  • Aucun détail en texte libre recopié d’une note de dossier. La règle est ce que vous avez appliqué, pas ce que l’enregistrement disait.

Cette habitude s’apprend utilement sur des données nutritionnelles, où elle ne coûte rien, afin d’être automatique le jour où l’on vous confie une charge de cas de protection — où les principes ne sont pas des conseils.

Où vit le journal

À côté du résultat, pas dans un document.

outputs/
  profiles/muac-2024-q4.json        arrival profile      (lesson 1)
  validation/muac-2024-q4.json      validation findings  (lesson 7)
  cleaning-log.csv                  decisions            (this lesson)
  review/duplicate-candidates.csv   reviewed and signed  (lesson 4)
  tables/gam_by_commune.csv         the result
  tables/definitions.csv            numerator, denominator, source

Ces six fichiers constituent le compte rendu complet d’un trimestre. Quiconque dispose de l’export brut et de ce dossier peut reconstituer tout ce que vous avez fait et vérifier chaque chiffre, et c’est une affirmation bien plus solide que « l’analyse a été soignée ».

Remarquez ce qui n’y est pas — le jeu de données nettoyé n’est pas le livrable. Le fichier brut reste en lecture seule et le fichier nettoyé est régénéré en exécutant le script. Un CSV nettoyé qui circule par courriel se détache de son journal en une semaine, et plus personne ne sait quelle version il tient.

L’annexe dont le rapport a besoin

Trois sections courtes, et elles ont leur place dans toute analyse que ce secteur produit.

Source et complétude des données. D’où vient le fichier, combien d’enregistrements, quelle part des unités de rapportage attendues il couvre, sur quelle période.

Nettoyage et exclusions. Le tableau du journal, ou son résumé avec le tableau complet en pièce jointe. Chaque exclusion avec son compte.

Limites. Ce que le nettoyage n’a pas pu corriger. Le manquant non au hasard que vous soupçonnez sans pouvoir le démontrer. Les six enregistrements fusionnés qu’un superviseur a confirmés et les deux sur lesquels il hésitait. Le district dont le taux repose sur trente-trois ménages.

L’annexe n’est pas un aveu. C’est la raison pour laquelle le chiffre du résumé exécutif peut être défendu, et la différence professionnelle entre un chiffre et une affirmation.

Ce que ce cours vous laisse

Vous savez prendre un export brut de programme, décrire honnêtement ce qui est arrivé, y trouver les défauts de quatre manières différentes, décider du traitement de chacun au regard d’une norme publiée, faire tourner ces décisions à nouveau le trimestre suivant sans vous, et remettre l’ensemble à un auditeur avec la démarche jointe.

Le cours suivant de ce module, Jointures et restructuration des données de programme, prend le tableau propre et l’assemble avec les autres — ménage vers membre, registre vers dénominateur de population, registre de formation sanitaire vers agrégat DHIS2 — où le mode de défaillance n’est pas une valeur fausse mais un nombre de lignes qui a doublé pendant que vous le regardiez.

Animer cette leçon

La leçon en diaporama, la prose étant reléguée dans les notes du présentateur plutôt que projetée. Produit à partir de cette page, dont il ne peut donc pas s'écarter.

Lancer le diaporamaLire les diapositives

Le PDF ne requiert aucun logiciel et se projette depuis n'importe quel poste. Le fichier PowerPoint est fait pour être modifié : appliquez la charte de votre organisation, retirez une section pour une séance plus courte, ou fusionnez deux leçons en atelier.