Leçon 2 sur 8
Unité · Mesurer un enfant
Du poids et de la taille au score z
La méthode LMS, la recherche dans la table de référence, les trois scores z et ce que chacun mesure. Calculé sur 930 enfants, il donne une moyenne de -0,67 et un écart-type de 1,22 — et ce second nombre est déjà un constat.
Ce que dit un score z
Un score z répond à une seule question — à quelle distance cet enfant est-il de la médiane d’une population de référence en bonne santé, en écarts-types ?
Un score z poids-pour-taille de -2 signifie que cet enfant pèse ce que pèse un enfant situé à deux écarts-types sous la médiane, pour sa taille. Ce n’est un pourcentage de rien, et ce n’est pas comparable à un percentile sans conversion.
La référence est constituée par les normes OMS 2006 de croissance de l’enfant, bâties sur une étude multi-pays d’enfants élevés dans des conditions ne limitant pas la croissance — allaités, foyers non-fumeurs, soins adéquats. Cette construction est délibérée : les normes décrivent comment les enfants devraient grandir, non comment les enfants d’un lieu donné grandissent.
Trois scores z, trois questions
| Score | Compare | Déficit détecté | Récupérable ? |
|---|---|---|---|
| Poids-pour-taille (WHZ) | Le poids à la taille | Aigu — émaciation | Oui, en semaines |
| Taille-pour-âge (HAZ) | La taille à l’âge | Chronique — retard de croissance | Non |
| Poids-pour-âge (WAZ) | Le poids à l’âge | Les deux à la fois — insuffisance pondérale | En partie |
Le poids-pour-âge est celui dont il faut se méfier. Il mélange les deux déficits, si bien qu’un WAZ bas ne dit pas si l’enfant est émacié, en retard de croissance ou les deux, et la réponse programmatique diffère. Il survit en suivi de la croissance parce qu’il n’exige pas de toise, et il ne doit pas servir à classer la malnutrition aiguë.
Ce cours calcule le poids-pour-taille, car c’est sur lui que reposent les définitions de cas et les seuils IPC.
La méthode LMS
Les normes sont publiées sous forme de trois paramètres, par sexe, par mesure et par tranche de 0,1 cm de longueur ou de taille.
- L — la puissance de Box-Cox qui normalise une distribution asymétrique
- M — la médiane
- S — le coefficient de variation
z = ((weight / M)^L - 1) / (L * S)
import pandas as pd
reference = pd.read_csv("who-2006-weight-for-lenhei.csv")
print(reference.head(3))
print(f"{len(reference)} rows: sex x standard x lenhei in 0.1 cm steps")
reference <- readr::read_csv("who-2006-weight-for-lenhei.csv")
nrow(reference)
2 404 lignes. Lisez la table ; ne réimplémentez pas l’interpolation d’après un
manuel. R dispose du paquet officiel anthro ; Python n’a pas d’équivalent
maintenu qui s’installe proprement, et c’est exactement pourquoi cette table est
livrée ici.
La clé de recherche a trois parties
C’est la partie qui dérape, et le laboratoire du cours sur les jointures était bâti dessus.
def lookup_key(row):
lying = row["measured_lying"] == "true"
standard = "L" if row["age_months"] < 24 else "H"
lenhei = row["height_cm"]
if standard == "L" and not lying:
lenhei += 0.7
elif standard == "H" and lying:
lenhei -= 0.7
return row["sex"], standard, round(lenhei, 1)
lookup_key <- function(sex, age, height, lying) {
standard <- if (age < 24) "L" else "H"
lenhei <- height +
if (standard == "L" && !lying) 0.7 else if (standard == "H" && lying) -0.7 else 0
list(sex = sex, lorh = standard, lenhei = round(lenhei, 1))
}
Trois éléments de cette fonction sont des décisions, non de la mécanique.
Le standard suit l’âge, non la position. Un enfant de 30 mois mesuré couché est malgré tout évalué selon le standard de taille, avec l’ajustement appliqué.
L’ajustement porte sur la mesure, non sur le standard. Vous convertissez la mesure en celle que le standard attend.
L’arrondi est à une décimale, des deux côtés, en un seul endroit. Un flottant issu d’un ajustement n’est pas le même flottant que celui lu dans un CSV, ce qui est la jointure sur clé inexacte à laquelle le cours sur les jointures a consacré un laboratoire.
Le calcul
reference["key"] = list(zip(reference["sex"], reference["lorh"],
reference["lenhei"].round(1)))
lms = reference.set_index("key")[["l", "m", "s"]]
def whz(row):
key = lookup_key(row)
if key not in lms.index or pd.isna(row["weight_kg"]):
return None
l, m, s = lms.loc[key]
return (((row["weight_kg"] / m) ** l) - 1) / (l * s)
smart["whz"] = smart.apply(whz, axis=1)
print(f"{smart['whz'].notna().sum()} of {len(smart)} computable")
# In R, use the official package rather than the table:
# anthro::anthro_zscores(sex = ..., age = ..., weight = ..., lenhei = ..., measure = ...)
864 sur 930 calculables. Les 66 restants se répartissent en trois groupes et la distinction compte.
- Poids ou âge manquant — 32 enfants, et ce sont des données manquantes.
- Taille hors de la plage de référence — le standard de longueur va de 45,0 à 110,0 cm et celui de taille de 65,0 à 120,0 cm. Un enfant hors de cette plage est réellement inclassable.
- Une mesure dans la mauvaise unité — quatre tailles enregistrées en mètres, que le laboratoire du cours sur les jointures a trouvées par anti-jointure. Celles-là sont récupérables.
Rapportez les trois séparément. « 66 enfants exclus » masque le fait que certains étaient des erreurs corrigeables.
Le signalement — deux règles, deux réponses
Les scores z extrêmes sont exclus avant toute prévalence, et il existe deux conventions.
- Valeurs aberrantes OMS — bornes fixes, exclure les z hors de -5 à +5. Absolu, comparable entre enquêtes.
- Valeurs aberrantes SMART — relatif, exclure les observations à plus de 3 ET de la moyenne de l’enquête elle-même. S’adapte à l’enquête, et la réduit davantage quand elle est plus bruitée.
who_flagged = smart["whz"].between(-5, 5)
mean, sd = smart["whz"].mean(), smart["whz"].std()
smart_flagged = smart["whz"].between(mean - 3 * sd, mean + 3 * sd)
print(f"WHO flags keep {who_flagged.sum()}, SMART flags keep {smart_flagged.sum()}")
smart <- smart |>
mutate(who_ok = between(whz, -5, 5),
smart_ok = between(whz, mean(whz, na.rm = TRUE) - 3 * sd(whz, na.rm = TRUE),
mean(whz, na.rm = TRUE) + 3 * sd(whz, na.rm = TRUE)))
Elles excluent des enfants différents et donnent des taux légèrement différents. Dites laquelle vous avez employée ; un rapport de plausibilité SMART l’exige, et deux enquêtes employant des règles différentes ne sont pas directement comparables.
L’écart-type est déjà un constat
analysable = smart.loc[who_flagged, "whz"]
print(f"n = {len(analysable)}, mean = {analysable.mean():.2f}, "
f"sd = {analysable.std():.2f}")
smart |> filter(who_ok) |> summarise(n = n(), mean = mean(whz), sd = sd(whz))
852 enfants, moyenne -0,67, écart-type 1,22.
La moyenne n’a rien de remarquable — une population un peu sous la médiane de référence, ce qui est normal dans ce secteur. L’écart-type, si. Une enquête bien mesurée produit un écart-type de poids-pour-taille compris entre environ 0,8 et 1,2, car l’écart-type de la population de référence vaut 1 par construction et les populations réelles ne sont que légèrement plus dispersées.
1,22 se situe à la limite de l’acceptable, et un écart-type au-dessus de la plage signifie l’une de trois choses — une erreur de mesure qui gonfle la dispersion, une population réellement hétérogène, ou un problème de saisie. C’est le nombre le plus informatif d’un rapport de plausibilité, et la leçon 5 apprend à le lire correctement.
Remarquez aussi ce qu’il fait à la prévalence. Une distribution plus large place davantage d’enfants au-delà d’un seuil fixe, si bien qu’un écart-type gonflé fait monter la MAG sans qu’aucun enfant ne soit plus malnutri.
Enregistrez les scores z avec leurs entrées
smart[["child_id", "cluster", "team", "age_months", "sex", "weight_kg",
"height_cm", "measured_lying", "oedema", "whz"]].to_csv(
"outputs/smart_with_zscores.csv", index=False)
readr::write_csv(smart, here::here("outputs", "smart_with_zscores.csv"))
Gardez les entrées à côté du résultat. Quand quelqu’un conteste une prévalence, la discussion ne porte presque jamais sur l’arithmétique — elle porte sur l’ajustement, la règle de signalement ou les enfants exclus, et les trois ne sont récupérables que si les entrées ont voyagé avec le résultat.
La suite
Vous avez un score z pour chaque enfant analysable. L’unité suivante en fait une classification — les définitions de cas de la malnutrition aiguë sévère et modérée, et le signe clinique qui prime sur les deux.