Leçon 7 sur 8
Unité · Le plan et l'ajustement
Deux coefficients traversent le seuil et un le retraverse
La strate rurale isolée pèse 11 % des ménages et un tiers des entretiens. Ajustez le modèle sans pondération et l'élevage ressemble à un facteur de risque significatif ; pondérez-le et il cesse de l'être, tandis que la taille du ménage et le statut de retourné se mettent à l'être.
Le plan sous lequel l’échantillon a été tiré
import pandas as pd
survey = pd.read_csv("household-survey-2025.v1.csv")
frame = pd.read_csv("household-survey-frame-2025.v1.csv")
print(frame.groupby("stratum")["households"].sum())
print(survey.groupby("stratum").size())
library(dplyr)
frame |> summarise(households = sum(households), .by = stratum)
survey |> count(stratum)
| Strate | Ménages du sondage | Part | Entretiens | Part |
|---|---|---|---|---|
| Rurale accessible | 28 958 | 51,3 % | 337 | 33,8 % |
| Urbaine | 21 270 | 37,7 % | 316 | 31,7 % |
| Rurale isolée | 6 200 | 11,0 % | 343 | 34,4 % |
La strate rurale isolée pèse 11,0 % de la population et 34,4 % de l’échantillon. C’est un choix de plan délibéré — le cours sur les enquêtes explique pourquoi on suréchantillonne une petite strate dont on a besoin d’estimations — et cela signifie que chaque nombre non pondéré tiré de ce fichier décrit une population qui n’existe pas.
Ce que les poids font à une estimation
stratum_households = frame.groupby("stratum")["households"].sum()
base_weight = stratum_households / (25 * 14)
interviewed = frame[frame["selected"]].set_index("ea_id")["households_interviewed"]
survey["weight"] = (survey["stratum"].map(base_weight)
* 14 / survey["ea_id"].map(interviewed))
assert abs(survey["weight"].sum() - frame["households"].sum()) < 1
unweighted = survey["food_insecure"].mean()
weighted = np.average(survey["food_insecure"], weights=survey["weight"])
print(f"unweighted {unweighted:.1%} weighted {weighted:.1%}")
survey <- survey |>
mutate(weight = base_weight[stratum] * 14 / households_interviewed)
c(unweighted = mean(survey$food_insecure),
weighted = weighted.mean(survey$food_insecure, survey$weight))
32,8 % sans pondération, 29,1 % avec. La strate rurale isolée a l’insécurité alimentaire la plus élevée (46,4 %), et la surreprésenter trois fois tire le chiffre national vers le haut de 3,7 points.
Une régression ajustée sur ce fichier sans poids hérite exactement de ce
problème, et cela ne se corrige pas en ajoutant stratum comme covariable — cela
change la question de « quelle est l’association dans la population » à « quelle
est-elle à l’intérieur des strates ». Les deux sont légitimes ; une seule est ce que
signifie une estimation nationale.
Le même modèle, pondéré et non
import statsmodels.api as sm
import statsmodels.formula.api as smf
FORMULA = ("food_insecure ~ improved_water_source + displacement_status"
" + main_livelihood + household_size")
plain = smf.glm(FORMULA, data=d, family=sm.families.Binomial()).fit(
cov_type="cluster", cov_kwds={"groups": d["ea_id"]})
weighted = smf.glm(FORMULA, data=d, family=sm.families.Binomial(),
freq_weights=d["weight"]).fit(
cov_type="cluster", cov_kwds={"groups": d["ea_id"]})
library(survey)
design <- svydesign(ids = ~ea_id, strata = ~stratum, weights = ~weight,
data = survey, nest = TRUE)
svyglm(food_insecure ~ improved_water_source + displacement_status +
main_livelihood + household_size, design = design,
family = quasibinomial())
| Terme | RC non pondéré | RC pondéré | Bouge ? |
|---|---|---|---|
| Source d’eau améliorée | 0,75 (0,55–1,03) | 0,74 (0,51–1,08) | — |
| Déplacement : retourné | 0,56 (0,25–1,26) | 0,39 (0,15–0,97) | devient significatif |
| Moyen d’existence : agriculture | 1,55 (1,03–2,34) | 1,69 (1,04–2,75) | — |
| Moyen d’existence : élevage | 1,51 (1,04–2,18) | 1,26 (0,73–2,18) | cesse d’être significatif |
| Moyen d’existence : salarié | 0,41 (0,22–0,77) | 0,45 (0,24–0,87) | — |
| Taille du ménage | 1,04 (0,98–1,11) | 1,08 (1,01–1,16) | devient significatif |
Trois coefficients changent de côté du seuil, dans les deux sens. La pondération n’est pas une correction qui affaiblit tout ou renforce tout — elle repondère les ménages depuis lesquels l’association est estimée, et la réponse bouge partout où ces ménages diffèrent.
Les moyens d’existence par l’élevage sont concentrés dans la strate isolée suréchantillonnée. Sans pondération, ils portent un tiers de l’influence de l’échantillon ; pondérés, ils portent leurs 11 % réels, et l’association se dissipe.
Poids, grappes et strates sont trois choses distinctes
Ils arrivent ensemble et font trois travaux différents, et un modèle peut aisément en réussir un et rater les deux autres.
| Élément du plan | Corrige | Si vous l’omettez |
|---|---|---|
| Poids | L’estimation | Les estimations décrivent l’échantillon, non la population |
| Grappes | L’erreur-type | Erreurs-types trop petites, comme à la leçon précédente |
| Strates | L’erreur-type | Erreurs-types un peu trop grandes — l’erreur conservatrice |
Les poids changent le coefficient ; les grappes et les strates changent son intervalle. C’est la même distinction qu’ajustement contre grappes à la leçon 2, arrivant par une autre porte, et c’est celle à retenir.
print(f"clusters: {d['ea_id'].nunique()} enumeration areas")
print(f"strata: {d['stratum'].nunique()}")
print(f"weights: {d['weight'].min():.1f} to {d['weight'].max():.1f}")
# survey::svydesign wants all three; a glm with weights= handles only one.
glm(..., weights=) n’est pas une régression pondérée par le plan. Elle applique
les poids et calcule les erreurs-types comme si chaque observation était indépendante
et les poids des effectifs. Employez survey::svyglm en R, et en Python passez à la
fois freq_weights et une covariance par grappes — ou acceptez que l’intervalle soit
faux et dites-le.
Quand laisser les poids de côté
Deux cas, et aucun n’est « les poids ont fait disparaître mon résultat ».
Une question intra-strate. « Parmi les ménages ruraux isolés, une source d’eau améliorée va-t-elle avec moins d’insécurité alimentaire ? » est une question sur cette strate, et le poids de sondage à l’intérieur d’une strate est de toute façon quasi constant.
Un modèle dont les covariables contiennent tout ce dont les poids sont faits. Si la strate et la probabilité de sélection sont entièrement captées par les covariables, les estimations pondérée et non pondérée répondent à la même question et la non pondérée est plus précise. Vérifiez-le plutôt que de le supposer : ajustez les deux, et si elles diffèrent sensiblement, les covariables n’ont pas capté le plan.
print(f"unweighted {plain.params['main_livelihood[T.livestock]']:.3f}")
print(f"weighted {weighted.params['main_livelihood[T.livestock]']:.3f}")
# A large gap between the two is evidence the design is not in the model.
Un grand écart entre l’ajustement pondéré et le non pondéré est en soi un diagnostic, et c’est la vérification à faire avant de décider que les poids sont facultatifs.
Rapportez-le en entier
Food insecurity, household survey 2025
976 households with complete covariates (of 996 interviewed),
75 enumeration areas, 3 strata.
Survey-weighted logistic regression; weights sum to 56,428 households,
which is the frame total. Standard errors account for clustering by
enumeration area and for stratification.
Weighted prevalence 29.1% (unweighted 32.8%)
Adjusted odds ratios (weighted):
Improved water source 0.74 95% CI 0.51 to 1.08
Returnee household 0.39 95% CI 0.15 to 0.97
Farming livelihood 1.69 95% CI 1.04 to 2.75
Livestock livelihood 1.26 95% CI 0.73 to 2.18
Salaried livelihood 0.45 95% CI 0.24 to 0.87
Household size, per person 1.08 95% CI 1.01 to 1.16
The unweighted model makes livestock livelihoods significant (OR 1.51,
95% CI 1.04 to 2.18) and household size not. The rural remote stratum is
11% of households and 34% of interviews, and livestock is concentrated
there; the unweighted result is an artefact of the sampling design.
Odds ratios are reported because food insecurity is 29% and the ratios are
moderate; the weighted risk difference for salaried livelihoods is -14.2
points against the observed mix of livelihoods, which is the number in
the summary.
Le paragraphe qui nomme l’artefact est ce qu’un relecteur vérifiera en premier, et l’écrire vous-même vaut mieux que de le laisser trouver.
La suite
Chaque modèle jusqu’ici a été ajusté puis lu. La dernière leçon en ajuste un qui explique trois pour cent de son résultat, ne fait pas mieux que deviner, et constitue le constat le plus utile de son rapport — parce que ce qu’il échoue à prédire est la réponse opérationnelle.