Leçon 5 sur 8
Unité · Quelles covariables ont leur place
La covariable qui améliore chaque statistique et détruit la réponse
Ajoutez le fait qu'une orientation ait été émise et l'AIC chute de 595, le pseudo-R² quadruple, et 42,5 % de l'écart selon le handicap disparaît. Tout critère de sélection de modèle dit de la garder. Toute considération causale dit qu'elle doit sortir, et aucune statistique d'ajustement ne vous dira laquelle a raison.
Une covariable qui paraît manifestement juste
La filière d’orientation comporte une porte. Un cas est consenti, puis une
orientation est émise, puis elle est acceptée, puis un service est atteint.
referral_made est enregistré, il est fortement lié à l’aboutissement, et
l’ajouter au modèle est l’étape naturelle.
import statsmodels.formula.api as smf
BASE = ("completed ~ disability + case_category + age_band + sex"
" + service_requested + admin1")
adjusted = smf.logit(BASE, data=d).fit(disp=0)
plus_gate = smf.logit(BASE + " + referral_made", data=d).fit(disp=0)
for name, m in [("adjusted", adjusted), ("+ referral_made", plus_gate)]:
print(f"{name:16} AIC {m.aic:7.1f} pseudo-R2 {m.prsquared:.3f}")
adjusted <- glm(completed ~ disability + case_category + age_band + sex +
service_requested + admin1, data = d, family = binomial())
plus_gate <- update(adjusted, . ~ . + referral_made)
AIC(adjusted, plus_gate)
| Modèle | Rapport de cotes | Effet marginal moyen | AIC | Pseudo-R² |
|---|---|---|---|---|
| Brut | 0,430 | −19,05 pts | 2138,5 | 0,012 |
| Ajusté | 0,388 | −19,41 pts | 1999,6 | 0,089 |
+ referral_made |
0,494 | −11,15 pts | 1404,2 | 0,365 |
L’AIC s’améliore de 595 points. Le pseudo-R² quadruple. Et 42,5 % de l’effet s’évanouit.
Toute procédure automatique de sélection de modèle jamais écrite garderait cette variable. La sélection pas à pas la garde, l’AIC la garde, l’exactitude validée croisée la garde, et toutes répondent à une question que personne n’a posée.
Pourquoi elle retire l’effet
print(d.groupby("disability")["referral_made"].agg(["mean", "size"]).round(4))
d |> summarise(made = mean(referral_made), n = n(), .by = disability)
Une orientation est émise pour 71,5 % des cas sans handicap signalé et 53,8 % des cas avec.
Ce n’est pas une différence parasite à neutraliser — cela fait partie de ce qui est mesuré. Les cas signalant un handicap atteignent moins souvent un service en partie parce qu’une orientation est moins souvent émise pour eux au départ.
Conditionner sur referral_made demande : parmi les cas où une orientation a été
émise, reste-t-il un écart ? La réponse est oui, 11,2 points — un nombre réel et
utile sur l’étape d’acceptation. Ce n’est pas l’effet du handicap sur le fait
d’atteindre un service, et le rapporter comme tel sous-estime cet effet de 42 %.
Une covariable située sur le chemin causal entre exposition et résultat est un médiateur, et ajuster dessus retire exactement la part de l’effet qui passe par elle.
Quatre sortes de covariables, et ce que chacune fait
La décision porte sur la structure causale, non sur des statistiques, et elle doit être prise avant d’ajuster le modèle.
| Sorte | Se situe | Ajuster ? | Si vous vous trompez |
|---|---|---|---|
| Facteur de confusion | Cause l’exposition et le résultat | Oui | Estimation biaisée, dans les deux sens |
| Médiateur | Entre l’exposition et le résultat | Non (pour un effet total) | Effet sous-estimé |
| Collisionneur | Causé par l’exposition et le résultat | Jamais | Biais créé là où il n’y en avait pas |
| Cause concurrente | Ne cause que le résultat | Facultatif | Précision seulement |
Seule la première ligne est une raison d’ajouter une variable. La quatrième est une raison pour laquelle vous pouvez en ajouter une, et elle achète une erreur-type plus petite plutôt qu’une estimation différente. Les deux du milieu sont des raisons de ne pas le faire.
La sorte d’une variable n’est pas visible dans les données. Facteur de confusion, médiateur et collisionneur produisent tous un coefficient qui bouge quand on ajuste, et tous trois améliorent l’ajustement s’ils prédisent le résultat. Le seul moyen de les distinguer est de savoir ce qui est venu avant et ce qui a causé quoi — d’où le schéma tracé avant l’ajustement du modèle.
Le tracer avant d’ajuster
Trois flèches, tirées de ce que vous savez du fonctionnement de la filière.
disability -------------------------------> completion
| ^
+-------> referral made ---------------------+
department --> disability department --> completion
Le département est un facteur de confusion — le lieu où naît un cas influe à la fois sur qui est enregistré avec un handicap et sur la qualité du système de services — il a donc sa place dans le modèle. L’émission de l’orientation est un médiateur — le handicap l’influence et elle influence l’aboutissement — elle n’y a donc pas sa place.
TOTAL_EFFECT = ["disability", "case_category", "age_band", "sex",
"service_requested", "admin1"] # confounders only
MECHANISM = TOTAL_EFFECT + ["referral_made"] # a different question
# Two named model specifications, two questions, both legitimate.
Nommez les modèles d’après la question plutôt que d’après les variables. Un
modèle appelé MECHANISM ne sera pas rapporté par accident comme l’effet total, et
un relecteur voit lequel était visé.
Le collisionneur, qui est pire
Un médiateur sous-estime un effet réel. Un collisionneur en fabrique un qui n’existe pas, et le mécanisme est plus subtil.
Se restreindre aux cas clos est la façon la plus courante dont cela arrive ici, parce qu’un cas clos est un cas où quelque chose a été résolu — ce qui est en aval à la fois du handicap et de l’aboutissement.
closed = d[d["case_status"].isin(["closed-resolved", "closed-lost-contact"])]
print(f"closed cases: {len(closed)}")
print(closed.groupby("disability")["completed"].agg(["mean", "size"]).round(4))
d |> filter(case_status %in% c("closed-resolved", "closed-lost-contact")) |>
summarise(rate = mean(completed), n = n(), .by = disability)
| Échantillon | n | Écart (effet marginal moyen) |
|---|---|---|
| Tous les cas consentis | 1 581 | −19,4 points |
| Cas clos seulement | 860 | −21,1 points |
Se restreindre aux cas clos porte l’écart à 21,1 points, et le mouvement est produit par la restriction plutôt que par quoi que ce soit concernant le handicap. Les cas ouverts — ceux encore en cours — sont exclus sur un critère que les deux variables influencent.
Sélectionner des lignes, c’est ajuster sur une variable. Écarter les cas ouverts, ne garder que les formulaires complets, n’analyser que les ménages ayant répondu à tout : chacun est un conditionnement, et chacun peut être un collisionneur. « Nous avons restreint l’analyse aux cas clos par souci d’exhaustivité » est une phrase qui change une estimation sans que personne remarque qu’il s’agissait d’un choix de modélisation.
Rapportez les deux, et dites lequel est lequel
La médiation vaut d’être rapportée quand le mécanisme est la question du programme, ce qui est le cas ici : le cours de protection situait l’écart selon le handicap à l’émission et à l’acceptation, et cette décomposition en est la version chiffrée.
Referral completion by disability status, decomposition
Total gap -19.4 points
of which runs through referral-making -8.3 points (42.5%)
remaining, among referrals made -11.2 points
Referrals are made for 53.8% of cases reporting a disability against 71.5%
of others. Both gates contribute; neither explains the other away.
The -11.2 figure is conditional on a referral having been made and must not
be reported as the effect of disability on reaching a service.
La dernière ligne est celle qui garde la décomposition honnête. Les deux nombres sont réels, ils répondent à des questions différentes, et le mode d’échec n’est pas de calculer le mauvais — c’est de calculer le bon et de l’étiqueter comme l’autre.
La suite
Chaque modèle de ce cours a jusqu’ici supposé que chaque ligne était une observation indépendante. La leçon suivante donne au modèle un terme pour ce à l’intérieur de quoi les lignes sont regroupées, et trouve trois chemins honnêtes vers la même réponse là où le naïf était seul de son côté.