cassionAnalyse de données

Retour à la leçonLeçon 2 sur 8Mesurer un enfant

Du poids et de la taille au score z

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 / 23

    Ce que couvre cette leçon

    • Ce que dit un score z
    • Trois scores z, trois questions
    • La méthode LMS
    • La clé de recherche a trois parties
    • Le calcul
    • Le signalement — deux règles, deux réponses
    • L'écart-type est déjà un constat
    • Enregistrez les scores z avec leurs entrées
    • La suite
    Notes du présentateur
    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.
  2. Diapositive 2 / 23

    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 ?
    Notes du présentateur
    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.
  3. Diapositive 3 / 23

    Trois scores z, trois questions

    ScoreCompareDéficit détectéRécupérable ?
    Poids-pour-taille (WHZ)Le poids à la tailleAigu — émaciationOui, en semaines
    Taille-pour-âge (HAZ)La taille à l'âgeChronique — retard de croissanceNon
    Poids-pour-âge (WAZ)Le poids à l'âgeLes deux à la fois — insuffisance pondéraleEn partie
  4. Diapositive 4 / 23

    Trois scores z, trois questions

    • 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…
    Notes du présentateur
    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.
  5. Diapositive 5 / 23

    La méthode LMS

    • L — la puissance de Box-Cox qui normalise une distribution asymétrique
    • M — la médiane
    • S — le coefficient de variation
    Notes du présentateur
    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.
  6. Diapositive 6 / 23

    La méthode LMS — Exemple

    z = ((weight / M)^L - 1) / (L * S)
  7. Diapositive 7 / 23

    La méthode LMS — En Python

    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")
  8. Diapositive 8 / 23

    La méthode LMS — En R

    reference <- readr::read_csv("who-2006-weight-for-lenhei.csv")
    nrow(reference)
    Notes du présentateur
    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.
  9. Diapositive 9 / 23

    La clé de recherche a trois parties — En Python

    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)
    Notes du présentateur
    C'est la partie qui dérape, et le laboratoire du cours sur les jointures était bâti dessus.
  10. Diapositive 10 / 23

    La clé de recherche a trois parties — En R

    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))
    }
  11. Diapositive 11 / 23

    La clé de recherche a trois parties

    • Le standard suit l'âge — non la position
    • 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…
    Notes du présentateur
    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.
  12. Diapositive 12 / 23

    Le calcul — En Python

    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")
  13. Diapositive 13 / 23

    Le calcul — En R

    # In R, use the official package rather than the table:
    # anthro::anthro_zscores(sex = ..., age = ..., weight = ..., lenhei = ..., measure = ...)
  14. Diapositive 14 / 23

    Le calcul

    • 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 à…
    • Une mesure dans la mauvaise unité — quatre tailles enregistrées en mètres, que le laboratoire du cours sur les…
    • Rapportez les trois séparément — « 66 enfants exclus » masque le fait que certains étaient des erreurs corrigeables
    Notes du présentateur
    864 sur 930 calculables. Les 66 restants se répartissent en trois groupes et la distinction compte. Rapportez les trois séparément. « 66 enfants exclus » masque le fait que certains étaient des erreurs corrigeables.
  15. Diapositive 15 / 23

    Le signalement — deux règles, deux réponses

    • 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.…
    Notes du présentateur
    Les scores z extrêmes sont exclus avant toute prévalence, et il existe deux conventions.
  16. Diapositive 16 / 23

    Le signalement — deux règles, deux réponses — En Python

    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()}")
  17. Diapositive 17 / 23

    Le signalement — deux règles, deux réponses — En R

    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)))
    Notes du présentateur
    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.
  18. Diapositive 18 / 23

    L'écart-type est déjà un constat — En Python

    analysable = smart.loc[who_flagged, "whz"]
    print(f"n = {len(analysable)}, mean = {analysable.mean():.2f}, "
          f"sd = {analysable.std():.2f}")
  19. Diapositive 19 / 23

    L'écart-type est déjà un constat — En R

    smart |> filter(who_ok) |> summarise(n = n(), mean = mean(whz), sd = sd(whz))
    Notes du présentateur
    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.
  20. Diapositive 20 / 23

    Enregistrez les scores z avec leurs entrées — En Python

    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)
  21. Diapositive 21 / 23

    Enregistrez les scores z avec leurs entrées — En R

    readr::write_csv(smart, here::here("outputs", "smart_with_zscores.csv"))
    Notes du présentateur
    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.
  22. Diapositive 22 / 23

    La suite

    • Vous avez un score z pour chaque enfant analysable.
    Notes du présentateur
    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.
  23. Diapositive 23 / 23

    La suite

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