cassionAnalyse de données

Retour à la leçonLeçon 2 sur 8L'échantillon n'est pas la population

Construire les pondérations à partir de la base

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

    Ce que couvre cette leçon

    • Une pondération est un nombre avec un seul sens
    • Premier degré — probabilité proportionnelle à la taille
    • Second degré — un tirage fixe
    • Les deux probabilités se compensent
    • L'ajustement pour non-réponse
    • Le contrôle qui prouve toute la construction
    • Pondérations normalisées, et quand s'en servir
    • Pondérations par personne et de sous-échantillon
    • Enregistrez les pondérations à côté des données
    • La suite
    Notes du présentateur
    Probabilité de sélection à chaque degré, la pondération de base qu'elle implique, l'ajustement pour non-réponse, et le contrôle qui prouve l'ensemble — des pondérations totalisant 56 428, exactement ce que la base déclare.
  2. Diapositive 2 / 31

    Une pondération est un nombre avec un seul sens

    • Une pondération de sondage, c'est le nombre d'unités de la population que représente l'unité tirée
    Notes du présentateur
    Une pondération de sondage, c'est le nombre d'unités de la population que représente l'unité tirée. Cette phrase est toute la leçon. Le reste n'est que l'arithmétique pour y parvenir, et chaque contrôle est une façon de demander si les pondérations veulent toujours dire cela. La pondération est l'inverse de la probabilité de sélection. Un ménage ayant une chance sur 60 d'être retenu représente 60 ménages ; un ménage ayant une chance sur 18 en représente 18. Rien de plus mystérieux.
  3. Diapositive 3 / 31

    Premier degré — probabilité proportionnelle à la taille — Exemple

    P(area i selected) = n_h * M_i / M_h
    Notes du présentateur
    Vingt-cinq zones de dénombrement ont été tirées dans chaque strate, avec une probabilité proportionnelle aux ménages que chaque zone contient.
  4. Diapositive 4 / 31

    Premier degré — probabilité proportionnelle à la taille — En Python

    import pandas as pd
    
    frame = pd.read_csv("household-survey-frame-2025.v1.csv")
    
    stratum_households = frame.groupby("stratum")["households"].sum()
    selected = frame[frame["selected"] == True].copy()
    
    selected["p_stage1"] = (
        25 * selected["households"] / selected["stratum"].map(stratum_households)
    )
    print(selected[["ea_id", "stratum", "households", "p_stage1"]].head())
    Notes du présentateur
    où n_h est le nombre de zones tirées dans la strate h (25), M_i les ménages de la zone i, et M_h les ménages de toute la strate.
  5. Diapositive 5 / 31

    Premier degré — probabilité proportionnelle à la taille — En R

    library(dplyr)
    
    stratum_households <- frame |> summarise(M_h = sum(households), .by = stratum)
    
    selected <- frame |>
      filter(selected) |>
      left_join(stratum_households, by = "stratum") |>
      mutate(p_stage1 = 25 * households / M_h)
    Notes du présentateur
    Une zone plus grande a plus de chances d'être retenue. C'est tout l'objet du tirage proportionnel à la taille — il place les entretiens là où sont les gens, ce qui évite qu'une enquête dépense un tiers de son budget dans des hameaux.
  6. Diapositive 6 / 31

    Second degré — un tirage fixe — Exemple

    P(household selected | area selected) = m / M_i
    Notes du présentateur
    Quatorze ménages ont été tirés dans chaque zone retenue, à partir de la liste de cette zone.
  7. Diapositive 7 / 31

    Second degré — un tirage fixe — En Python

    selected["p_stage2"] = 14 / selected["households"]
    selected["p_overall"] = selected["p_stage1"] * selected["p_stage2"]
    print(selected.groupby("stratum")["p_overall"].describe()[["min", "max"]])
    Notes du présentateur
    avec m = 14.
  8. Diapositive 8 / 31

    Second degré — un tirage fixe — En R

    selected <- selected |>
      mutate(p_stage2 = 14 / households,
             p_overall = p_stage1 * p_stage2)
    
    selected |> summarise(min = min(p_overall), max = max(p_overall), .by = stratum)
  9. Diapositive 9 / 31

    Les deux probabilités se compensent — Exemple

    P(household) = (n_h * M_i / M_h) * (m / M_i) = n_h * m / M_h
    Notes du présentateur
    Développez le produit et M_i disparaît.
  10. Diapositive 10 / 31

    Les deux probabilités se compensent

    • Deux conséquences à retenir — Une pondération qui varie à l'intérieur d'une strate dans un plan proportionnel à la…
    Notes du présentateur
    Tout ménage d'une strate a la même probabilité globale, quelle que soit la taille de sa zone. Le plan est autopondéré à l'intérieur d'une strate. Exécutez le code et le minimum et le maximum de p_overall sont identiques dans chaque strate, ce qui est l'arithmétique qui le confirme. Ce n'est ni une coïncidence ni une commodité — c'est précisément pourquoi le tirage proportionnel à la taille va de pair avec un tirage fixe, dans les EDS, les MICS et la méthodologie SMART. La mesure de taille qui décide des zones visitées est annulée par celle qui décide du nombre de ménages tirés. Deux conséquences à retenir. Une pondération qui varie à l'intérieur d'une strate dans un plan proportionnel à la taille signale un problème — en général une base dont la mesure de taille est périmée. Et la pondération de base est une propriété de la strate, non du ménage, si bien qu'elle se calcule en trois nombres.
  11. Diapositive 11 / 31

    Les deux probabilités se compensent — En Python

    base_weight = stratum_households / (25 * 14)
    print(base_weight.round(1))
  12. Diapositive 12 / 31

    Les deux probabilités se compensent — En R

    stratum_households |> mutate(base_weight = M_h / (25 * 14))
  13. Diapositive 13 / 31

    Les deux probabilités se compensent

    StrateMénages dans la basePondération de base
    Urbain21 27060,8
    Rural accessible28 95882,7
    Rural reculé6 20017,7
    Notes du présentateur
    Un ménage rural reculé en représente dix-huit ; un ménage rural accessible en représente quatre-vingt-trois. Ce rapport est toute la différence entre 32,8 % et 29,1 %.
  14. Diapositive 14 / 31

    L'ajustement pour non-réponse — En Python

    survey = pd.read_csv("household-survey-2025.v1.csv")
    
    interviewed = selected.set_index("ea_id")["households_interviewed"]
    
    survey["base_weight"] = survey["stratum"].map(base_weight)
    survey["nr_adjustment"] = 14 / survey["ea_id"].map(interviewed)
    survey["weight"] = survey["base_weight"] * survey["nr_adjustment"]
    
    print(survey["weight"].describe()[["min", "max"]].round(1))
    Notes du présentateur
    Quatorze ménages ont été tirés par zone. Moins ont été enquêtés — 996 des 1 050 tirés. Les ménages enquêtés doivent porter ceux qui ne l'ont pas été.
  15. Diapositive 15 / 31

    L'ajustement pour non-réponse — En R

    survey <- survey |>
      left_join(select(selected, ea_id, households_interviewed), by = "ea_id") |>
      left_join(mutate(stratum_households, base_weight = M_h / (25 * 14)), by = "stratum") |>
      mutate(weight = base_weight * 14 / households_interviewed)
    
    range(survey$weight)
  16. Diapositive 16 / 31

    L'ajustement pour non-réponse

    • Ajustez à l'intérieur de la zone, pas de la strate — Les ménages qui n'ont pas répondu dans une zone donnée ressemblent…
    Notes du présentateur
    Les pondérations vont désormais de 17,7 à 96,5. Ajustez à l'intérieur de la zone, pas de la strate. Les ménages qui n'ont pas répondu dans une zone donnée ressemblent bien plus aux ménages ayant répondu dans cette zone qu'à la moyenne de la strate. Ajuster au niveau de la strate est plus simple et jette précisément l'information qui rend l'ajustement utile. L'hypothèse est énoncée et elle n'est pas gratuite — on suppose que les non-répondants ressemblent aux répondants de la même zone. Là où vous avez des raisons d'en douter — des concessions fermées dans un quartier, un incident de sécurité un jour donné — dites-le dans les limites, car aucune pondération n'y remédie.
  17. Diapositive 17 / 31

    Le contrôle qui prouve toute la construction — En Python

    total = survey["weight"].sum()
    frame_total = frame["households"].sum()
    print(f"weights sum to {total:,.0f}; frame holds {frame_total:,}")
    assert abs(total - frame_total) < 1
  18. Diapositive 18 / 31

    Le contrôle qui prouve toute la construction — En R

    c(weights = sum(survey$weight), frame = sum(frame$households))
  19. Diapositive 19 / 31

    Le contrôle qui prouve toute la construction

    • 56 428 et 56 428 — Les pondérations totalisent exactement le nombre de ménages que la base déclare, ce que « combien…
    Notes du présentateur
    56 428 et 56 428. Les pondérations totalisent exactement le nombre de ménages que la base déclare, ce que « combien d'unités celle-ci représente » doit signifier pour signifier quelque chose. Faites ce contrôle à chaque fois. Il attrape une strate dont la pondération de base a employé le mauvais dénominateur, un ajustement pour non-réponse appliqué deux fois, et une jointure qui a perdu des zones — trois erreurs autrement invisibles, puisque l'estimation obtenue ressemble toujours à un pourcentage.
  20. Diapositive 20 / 31

    Pondérations normalisées, et quand s'en servir — En Python

    survey["weight_norm"] = survey["weight"] / survey["weight"].mean()
    Notes du présentateur
    Certains logiciels veulent des pondérations de moyenne un plutôt que totalisant la population.
  21. Diapositive 21 / 31

    Pondérations normalisées, et quand s'en servir — En R

    survey <- survey |> mutate(weight_norm = weight / mean(weight))
    Notes du présentateur
    Proportions et moyennes sont identiques dans les deux cas — la mise à l'échelle s'annule. Les totaux, non. Une pondération normalisée ne peut pas estimer « combien de ménages sont en insécurité alimentaire », seulement « quelle part ». Gardez la pondération à l'échelle de la population comme référence et dérivez la normalisée là où un outil l'exige.
  22. Diapositive 22 / 31

    Pondérations par personne et de sous-échantillon

    • Une pondération par personne — est la pondération du ménage multipliée par sa taille, car un ménage de huit représente…
    Notes du présentateur
    Deux autres pondérations découlent de la même logique, et les deux sont régulièrement fausses. Une pondération par personne est la pondération du ménage multipliée par sa taille, car un ménage de huit représente huit fois plus de personnes que de ménages.
  23. Diapositive 23 / 31

    Pondérations par personne et de sous-échantillon — En Python

    people = survey[survey["household_size"].notna()].copy()
    people["person_weight"] = people["weight"] * people["household_size"]
    print(f"estimated population {people['person_weight'].sum():,.0f}")
  24. Diapositive 24 / 31

    Pondérations par personne et de sous-échantillon — En R

    people <- survey |>
      filter(!is.na(household_size)) |>
      mutate(person_weight = weight * household_size)
    
    sum(people$person_weight)
  25. Diapositive 25 / 31

    Pondérations par personne et de sous-échantillon

    • Une pondération de sous-échantillon — s'applique quand une unité est choisie parmi plusieurs
    Notes du présentateur
    Cela donne 333 336 contre 328 127 dans la liste de base — 1,6 % d'écart. Vingt ménages n'ont pas de taille enregistrée et sortent, et une liste de base est elle-même une estimation faite des mois plus tôt. Un écart de cet ordre est normal et mérite d'être énoncé ; un écart de 20 % signale un problème. Une pondération de sous-échantillon s'applique quand une unité est choisie parmi plusieurs. Un enfant de moins de cinq ans a été mesuré par ménage, si bien qu'un enfant mesuré dans un ménage comptant trois enfants éligibles en représente trois.
  26. Diapositive 26 / 31

    Pondérations par personne et de sous-échantillon — En Python

    children = survey[survey["child_muac_mm"].notna()].copy()
    children["child_weight"] = children["weight"] * children["children_under5"]
  27. Diapositive 27 / 31

    Pondérations par personne et de sous-échantillon — En R

    children <- survey |>
      filter(!is.na(child_muac_mm)) |>
      mutate(child_weight = weight * children_under5)
    Notes du présentateur
    Sautez cette multiplication et les enfants des grands ménages sont sous-représentés — or les grands ménages sont systématiquement plus pauvres, donc le biais va dans un sens prévisible. Sur cette enquête, la malnutrition aiguë par PB est de 13,3 % parmi les enfants mesurés et de 11,4 % une fois les pondérations enfant appliquées.
  28. Diapositive 28 / 31

    Enregistrez les pondérations à côté des données — En Python

    survey[["household_id", "ea_id", "stratum", "base_weight",
            "nr_adjustment", "weight"]].to_csv("outputs/weights.csv", index=False)
  29. Diapositive 29 / 31

    Enregistrez les pondérations à côté des données — En R

    survey |>
      select(household_id, ea_id, stratum, base_weight, households_interviewed, weight) |>
      readr::write_csv(here::here("outputs", "weights.csv"))
    Notes du présentateur
    Conservez les composantes, pas seulement la pondération finale. Quand quelqu'un demandera dans un an pourquoi un ménage compte pour 96 et un autre pour 18, la réponse est dans les colonnes et non dans votre souvenir d'un script.
  30. Diapositive 30 / 31

    La suite

    • Vous savez désormais produire une estimation de population.
    Notes du présentateur
    Vous savez désormais produire une estimation de population. L'unité suivante demande ce qu'elle a coûté — combien de ménages exige une précision donnée, et pourquoi la formule de taille d'échantillon des manuels donne à peu près la moitié de ce qu'une enquête en grappes réclame réellement.
  31. Diapositive 31 / 31

    La suite

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