cassionAnalyse de données

Leçon 8 sur 8

Unité · Le plan et l'ajustement

Un R² de 0,03, et le constat le plus utile du rapport

Douze caractéristiques de ménage expliquent trois pour cent de la variation du PB des enfants. Cibler le dépistage sur les 20 % les moins bien prédits trouve 31 % des enfants malnutris, contre 20 % au hasard. Le modèle a échoué, et son échec est la réponse opérationnelle.

PythonR150 minEnquête SMARTNormes OMS de croissance de l'enfantDéfinitions d'indicateurs de l'UNICEFCritères d'évaluation du CAD de l'OCDE

Un modèle bâti pour répondre à une question de ciblage

Un programme veut dépister moins d’enfants. Si les caractéristiques des ménages prédisaient quels enfants sont malnutris, le dépistage pourrait viser les ménages qui en abritent le plus probablement, et l’enquête porte toutes les variables qu’une telle règle emploierait.

import pandas as pd
import numpy as np
import statsmodels.formula.api as smf

survey = pd.read_csv("household-survey-2025.v1.csv")
d = survey.dropna(subset=["child_muac_mm", "child_age_months", "child_sex",
                          "household_size", "displacement_status",
                          "main_livelihood", "food_insecure",
                          "improved_water_source"])

model = smf.ols(
    "child_muac_mm ~ child_age_months + child_sex + household_size"
    " + displacement_status + main_livelihood + food_insecure"
    " + improved_water_source", data=d).fit()

print(f"n = {int(model.nobs)}   R2 = {model.rsquared:.4f}"
      f"   adjusted R2 = {model.rsquared_adj:.4f}")
print(f"residual SD {np.sqrt(model.scale):.2f}  outcome SD {d['child_muac_mm'].std():.2f}")
model <- lm(child_muac_mm ~ child_age_months + child_sex + household_size +
              displacement_status + main_livelihood + food_insecure +
              improved_water_source, data = d)
summary(model)

n = 641. R² = 0,030, R² ajusté = 0,011. Écart-type résiduel 15,95 mm contre un écart-type du résultat de 16,04 mm.

Le modèle a retiré moins d’un millimètre des seize dont il partait. Un seul coefficient se distingue de zéro.

Terme Coefficient IC à 95 %
Insécurité alimentaire −4,70 mm −7,45 à −1,95
Moyen d’existence salarié −3,49 mm −8,44 à +1,45
Moyen d’existence agricole −2,76 mm −6,16 à +0,64
Âge de l’enfant, par mois −0,03 mm −0,11 à +0,05
Source d’eau améliorée −1,09 mm −3,76 à +1,58

Ne le supprimez pas

L’instinct est d’écarter le modèle, d’essayer plus de variables, ou de se tourner vers quelque chose de non linéaire. Les trois sont faux ici, et la raison est que la question n’était pas « puis-je modéliser le PB » — c’était « puis-je cibler le dépistage ».

d = d.assign(predicted=model.fittedvalues, mam=(d["child_muac_mm"] < 125))
for frac in (0.20, 0.30, 0.50):
    cut = d["predicted"].quantile(frac)
    caught = d.loc[d["predicted"] <= cut, "mam"].sum()
    print(f"screen worst {frac:.0%}: catches {caught}/{d['mam'].sum()}"
          f" = {caught / d['mam'].sum():.1%} of cases")
d |> mutate(predicted = fitted(model), mam = child_muac_mm < 125) |>
  arrange(predicted) |>
  summarise(caught = mean(head(mam, n() * 0.2)) * sum(mam))
Règle de dépistage Enfants dépistés PB < 125 mm trouvés
20 % les moins bien prédits 129 28 sur 90 = 31,1 %
30 % les moins bien prédits 193 41 sur 90 = 45,6 %
50 % les moins bien prédits 321 54 sur 90 = 60,0 %
20 % au hasard 129 20 % attendus

Le ciblage par le modèle trouve 31 % des enfants malnutris en en dépistant 20 %. Dépister 20 % au hasard en trouve 20 %. Le modèle fait onze points mieux que le hasard et manque sept enfants sur dix parmi ceux qu’un programme existe pour atteindre.

C’est cela, le constat. Non pas « le modèle n’a pas marché » — les caractéristiques des ménages n’identifient pas assez bien les enfants malnutris pour cibler le dépistage, donc le dépistage doit rester systématique. Un programme peut agir sur cette phrase, elle coûte une somme réelle, et elle est étayée par un modèle de R² 0,03.

Des diagnostics qui changent une décision

Quatre vérifications, chacune assortie d’une décision plutôt que d’un seuil.

Des valeurs ajustées hors de la plage possible. Pour un résultat binaire ajusté par régression linéaire, c’est immédiat.

lpm = smf.ols("completed ~ disability + case_category + age_band + sex"
              " + service_requested + admin1", data=referrals).fit()
print(f"fitted values from {lpm.fittedvalues.min():.3f}"
      f" to {lpm.fittedvalues.max():.3f}")
print(f"outside [0, 1]: {((lpm.fittedvalues < 0) | (lpm.fittedvalues > 1)).sum()}")
range(fitted(lm(completed ~ ., data = referrals)))

Huit des 1 581 probabilités ajustées tombent sous zéro, la plus basse à −0,060. Le modèle logistique sur les mêmes données reste entre 0,065 et 0,738. La décision : employez le logistique quand les prédictions comptent, et le modèle linéaire de probabilité quand seule la différence moyenne compte — le coefficient du modèle linéaire est directement une différence de risques, ce qui explique sa survie en économie.

Les résidus contre les valeurs ajustées. Cherchez une forme en éventail, qui signifie que la dispersion dépend du niveau.

import matplotlib.pyplot as plt
plt.scatter(model.fittedvalues, model.resid, s=6)
plot(model, which = 1)

La décision : l’hétéroscédasticité ne biaise pas le coefficient, elle biaise l’erreur-type — le remède est donc une erreur-type robuste, non un résultat transformé.

L’influence. Une poignée de lignes peut porter un coefficient.

influence = model.get_influence().cooks_distance[0]
print(f"rows with Cook's D > 4/n: {(influence > 4 / len(d)).sum()}")
sum(cooks.distance(model) > 4 / nobs(model))

La décision : regardez les lignes signalées avant de faire quoi que ce soit. Les onze ménages du cours EAH avec une erreur d’unité sont exactement le genre de ligne qui ressort ici, et la réponse est de corriger les données, non de sous-pondérer le point.

La linéarité d’un prédicteur continu. Ajustez-le par classes et voyez si les coefficients progressent régulièrement.

d["age_band"] = pd.cut(d["child_age_months"], [0, 12, 24, 36, 48, 60])
print(smf.ols("child_muac_mm ~ C(age_band)", data=d).fit().params.round(2))
lm(child_muac_mm ~ cut(child_age_months, c(0, 12, 24, 36, 48, 60)), data = d)

La décision : si les classes ne progressent pas régulièrement, le terme linéaire répond à la mauvaise question, et le découpage en classes est généralement une meilleure réponse qu’un polynôme, parce que les classes sont interprétables par ceux qui lisent le rapport.

Ce que le R² est et n’est pas

Le R² est la part de variance dont le modèle rend compte. Dans des données de programme il est couramment petit, et c’est un fait sur les gens, non sur l’analyste.

Ce n’est pas une mesure de la justesse d’un coefficient. Un essai randomisé avec un effet de traitement tranché peut avoir un R² de 0,02, parce que la variation individuelle noie une vraie différence moyenne. Juger une estimation causale par le R² est une erreur de catégorie.

C’est une mesure de la valeur des prédictions. C’est l’usage ci-dessus, et c’est l’usage honnête : la question du ciblage est une question de prédiction, et le R² y a répondu.

Le R² ajusté pénalise les termes ajoutés, et il est passé de 0,030 à 0,011 ici — l’écart entre les deux mesure combien des douze variables payaient leur place. Presque aucune.

Rapportez-le en entier

Predicting child MUAC from household characteristics

  Linear model, 641 children with complete data.
  R-squared 0.030, adjusted 0.011. Residual SD 15.95 mm against an outcome
  SD of 16.04 mm.

  Only food insecurity is distinguishable from zero: -4.70 mm (95% CI -7.45
  to -1.95). Household size, displacement status, water source, child sex
  and child age are not.

  Used as a targeting rule, screening the 20% of children the model ranks
  worst would find 31% of the children with MUAC below 125 mm, against 20%
  expected from screening 20% at random. Screening half the children would
  find 60%.

  Recommendation: do not target screening on household characteristics. The
  survey's 14.0% prevalence of MUAC below 125 mm is not concentrated in
  households that a registration form can identify, and blanket screening
  remains the only rule that reaches the caseload.

  This model is reported because it does not fit. A negative result about
  targeting is a budget decision, and dropping the model would have left the
  proposal to assume targeting works.

Le dernier paragraphe est la raison d’être de cette section. Un modèle qui s’ajuste mal est une preuve, et le tiroir où il finit d’ordinaire est l’endroit où l’hypothèse d’un programme survit sans être contestée.

La suite

C’est le cours. Huit leçons, une idée : un coefficient est une comparaison, et le travail consiste à dire laquelle, entre quelles unités, ajustée sur quoi, avec une erreur-type qui épouse la façon dont les données sont arrivées.

Le laboratoire met les quatre décisions dans une seule analyse. Puis Méthodes d’évaluation d’impact prend en charge la question que ce cours a différée dans le dernier paragraphe de chaque leçon — laquelle de ces comparaisons peut s’écrire comme une cause.

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.