cassionAnalyse de données

Leçon 3 sur 8

Unité · Qui est un cas

Les définitions de cas, et la clause que tout le monde oublie

Malnutrition aiguë sévère, modérée et globale, les seuils dont le secteur a convenu, et la clause des œdèmes qui rend fausse toute implémentation en « décompte sous le seuil ».

PythonR120 minNormes OMS de croissance de l'enfantStandards SphèreDéfinitions d'indicateurs de l'UNICEF

Les définitions

Trois termes, et ils s’emboîtent.

Terme Score z poids-taille PB Œdèmes
MAS — malnutrition aiguë sévère sous -3 sous 115 mm présents
MAM — malnutrition aiguë modérée -3 à moins de -2 115 à moins de 125 mm —
MAG — malnutrition aiguë globale sous -2 sous 125 mm présents

La MAG est la MAS plus la MAM. Ce n’est pas une affection distincte, c’est la charge totale de malnutrition aiguë, et c’est le chiffre auquel se réfèrent les phases IPC et le seuil d’urgence de 15 %.

Deux points structurels avant tout code.

Chaque ligne est à elle seule une définition complète. Un enfant est en MAS par le poids-pour-taille, ou par le PB, ou par les œdèmes — les critères sont des alternatives, non des exigences cumulatives. La leçon 4 porte entièrement sur l’ampleur du désaccord entre les deux premiers.

La colonne des œdèmes est un OU, non un ET. Un enfant présentant des œdèmes bilatéraux prenant le godet est sévère quoi que disent ses mesures. Cette clause est un terme d’une expression booléenne, et c’est le terme le plus souvent omis.

L’implémentation fausse

# WRONG: the definition everybody writes first
sam_wrong = (smart["whz"] < -3).sum()
# WRONG
sum(smart$whz < -3, na.rm = TRUE)

Elle est fausse de deux façons à la fois. Elle écarte les enfants œdémateux, et le na.rm ou une comparaison propageant les valeurs nulles écarte silencieusement les enfants sans score z — si bien que le numérateur et le dénominateur diffèrent tous deux de ce que le libellé prétend.

L’implémentation juste

import pandas as pd

analysable = smart[smart["whz"].between(-5, 5)].copy()
oedema = analysable["oedema"] == True

analysable["sam"] = (analysable["whz"] < -3) | oedema
analysable["mam"] = (analysable["whz"].between(-3, -2, inclusive="left")) & ~oedema
analysable["gam"] = analysable["sam"] | analysable["mam"]

n = len(analysable)
for label in ["sam", "mam", "gam"]:
    print(f"{label.upper():4} {analysable[label].sum():>4} / {n}  "
          f"{analysable[label].mean():.1%}")
analysable <- smart |> filter(between(whz, -5, 5))

analysable <- analysable |>
  mutate(sam = whz < -3 | oedema,
         mam = whz >= -3 & whz < -2 & !oedema,
         gam = sam | mam)

analysable |> summarise(across(c(sam, mam, gam), list(n = sum, rate = mean)), n = n())

852 enfants analysables : MAG 14,9 %, MAS 3,8 %.

Trois détails de ce code portent le résultat.

La MAM exclut explicitement les œdèmes. Un enfant œdémateux dont le score z tombe dans la bande modérée est sévère et non modéré, et sans le & ~oedema il serait compté dans les deux — si bien que MAS plus MAM dépasserait la MAG.

Les bornes sont semi-ouvertes. -3 <= z < -2. Un enfant exactement à -3,0 est sévère. Se tromper ici déplace une poignée d’enfants et c’est le genre de point sur lequel deux analystes découvrent leur désaccord au pire moment.

Le dénominateur est énoncé. 852, non 930 — la différence est faite des enfants sans score z calculable et de ceux hors des bornes de signalement, et la leçon 2 exigeait de rapporter ces trois groupes séparément.

Vérifiez que les parties totalisent le tout

assert (analysable["sam"] & analysable["mam"]).sum() == 0, "a child is both"
assert analysable["gam"].sum() == analysable["sam"].sum() + analysable["mam"].sum()
stopifnot(sum(analysable$sam & analysable$mam) == 0,
          sum(analysable$gam) == sum(analysable$sam) + sum(analysable$mam))

Deux assertions, et elles attrapent l’erreur des œdèmes, celle des bornes et toute modification future qui casserait l’emboîtement. Exécutez-les à chaque fois.

Les définitions par le PB, sur le registre

Le registre de dépistage a le PB et les œdèmes, sans poids ni taille, si bien qu’il ne soutient que les définitions fondées sur le PB.

muac = pd.read_csv("muac-screening-artibonite-2024.v1.csv")
measured = muac[muac["muac_mm"].notna()].copy()
oed = measured["oedema"] == True

measured["sam"] = (measured["muac_mm"] < 115) | oed
measured["gam"] = (measured["muac_mm"] < 125) | oed

print(f"n = {len(measured):,}  GAM {measured['gam'].mean():.1%}  "
      f"SAM {measured['sam'].mean():.1%}")
muac |>
  filter(!is.na(muac_mm)) |>
  summarise(n = n(),
            gam = mean(muac_mm < 125 | oedema),
            sam = mean(muac_mm < 115 | oedema))

Nommez la mesure dans l’indicateur. gam_muac_percent et gam_whz_percent sont deux indicateurs différents que l’on appelle tous deux « MAG », et la règle du cours sur la conception d’indicateurs consistant à mettre la mesure dans le nom n’est pas ici du pédantisme — la leçon suivante montre les deux en désaccord sur les trois quarts des cas sévères.

Ce qu’une définition ne dit pas

Trois choses que la définition de cas laisse délibérément de côté, et que quelqu’un supposera.

L’âge. Les définitions s’appliquent aux enfants de 6 à 59 mois. En dessous de six mois, les normes et les définitions diffèrent ; au-dessus de 59 mois, elles ne s’appliquent pas. Vérifiez la plage d’âge avant de classer.

out_of_scope = ~analysable["age_months"].between(6, 59)
print(f"{out_of_scope.sum()} children outside 6-59 months")
sum(!between(analysable$age_months, 6, 59), na.rm = TRUE)

L’admission. Une définition de cas dit qui est malnutri. Savoir s’il est admis dépend du protocole du programme, qui peut employer un critère, les deux, ou le PB pour le dépistage communautaire et le poids-pour-taille au site. Le champ admission_criterion du registre enregistre ce que le site a saisi, non tout ce que l’enfant remplissait.

La gravité à l’intérieur du sévère. Une MAS avec complications exige des soins hospitaliers ; sans complications, ambulatoires. La définition ne les distingue pas, et le test de l’appétit et les signes cliniques qui le font ne figurent pas dans un jeu de données anthropométrique.

Une définition de cas est une règle de classification, non une décision thérapeutique. Confondre les deux produit une charge de cas qui ne correspond aux admissions d’aucun programme et une discussion que les données ne peuvent pas trancher.

La suite

Vous savez classer un enfant par l’une ou l’autre mesure. La leçon suivante place les deux mesures sur les mêmes enfants et constate qu’elles divergent sur les trois quarts des cas sévères — et que ce désaccord a une cause qui tient en un nombre.

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.