Retour à la leçon·Leçon 2 sur 8·Le dénominateur, c'est l'épidémiologie
Des dénominateurs enchaînés
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.
Ce que couvre cette leçon
- La forme
- Deux façons d'exprimer chaque étape
- Le premier dénominateur est le difficile
- La cascade vaccinale
- Surveillez le sens de l'abandon
- Dessinez-la, mais rapportez le tableau
- La suite
Notes du présentateur
Une cascade est une suite où le dénominateur de chaque étape est le numérateur de la précédente. 1 850 cas de protection deviennent 757 atteignant un service, et le nombre utile n'est pas les 41 % — c'est le maillon qui a le plus perdu.La forme — Exemple
people living with HIV -> diagnosed -> on treatment -> virally suppressedNotes du présentateur
La cascade de traitement du VIH est l'exemple le plus connu et la structure est générale. Chaque flèche est une proportion, et le dénominateur de chaque étape est l'étape précédente. C'est ce qui en fait une cascade plutôt que quatre indicateurs séparés, et ce qui rend l'arithmétique digne d'attention. La cascade de soins de la tuberculose a la même forme — cas incidents estimés, notifiés, mis sous traitement, traités avec succès — et c'est aussi celle de tout circuit de référencement, de tout calendrier vaccinal, et de tout programme dont on peut sortir entre deux étapes.Deux façons d'exprimer chaque étape — En Python (suite)
import pandas as pd referrals = pd.read_csv("protection-referrals-2024.v1.csv") steps = [ ("cases", len(referrals)), ("consented", (referrals["consent_to_refer"] == True).sum()), ("referral made", ((referrals["consent_to_refer"] == True) & (referrals["referral_made"] == True)).sum()), ("reached a service", ((referrals["consent_to_refer"] == True) & (referrals["referral_made"] == True) & (referrals["referral_accepted"] == True)).sum()), ] first = steps[0][1] previous = NoneDeux façons d'exprimer chaque étape — En Python (suite)
for name, count in steps: line = f"{name:20} {count:5} {count / first:6.1%} of all" if previous: line += f" {count / previous:6.1%} of previous" print(line) previous = countDeux façons d'exprimer chaque étape — En R
library(dplyr) referrals |> summarise( cases = n(), consented = sum(consent_to_refer), referred = sum(consent_to_refer & referral_made), reached = sum(consent_to_refer & referral_made & referral_accepted) )Deux façons d'exprimer chaque étape
Étape n Sur le total Sur la précédente Cas 1 850 100 % — Ont consenti au référencement 1 638 88,5 % 88,5 % Référencement émis 1 142 61,7 % 69,7 % Ont atteint un service 757 40,9 % 66,3 % Deux façons d'exprimer chaque étape
- Les deux colonnes sont nécessaires et elles disent des choses différentes
- Classez par perte conditionnelle, agissez sur la plus grande
Notes du présentateur
Les deux colonnes sont nécessaires et elles disent des choses différentes. La colonne sur le total est la cascade telle qu'on la dessine d'ordinaire — un escalier descendant de 100 % à 41 %. Elle dit à un bailleur quelle part de la charge de cas aboutit. La colonne sur la précédente est celle qui identifie le problème. La plus grosse perte unique se situe à « référencement émis » : 30,3 % des personnes ayant consenti n'ont jamais vu de référencement émis. C'est une étape sous le contrôle de l'organisation, et elle est invisible dans la première colonne, où la chute de 88,5 % à 61,7 % ressemble à celle de 61,7 % à 40,9 %. Classez par perte conditionnelle, agissez sur la plus grande.Deux façons d'exprimer chaque étape — En Python
losses = pd.DataFrame(steps, columns=["step", "n"]) losses["lost"] = losses["n"].shift(1) - losses["n"] losses["conditional_loss"] = losses["lost"] / losses["n"].shift(1) print(losses.dropna().sort_values("conditional_loss", ascending=False))Deux façons d'exprimer chaque étape — En R
tibble::tibble(step = c("consented", "referred", "reached"), n = c(1638, 1142, 757), previous = c(1850, 1638, 1142)) |> mutate(conditional_loss = (previous - n) / previous) |> arrange(desc(conditional_loss))Le premier dénominateur est le difficile
- VIH — les personnes vivant avec le VIH. Personne ne les compte ; le chiffre vient d'un modèle, et tout « %…
- Tuberculose — les cas incidents estimés. De même, et l'écart entre estimés et notifiés est le constat phare de la…
- Protection — les personnes ayant subi un incident. Inconnaissable, et la raison pour laquelle la cascade de…
Notes du présentateur
Toute cascade a une étape qui ne se compte pas, seulement s'estime, et c'est toujours la première.Le premier dénominateur est le difficile — En Python
print("cascade base: cases known to the system, not people in need")Le premier dénominateur est le difficile — En R
# The base of this cascade is cases the system saw. It is not incidence.Le premier dénominateur est le difficile
- Dites quelle base vous avez employée — Une cascade partant d'un besoin estimé et une partant des cas déjà dans le…
Notes du présentateur
Dites quelle base vous avez employée. Une cascade partant d'un besoin estimé et une partant des cas déjà dans le système se ressemblent et veulent dire des choses complètement différentes — la première mesure si le système atteint les gens, la seconde seulement s'il les traite.La cascade vaccinale — En Python
vax = pd.read_csv("vaccination-coverage-2024.v1.csv") reported = vax[vax["report_submitted"] == True] doses = reported.groupby("antigen")["doses_administered"].sum() for first_dose, last_dose in [("penta1", "penta3"), ("mcv1", "mcv2")]: dropout = (doses[first_dose] - doses[last_dose]) / doses[first_dose] print(f"{first_dose} -> {last_dose}: {doses[first_dose]:,} -> " f"{doses[last_dose]:,}, dropout {dropout:.1%}")Notes du présentateur
L'extraction vaccinale en porte une, et elle n'exige aucun dénominateur modélisé puisque chaque étape est comptée.La cascade vaccinale — En R
doses <- vax |> filter(report_submitted) |> summarise(doses = sum(doses_administered), .by = antigen)La cascade vaccinale
- Penta1 vers penta3 : 13,8 % d'abandon. Première vers seconde dose de rougeole : 22,9 %
- C'est robuste au dénominateur — Numérateur et dénominateur viennent des mêmes formations aux mêmes mois, si bien qu'une…
- Cela mesure le mécanisme — La couverture monte si davantage d'enfants commencent ; l'abandon ne baisse que si davantage…
Notes du présentateur
Penta1 vers penta3 : 13,8 % d'abandon. Première vers seconde dose de rougeole : 22,9 %. Deux choses que cela rend possible et qu'un taux de couverture ne permet pas. C'est robuste au dénominateur. Numérateur et dénominateur viennent des mêmes formations aux mêmes mois, si bien qu'une projection de recensement vieille de neuf ans ne peut pas le déplacer. Le cours sur la conception d'indicateurs avançait cet argument ; ici c'est la raison pour laquelle l'abandon est souvent le meilleur indicateur à rapporter. Cela mesure le mécanisme. La couverture monte si davantage d'enfants commencent ; l'abandon ne baisse que si davantage d'enfants qui commencent terminent aussi, ce que change réellement une intervention de rappel ou de recherche des perdus de vue.Surveillez le sens de l'abandon — En Python
if doses["penta3"] > doses["penta1"]: print("negative dropout: check the denominator and the period")Surveillez le sens de l'abandon — En R
if (doses$doses[doses$antigen == "penta3"] > doses$doses[doses$antigen == "penta1"]) warning("negative dropout")Notes du présentateur
Un abandon négatif — plus de troisièmes doses que de premières — est arithmétiquement possible et signifie toujours quelque chose de précis : une campagne de rattrapage, un problème de bornes de période, ou des enfants vaccinés ailleurs pour la dose antérieure. Ce n'est pas une erreur à ramener à zéro, c'est un constat à expliquer.Dessinez-la, mais rapportez le tableau — En Python
cascade = pd.DataFrame({ "step": ["Cases", "Consented", "Referral made", "Reached service"], "n": [1850, 1638, 1142, 757], }) cascade["of_all"] = cascade["n"] / cascade["n"].iloc[0] cascade["of_previous"] = cascade["n"] / cascade["n"].shift(1) cascade["base"] = "cases known to the system"Notes du présentateur
Un graphique en cascade est l'une des rares visualisations par défaut réellement bonnes de ce secteur — les barres descendantes rendent les pertes immédiates. Mais le graphique ne montre que la colonne sur le total, alors publiez le tableau à côté avec les deux.Dessinez-la, mais rapportez le tableau — En R
tibble::tribble( ~step, ~n, "Cases", 1850, "Consented", 1638, "Referral made", 1142, "Reached", 757 ) |> mutate(of_all = n / first(n), of_previous = n / lag(n))Notes du présentateur
Quatre colonnes, et la dernière — la base — est ce qui empêche un lecteur de comparer votre cascade à celle de quelqu'un d'autre partie d'ailleurs.La suite
- Une cascade est un ensemble de décomptes déjà agrégés.
Notes du présentateur
Une cascade est un ensemble de décomptes déjà agrégés. L'unité suivante revient aux enregistrements individuels — une liste linéaire d'épidémie, où l'analyse commence par mettre 975 cas dans l'ordre du temps et demander quelle forme ils dessinent.