cassionAnalyse de données

Leçon 7 sur 8

Unité · Ce que la comparaison peut affirmer

Qu'est-ce qui pourrait aussi l'expliquer

Un facteur de confusion cause le résultat et diffère entre les groupes. Quatre candidats séparent les districts de cette épidémie — l'un a été retiré, l'un n'est pas mesuré, et l'un n'est pas un facteur de confusion du tout : c'est le mécanisme.

PythonR135 minDéfinitions d'indicateurs de l'UNICEFCritères d'évaluation du CAD de l'OCDE

La définition, et pourquoi il vaut la peine d’être strict

Un facteur de confusion est une variable qui satisfait trois conditions à la fois :

  • elle est associée à l’exposition — elle diffère entre les groupes comparés ;
  • elle est une cause du résultat, indépendamment de l’exposition ;
  • elle n’est pas sur le chemin causal entre l’exposition et le résultat.

Les trois comptent. Une variable qui diffère entre groupes sans causer le résultat est sans objet. Une variable qui cause le résultat mais est identique dans les deux groupes ne peut pas expliquer un écart. Et une variable sur le chemin causal n’est pas un facteur de confusion — c’est le mécanisme, et ajuster dessus détruit le constat.

Les quatre candidats de cette épidémie

Nord a un taux d’attaque standardisé de 7,25 pour 1 000 contre 5,95 pour Sud, et une létalité de 6,30 % contre 3,11 %. Qu’est-ce qui pourrait aussi expliquer ces écarts ?

Candidat Diffère entre districts ? Cause le résultat ? Sur le chemin ?
Structure par âge Oui, nettement Oui Non — facteur de confusion, déjà retiré
Source d’eau et densité Presque certainement Oui Non — facteur de confusion, non mesuré
Distance au traitement Oui Oui, pour la létalité Oui — c’est le mécanisme
Qualité du registre Oui Non Non — pas un facteur de confusion, un biais

Parcourez ce tableau et chaque ligne appelle une réponse différente.

La structure par âge a été traitée. La leçon 6 l’a retirée et a chiffré ce qu’elle valait — environ la moitié de l’écart brut.

La source d’eau, l’assainissement et la promiscuité sont les causes réelles de la transmission du choléra, elles diffèrent certainement entre un district de type camp et un district rural, et elles ne sont pas dans ce jeu de données. C’est la phrase la plus importante de cette leçon. Un facteur de confusion non mesuré ne peut pas être ajusté, et son existence doit être énoncée plutôt qu’ignorée.

print("Available for adjustment: age, sex, district")
print("Known to matter and unavailable: water source, sanitation, crowding, "
      "displacement status")
# The list of what you could not adjust for belongs in the limitations section.

La distance au traitement est l’intéressante et n’est pas du tout un facteur de confusion. La chaîne est : Nord est plus loin des centres de traitement → ses cas arrivent plus tard → davantage meurent. La distance cause la létalité à travers le délai, donc le délai est sur le chemin causal. Ajuster sur le délai supprimerait précisément l’effet que vous cherchez à démontrer, ce qui est l’erreur classique de sur-ajustement.

La qualité du registre n’est pas non plus un facteur de confusion. Les dates de début rétro-remplies de Nord ne causent pas de décès ; elles faussent la mesure de l’explication. C’est un biais d’information, et il se corrige en réparant le registre, non en ajustant.

Stratifiez pour le voir

L’ajustement le plus simple, et celui qui montre son travail.

import pandas as pd

cases = pd.read_csv("cholera-line-list-2024.v1.csv")
with_outcome = cases[cases["outcome"].notna()]

stratified = (
    with_outcome.assign(died=with_outcome["outcome"] == "died")
    .groupby(["district", "age_band"])
    .agg(cases=("died", "size"), deaths=("died", "sum"))
)
stratified["cfr"] = stratified["deaths"] / stratified["cases"]
print((stratified["cfr"].unstack() * 100).round(1))
library(dplyr)

cases |>
  filter(!is.na(outcome)) |>
  summarise(cases = n(), cfr = mean(outcome == "died"), .by = c(district, age_band)) |>
  tidyr::pivot_wider(id_cols = age_band, names_from = district, values_from = cfr)

Deux choses se lisent sur un tableau stratifié, et une seule est l’estimation ajustée.

L’écart persiste-t-il à l’intérieur des strates ? Si la létalité de Nord est plus élevée dans chaque tranche d’âge, l’âge n’est pas l’explication. Si elle s’inverse dans certaines tranches, il se passe quelque chose de plus intéressant.

Les strates sont-elles cohérentes ? Un écart grand dans une tranche et absent des autres est une modification d’effet — l’exposition agit réellement différemment selon les groupes — et il doit être rapporté par strate plutôt que moyenné en un seul chiffre ajusté.

La modification d’effet est un constat ; la confusion est une nuisance. Réduire la première à un nombre unique détruit le résultat ; ne pas retirer la seconde en fabrique un.

Quand la stratification s’épuise

Deux variables et les cellules se vident vite — la leçon sur la désagrégation du module 3, arrivant avec une autre conséquence. Trois districts par quatre tranches d’âge par deux sexes font vingt-quatre cellules sur 974 issues, et les décès par choléra sont rares.

cells = with_outcome.groupby(["district", "age_band", "sex"]).size()
print(f"{len(cells)} cells, smallest {cells.min()}, {(cells < 30).sum()} below 30")
cases |> filter(!is.na(outcome)) |> count(district, age_band, sex) |>
  summarise(cells = n(), smallest = min(n), under_30 = sum(n < 30))

C’est là que la régression prend le relais, et Régression appliquée aux données de programme, plus loin dans le programme, porte exactement là-dessus — ajuster sur plusieurs variables à la fois sans épuiser les cellules. Son objet est le même que celui de la stratification, et un modèle qui ajuste sur un mécanisme commet la même erreur qu’une stratification qui le fait.

Les trois questions à poser à toute comparaison

Avant d’attribuer un écart à quoi que ce soit.

1. Qu’est-ce qui diffère entre ces groupes en dehors de ce que j’étudie ? Listez-le. La liste est la section des limites, et ce que vous ne pouvez pas mesurer y figure aussi.

2. Lesquels causent le résultat ? Ceux-là seuls sont des facteurs de confusion. Un district ayant davantage d’écoles ne confond pas une comparaison sur le choléra à moins que les écoles ne causent le choléra.

3. Lesquels sont sur le chemin causal ? N’ajustez pas dessus. Le délai d’accès au traitement, dans cette épidémie, est la façon dont la distance tue.

adjustment_plan = pd.DataFrame({
    "variable": ["age", "sex", "water source", "delay to treatment", "register quality"],
    "differs": [True, False, True, True, True],
    "causes_outcome": [True, True, True, True, False],
    "on_causal_path": [False, False, False, True, False],
    "action": ["adjust", "no need", "unmeasured; state it", "do not adjust",
               "fix the register"],
})
print(adjustment_plan)
tibble::tribble(
  ~variable,        ~action,
  "age",            "adjust",
  "water source",   "unmeasured; state it",
  "delay",          "do not adjust; it is the mechanism",
  "register",       "fix it; this is bias, not confounding"
)

Écrivez ce tableau avant l’analyse, non après. Décider sur quoi ajuster une fois qu’on a vu quel ajustement donne la réponse la plus agréable est ce qui rend l’épidémiologie observationnelle peu digne de confiance, et c’est indiscernable d’un travail honnête après coup.

La suite

Vous avez nommé ce qui pourrait aussi expliquer un écart et retiré ce que vous pouviez. La dernière leçon porte sur ce qui reste dicible — la phrase à laquelle une comparaison observationnelle a droit, et les plusieurs auxquelles elle n’a pas droit.

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.