Cette analyse a pour objectif principal d’estimer l’effet du traitement maternel par AZT, comparativement au placebo, sur la transmission du VIH à l’enfant.
Les participants apprendront à :
Question principale : l’administration de l’AZT à la mère réduit-elle le risque d’infection VIH de l’enfant par rapport au placebo ?
Au milieu des années 1990, la transmission mère-enfant du VIH constituait une cause importante d’infection pédiatrique en Afrique subsaharienne. La zidovudine, ou AZT, avait déjà montré une efficacité élevée dans des contextes où l’allaitement maternel était peu fréquent, mais les schémas thérapeutiques longs et coûteux étaient difficilement applicables dans de nombreux systèmes de santé africains. L’essai DITRAME ANRS 049a a donc évalué un schéma court de zidovudine administré à la mère dans deux villes d’Afrique de l’Ouest : Abidjan, en Côte d’Ivoire, et Bobo-Dioulasso, au Burkina Faso.
L’essai original était multicentrique, randomisé, en double aveugle et contrôlé par placebo. Le recrutement ne correspondait pas à un tirage aléatoire dans la population générale. Les femmes enceintes fréquentant les consultations prénatales sélectionnées étaient systématiquement informées et se voyaient proposer un conseil prétest et un dépistage du VIH lorsqu’elles avaient au moins 18 ans, se présentaient avant 32 semaines de grossesse, résidaient dans la ville et prévoyaient d’accoucher dans une structure participante. Les femmes ayant une infection VIH-1 confirmée, ayant donné leur consentement écrit et satisfaisant aux critères biologiques étaient ensuite incluses entre 36 et 38 semaines de grossesse.
Les principales causes d’exclusion étaient une anémie sévère, une neutropénie importante, une fonction hépatique anormale ou une drépanocytose de type SS, SC ou CC. La sélection des participantes reposait donc sur l’éligibilité clinique et le consentement, tandis que la randomisation concernait uniquement l’attribution du traitement.
La liste de randomisation était préparée par un statisticien indépendant. Une randomisation par blocs de dix, stratifiée selon le centre, était utilisée. Les traitements étaient conditionnés dans des emballages scellés, numérotés séquentiellement et préparés par une pharmacie centrale indépendante, ce qui permettait de maintenir l’aveugle des participantes et des équipes.
Selon la phase de l’essai, le schéma maternel correspondait à 250 ou 300 mg de zidovudine deux fois par jour avant l’accouchement, une dose de charge de 500 ou 600 mg au début du travail, puis 250 ou 300 mg deux fois par jour pendant sept jours après l’accouchement. Le groupe témoin recevait un placebo d’apparence identique. Aucun traitement antirétroviral n’était administré au nouveau-né dans ce protocole.
Le critère principal était l’infection VIH-1 de l’enfant, déterminée par des tests PCR séquentiels, notamment entre les jours 1 et 8, puis aux jours 45, 90 et 180. Le premier test positif servait à approcher le moment du diagnostic. Les analyses principales étaient conduites selon le principe de l’intention de traiter, c’est-à-dire selon le groupe attribué par la randomisation, indépendamment de l’observance réelle. Les probabilités d’infection étaient estimées par la méthode de Kaplan-Meier, les courbes comparées par le test du log-rank et les analyses multivariées temporelles réalisées par modèle de Cox. Un seul enfant était retenu par grossesse multiple afin de préserver l’indépendance des observations.
La base pédagogique TME_Africa utilisée ici contient
401 couples mère-enfant et ne représente qu’un extrait
simplifié des données de DITRAME. Le script conserve les variables
disponibles et reproduit une démarche pédagogique proche des
publications : description des groupes, estimation du RR, comparaison
avec l’OR, analyses stratifiées, RR ajustés, Kaplan-Meier et modèles de
Cox. Il ne constitue toutefois pas une reproduction exacte des analyses
publiées. En particulier, les publications prolongées ont utilisé des
méthodes adaptées aux temps d’infection connus par intervalle et, dans
certaines analyses, aux risques concurrents. Le seuil de CD4 de 350
cellules/mm³ retenu dans ce script est conservé pour rester fidèle au
code pédagogique ; l’analyse publiée à 24 mois a principalement présenté
des résultats selon le seuil de 500 cellules/mm³.
L’objectif principal est d’estimer l’efficacité du traitement maternel par AZT sur la transmission du VIH à l’enfant. Les objectifs secondaires sont de :
Références méthodologiques principales
Le script utilise directement les packages nécessaires. Installez ceux qui manquent avant de compiler le document.
library(tidyverse)
library(readxl)
library(lubridate)
library(questionr)
library(naniar)
library(gtsummary)
library(gt)
library(epiR)
library(epitools)
library(broom)
library(survival)
library(survminer)
library(scales)
library(sandwich)
library(lmtest)
library(GGally)
tme_raw <- read_excel("TME_Africa.xls")
# Dimensions de la base
nrow(tme_raw)
## [1] 401
ncol(tme_raw)
## [1] 13
# Noms des variables
names(tme_raw)
## [1] "ID" "TTTGRP" "AGEINC" "CD4VAL"
## [5] "NIVINSTRUC" "PARITY" "HIVSTATUS" "DATINF"
## [9] "DATBIRTH" "DTH_CH" "DATE_DTH" "DATE_LAST_BIO"
## [13] "SITE"
# Premières observations
tme_raw |> head()
## # A tibble: 6 × 13
## ID TTTGRP AGEINC CD4VAL NIVINSTRUC PARITY HIVSTATUS DATINF
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dttm>
## 1 B0141 0 28 518 0 1 1 1996-01-07 00:00:00
## 2 A0051 0 21 638 0 1 1 1996-01-29 00:00:00
## 3 B0231 0 27 14 1 1 1 1996-02-17 00:00:00
## 4 A0241 1 21 412 0 0 1 1996-04-02 00:00:00
## 5 B0191 1 30 283 0 5 1 1996-04-18 00:00:00
## 6 B0341 0 37 1817 1 4 1 1996-04-24 00:00:00
## # ℹ 5 more variables: DATBIRTH <dttm>, DTH_CH <dbl>, DATE_DTH <dttm>,
## # DATE_LAST_BIO <dttm>, SITE <chr>
| Variable | Signification |
|---|---|
ID |
Identifiant de la mère |
SITE |
Site de suivi : Abidjan ou Bobo-Dioulasso |
TTTGRP |
Groupe maternel : placebo ou AZT |
AGEINC |
Âge maternel à l’inclusion |
CD4VAL |
Nombre de CD4 maternels à l’inclusion |
NIVINSTRUC |
Nombre d’années d’instruction |
PARITY |
Nombre d’enfants nés vivants |
HIVSTATUS |
Statut VIH de l’enfant |
DATINF |
Date du diagnostic de l’infection |
DATBIRTH |
Date de naissance de l’enfant |
DTH_CH |
Décès de l’enfant |
DATE_DTH |
Date du décès |
DATE_LAST_BIO |
Date du dernier suivi biologique |
Les variables de base sont recodées sous des intitulés directement
interprétables. Le statut VIH codé 9 est considéré comme
indéterminé et non comme « non infecté ».
tme <- tme_raw |>
mutate(
traitement = recode_factor(
TTTGRP,
`0` = "Placebo",
`1` = "AZT"
),
site_suivi = recode_factor(
SITE,
CI = "Abidjan, Côte d'Ivoire",
BF = "Bobo-Dioulasso, Burkina Faso"
),
statut_vih = recode_factor(
HIVSTATUS,
`0` = "Non infecté",
`1` = "Infecté",
`9` = "Indéterminé"
),
statut_deces = recode_factor(
DTH_CH,
`0` = "Vivant",
`1` = "Décédé"
),
# Variable binaire pour les analyses : 1 = infecté, 0 = non infecté,
# NA = statut indéterminé
infection = case_when(
HIVSTATUS == 1 ~ 1,
HIVSTATUS == 0 ~ 0,
TRUE ~ NA_real_
),
deces = as.numeric(DTH_CH),
niveau_instruction = case_when(
NIVINSTRUC == 0 ~ "Aucune instruction",
between(NIVINSTRUC, 1, 6) ~ "Primaire",
between(NIVINSTRUC, 7, 12) ~ "Secondaire",
TRUE ~ NA_character_
) |>
factor(levels = c(
"Aucune instruction", "Primaire", "Secondaire")),
age_groupe = case_when(
AGEINC >= 25 ~ "≥ 25 ans",
AGEINC < 25 ~ "< 25 ans"
) |>
factor(levels = c("≥ 25 ans", "< 25 ans")),
cd4_groupe = case_when(
CD4VAL >= 350 ~ "≥ 350 cellules/mm³",
CD4VAL < 350 ~ "< 350 cellules/mm³"
) |>
factor(levels = c("≥ 350 cellules/mm³", "< 350 cellules/mm³")),
instruction_groupe = case_when(
NIVINSTRUC >= 7 ~ "Secondaire ou supérieur",
NIVINSTRUC < 7 ~ "Aucune ou primaire"
) |>
factor(levels = c("Secondaire ou supérieur", "Aucune ou primaire")),
parite_groupe = case_when(
PARITY < 1 ~ "Nullipare",
PARITY == 1 ~ "Primipare",
PARITY >= 1 & PARITY <=4 ~ "Paucipare",
PARITY > 4 ~ "Multipare"
) |>
factor(levels = c("Nullipare", "Primipare","Paucipare","Multipare")),
# Les dates de la base sont au format année/mois/jour
DATINF = ymd(DATINF),
DATBIRTH = ymd(DATBIRTH),
DATE_DTH = ymd(DATE_DTH),
DATE_LAST_BIO = ymd(DATE_LAST_BIO)
)
# Vérification des nouveaux codages
freq(tme$traitement, total = TRUE)
## n % val%
## Placebo 201 50,1 50,1
## AZT 200 49,9 49,9
## Total 401 100,0 100,0
freq(tme$statut_vih, total = TRUE)
## n % val%
## Non infecté 291 72,6 72,6
## Infecté 100 24,9 24,9
## Indéterminé 10 2,5 2,5
## Total 401 100,0 100,0
freq(tme$site_suivi, total = TRUE)
## n % val%
## Abidjan, Côte d'Ivoire 236 58,9 58,9
## Bobo-Dioulasso, Burkina Faso 165 41,1 41,1
## Total 401 100,0 100,0
La base pédagogique comprend 401 observations, dont 200 dans le groupe AZT et 201 dans le groupe placebo. Le statut VIH est connu pour 391 enfants : 100 infectés et 291 non infectés. 10 statuts sont indéterminés. Le CD4 maternel à l’inclusion est manquant pour 8 participantes, et 89 décès d’enfants sont enregistrés.
Aide à l’interprétation :
infection = 1signifie que l’enfant est infecté ;infection = 0signifie qu’il est non infecté. Les enfants au statut indéterminé ont une valeur manquante pour cette variable analytique.
tme |>
count(ID) |>
filter(n > 1)
## # A tibble: 0 × 2
## # ℹ 2 variables: ID <chr>, n <int>
Une sortie vide indique que chaque identifiant apparaît une seule fois.
miss_var_summary(tme) |>
gt() |>
cols_label(
variable = "Variable",
n_miss = "Valeurs manquantes",
pct_miss = "Pourcentage manquant"
) |>
fmt_number(columns = pct_miss, decimals = 1) |>
tab_header(title = "Répartition des données manquantes")
| Répartition des données manquantes | ||
| Variable | Valeurs manquantes | Pourcentage manquant |
|---|---|---|
| DATE_DTH | 312 | 77.8 |
| DATINF | 301 | 75.1 |
| DATE_LAST_BIO | 10 | 2.49 |
| infection | 10 | 2.49 |
| CD4VAL | 8 | 2.00 |
| cd4_groupe | 8 | 2.00 |
| ID | 0 | 0 |
| TTTGRP | 0 | 0 |
| AGEINC | 0 | 0 |
| NIVINSTRUC | 0 | 0 |
| PARITY | 0 | 0 |
| HIVSTATUS | 0 | 0 |
| DATBIRTH | 0 | 0 |
| DTH_CH | 0 | 0 |
| SITE | 0 | 0 |
| traitement | 0 | 0 |
| site_suivi | 0 | 0 |
| statut_vih | 0 | 0 |
| statut_deces | 0 | 0 |
| deces | 0 | 0 |
| niveau_instruction | 0 | 0 |
| age_groupe | 0 | 0 |
| instruction_groupe | 0 | 0 |
| parite_groupe | 0 | 0 |
gg_miss_var(tme, show_pct = TRUE) +
labs(
title = "Données manquantes par variable",
x = NULL,
y = "Nombre de valeurs manquantes"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank()
)
tme |>
transmute(
ID,
infection_avant_naissance = !is.na(DATINF) & DATINF < DATBIRTH,
deces_avant_naissance = !is.na(DATE_DTH) & DATE_DTH < DATBIRTH,
suivi_avant_naissance = !is.na(DATE_LAST_BIO) & DATE_LAST_BIO < DATBIRTH
) |>
summarise(
infection_avant_naissance = sum(infection_avant_naissance),
deces_avant_naissance = sum(deces_avant_naissance),
suivi_avant_naissance = sum(suivi_avant_naissance)
) |>
gt() |>
tab_header(title = "Contrôle de cohérence chronologique")
| Contrôle de cohérence chronologique | ||
| infection_avant_naissance | deces_avant_naissance | suivi_avant_naissance |
|---|---|---|
| 0 | 0 | 0 |
Les éventuelles incohérences doivent être examinées à partir du protocole ou du dictionnaire original. Elles ne doivent pas être corrigées automatiquement sans justification.
Les variables qualitatives sont présentées par leurs effectifs et pourcentages. Les variables quantitatives sont présentées dans une cellule unique par moyenne ± écart-type ou médiane [Q1–Q3].
tableau_descriptif <- tme |>
select(
site_suivi,
traitement,
statut_vih,
statut_deces,
AGEINC,
CD4VAL,
niveau_instruction,
PARITY
) |>
tbl_summary(
label = list(
site_suivi ~ "Site de suivi",
traitement ~ "Groupe de traitement maternel",
statut_vih ~ "Statut VIH de l'enfant",
statut_deces ~ "Décès de l'enfant",
AGEINC ~ "Âge maternel à l'inclusion, années",
CD4VAL ~ "CD4 maternel, cellules/mm³",
niveau_instruction ~ "Niveau d'instruction",
PARITY ~ "Parité, enfants nés vivants"
),
statistic = list(
all_categorical() ~ "{n}|{p}",
AGEINC ~ "{mean} ± {sd}|",
CD4VAL ~ "{median} [{p25}–{p75}]|",
PARITY ~ "{median} [{p25}–{p75}]|"
),
digits = list(
all_categorical() ~ c(0, 1),
AGEINC ~ 1,
CD4VAL ~ 0,
PARITY ~ 0
),
missing = "ifany",
missing_text = "Données manquantes"
) |>
modify_table_body(
~ .x |>
separate_wider_delim(
stat_0,
delim = "|",
names = c("frequence_absolue", "frequence_relative"),
too_few = "align_start"
) |>
mutate(
frequence_relative = case_when(
row_type == "level" & frequence_relative != "" ~
frequence_relative,
TRUE ~ frequence_relative
)
)
) |>
modify_header(
label ~ "**Variables et modalités**",
frequence_absolue ~ "**Fréquence absolue/statistique**",
frequence_relative ~ "**Fréquence relative (%)**"
) |>
modify_column_alignment(
columns = label,
align = "left"
) |>
modify_column_alignment(
columns = c(frequence_absolue, frequence_relative),
align = "center"
) |>
bold_labels() |>
modify_caption(
"**Tableau II. Caractéristiques des couples mère-enfant inclus dans l'étude**"
)
tableau_descriptif
| Variables et modalités | Fréquence absolue/statistique | Fréquence relative (%) |
|---|---|---|
| Site de suivi | ||
| Abidjan, Côte d'Ivoire | 236 | 58,9 |
| Bobo-Dioulasso, Burkina Faso | 165 | 41,1 |
| Groupe de traitement maternel | ||
| Placebo | 201 | 50,1 |
| AZT | 200 | 49,9 |
| Statut VIH de l'enfant | ||
| Non infecté | 291 | 72,6 |
| Infecté | 100 | 24,9 |
| Indéterminé | 10 | 2,5 |
| Décès de l'enfant | ||
| Vivant | 312 | 77,8 |
| Décédé | 89 | 22,2 |
| Âge maternel à l'inclusion, années | 25,6 ± 5,4 | |
| CD4 maternel, cellules/mm³ | 541 [359–741] | |
| Données manquantes | 8 | |
| Niveau d'instruction | ||
| Aucune instruction | 193 | 48,1 |
| Primaire | 188 | 46,9 |
| Secondaire | 20 | 5,0 |
| Parité, enfants nés vivants | 1 [1–3] |
Ici, nous présentons les pourccentages par colonne parceque la variable de croisement est le status vis-à-vis du traitement, qui était connu depuis l’inclusion.
tme |>
select(
traitement,
site_suivi,
AGEINC,
CD4VAL,
niveau_instruction,
PARITY
) |>
tbl_summary(
by = traitement,
label = list(
site_suivi ~ "Site de suivi",
AGEINC ~ "Âge maternel, années",
CD4VAL ~ "CD4 maternel, cellules/mm³",
niveau_instruction ~ "Niveau d'instruction",
PARITY ~ "Parité"
),
statistic = list(
AGEINC ~ "{mean} ({sd})",
CD4VAL ~ "{median} [{p25}–{p75}]",
PARITY ~ "{median} [{p25}–{p75}]",
all_categorical() ~ "{n} ({p} %)"
),
missing = "ifany",
missing_text = "Données manquantes"
) |>
add_overall(last = TRUE) |>
add_p() |>
modify_header(
label ~ "**Caractéristiques initiales**",
stat_0 ~ "**{level}**
n = {n}",
stat_1 ~ "**{level}**
n~0~ = {n}",
stat_2 ~ "**{level}**
n~1~ = {n}",
p.value ~ "**p**"
) |>
bold_labels() |>
modify_caption(
"**Tableau II. Comparabilité initiale des groupes AZT et placebo**"
)
| Caractéristiques initiales | Placebo n0 = 2011 |
AZT n1 = 2001 |
Overall n = 4011 |
p2 |
|---|---|---|---|---|
| Site de suivi | >0,9 | |||
| Abidjan, Côte d'Ivoire | 118 (59 %) | 118 (59 %) | 236 (59 %) | |
| Bobo-Dioulasso, Burkina Faso | 83 (41 %) | 82 (41 %) | 165 (41 %) | |
| Âge maternel, années | 25,9 (5,7) | 25,3 (5,0) | 25,6 (5,4) | 0,6 |
| CD4 maternel, cellules/mm³ | 528 [362–729] | 568 [357–757] | 541 [359–741] | 0,7 |
| Données manquantes | 4 | 4 | 8 | |
| Niveau d'instruction | 0,8 | |||
| Aucune instruction | 99 (49 %) | 94 (47 %) | 193 (48 %) | |
| Primaire | 93 (46 %) | 95 (48 %) | 188 (47 %) | |
| Secondaire | 9 (4,5 %) | 11 (5,5 %) | 20 (5,0 %) | |
| Parité | 1,00 [1,00–3,00] | 1,00 [0,00–3,00] | 1,00 [1,00–3,00] | 0,7 |
| 1 n (% %); Mean (SD); Median [Q1–Q3] | ||||
| 2 Pearson’s Chi-squared test; Wilcoxon rank sum test | ||||
Aide à l’interprétation du tableau descriptif :
- Pour les variables qualitatives, les pourcentages décrivent la composition de l’échantillon.
- Pour une variable quantitative approximativement symétrique, la moyenne et l’écart-type décrivent le niveau moyen et la dispersion.
- Pour une variable asymétrique comme les CD4 ou la parité, la médiane et l’intervalle interquartile sont généralement plus appropriés.
- Une ligne « données manquantes » doit être lue séparément : elle indique le nombre de participantes non incluses dans les analyses nécessitant cette variable.
Aide à l’interprétation de la comparabilité initiale : dans un essai randomisé, ce tableau sert surtout à vérifier descriptivement que les caractéristiques initiales sont réparties de façon raisonnablement équilibrée. Une différence observée peut résulter du hasard. Les p-values ne doivent pas être utilisées seules pour sélectionner les covariables du modèle ; la pertinence clinique et le DAG restent prioritaires.
Une même charte graphique est utilisée dans l’ensemble du document : bleu-vert pour l’AZT et gris bleuté pour le placebo.
couleurs_traitement <- c(
"Placebo" = "#626B78",
"AZT" = "#007F86"
)
tme |>
count(traitement) |>
mutate(pourcentage = 100 * n / sum(n)) |>
ggplot(aes(x = traitement, y = pourcentage, fill = traitement)) +
geom_col(width = 0.65) +
geom_text(
aes(label = paste0(n, " (", number(pourcentage, accuracy = 0.1), " %)")),
vjust = -0.5,
fontface = "bold"
) +
scale_fill_manual(values = couleurs_traitement, guide = "none") +
scale_y_continuous(
labels = label_percent(scale = 1),
limits = c(0, 60),
expand = expansion(mult = c(0, 0.03))
) +
labs(
title = "Répartition des participantes selon le traitement",
x = NULL,
y = "Pourcentage"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank()
)
ggplot(tme, aes(x = traitement, y = CD4VAL, fill = traitement)) +
geom_boxplot(width = 0.55, alpha = 0.85, outlier.alpha = 0.45) +
scale_fill_manual(values = couleurs_traitement, guide = "none") +
labs(
title = "Distribution des CD4 maternels à l'inclusion",
x = NULL,
y = "CD4 maternel (cellules/mm³)"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank()
)
tme |>
mutate(indetermine = if_else(statut_vih == "Indéterminé", "Oui", "Non")) |>
count(traitement, indetermine) |>
group_by(traitement) |>
mutate(pourcentage = 100 * n / sum(n)) |>
ungroup() |>
filter(indetermine == "Oui") |>
gt() |>
cols_label(
traitement = "Traitement",
n = "Statuts indéterminés",
pourcentage = "Pourcentage (%)"
) |>
fmt_number(columns = pourcentage, decimals = 1) |>
tab_header(title = "Statuts VIH indéterminés selon le traitement")
| Statuts VIH indéterminés selon le traitement | |||
| Traitement | indetermine | Statuts indéterminés | Pourcentage (%) |
|---|---|---|---|
| Placebo | Oui | 3 | 1.5 |
| AZT | Oui | 7 | 3.5 |
Règle analytique principale : les enfants au statut indéterminé ne sont classés ni comme infectés ni comme non infectés. Ils sont exclus de l’analyse principale de l’infection, puis intégrés dans des analyses de sensibilité.
Le traitement maternel constitue l’exposition principale. Puisqu’il a
été attribué par randomisation, aucune flèche ne doit entrer dans le
nœud du traitement. CD4VAL représente le taux de CD4
à l’inclusion ; il précède donc l’intervention et n’est
pas considéré comme une conséquence de l’AZT dans ce DAG.
Diagramme causal proposé pour l’analyse de l’effet de l’AZT sur les événements de l’enfant.
Source : OpenAI/ChatGPT
Pour l’effet causal principal du traitement, le RR brut reste central grâce à la randomisation. L’ajustement sert principalement à améliorer la précision et à explorer les facteurs pronostiques.
Pour une exposition binaire et un événement binaire, les données peuvent être résumées dans un tableau \(2 \times 2\).
| Événement présent | Événement absent | Total | |
|---|---|---|---|
| Exposés | \(a\) | \(b\) | \(a+b\) |
| Non exposés | \(c\) | \(d\) | \(c+d\) |
Dans cette étude :
Le risque chez les exposés est :
\[R_E = \frac{a}{a+b}\]
Le risque chez les non exposés est :
\[R_0 = \frac{c}{c+d}\]
Le risque relatif est :
\[RR = \frac{R_E}{R_0} = \frac{a/(a+b)}{c/(c+d)}\]
L’odds d’infection chez les exposés est \(a/b\), tandis que l’odds chez les non exposés est \(c/d\). L’odds ratio est donc :
\[OR = \frac{a/b}{c/d} = \frac{ad}{bc}\]
La différence absolue des risques est :
\[DR = R_E - R_0\]
Lorsque le traitement est protecteur, la réduction relative du risque est :
\[RRR = 1-RR\]
et le nombre nécessaire à traiter peut être calculé par :
\[NNT = \frac{1}{|DR|}\]
Lecture des mesures
- \(RR=1\) : risques identiques dans les deux groupes ;
- \(RR<1\) : exposition associée à une diminution du risque ;
- \(RR>1\) : exposition associée à une augmentation du risque ;
- \(OR=1\) : cotes identiques ;
- le RR et l’OR deviennent proches lorsque l’événement est rare, mais peuvent différer lorsque l’événement est fréquent.
tme_assoc <- tme |>
filter(HIVSTATUS != 9)
nrow(tme_assoc)
## [1] 391
Portée de cette estimation : le RR calculé ci-dessous compare les proportions d’enfants classés infectés dans l’extrait pédagogique à la fin du suivi disponible. Il ne correspond pas exactement à l’estimation Kaplan-Meier du risque à 6 mois publiée dans l’article principal.
La première colonne correspond à l’événement, et la première ligne au groupe exposé à l’AZT.
# Le facteur traitement conserve Placebo comme catégorie de référence
# pour les modèles de régression.
tme_assoc <- tme_assoc |>
mutate(
traitement = factor(
traitement,
levels = c("Placebo", "AZT")
),
traitement_2x2 = factor(
traitement,
levels = c("AZT", "Placebo")
),
infection_2x2 = factor(
HIVSTATUS,
levels = c(1, 0),
labels = c("Infecté", "Non infecté")
)
)
# Première ligne : groupe exposé (AZT)
# Première colonne : événement (infection)
tab_azt <- with(
tme_assoc,
table(traitement_2x2, infection_2x2)
)
# Matrice numérique explicitement ordonnée pour epiR et epitools
tab_azt_matrix <- matrix(
c(
tab_azt["AZT", "Infecté"],
tab_azt["AZT", "Non infecté"],
tab_azt["Placebo", "Infecté"],
tab_azt["Placebo", "Non infecté"]
),
nrow = 2,
byrow = TRUE,
dimnames = list(
Traitement = c("AZT", "Placebo"),
Statut_VIH = c("Infecté", "Non infecté")
)
)
tab_azt_matrix
## Statut_VIH
## Traitement Infecté Non infecté
## AZT 41 152
## Placebo 59 139
epiRepiR::epi.2by2(
dat = tab_azt_matrix,
method = "cohort.count",
conf.level = 0.95,
units = 100,
outcome = "as.columns"
)
## Outcome+ Outcome- Total Inc risk *
## Exposure+ 41 152 193 21,24 (15,70 to 27,70)
## Exposure- 59 139 198 29,80 (23,52 to 36,69)
## Total 100 291 391 25,58 (21,32 to 30,20)
##
## Point estimates and 95% CIs:
## -------------------------------------------------------------------
## Inc risk ratio 0.71 (0.50, 1.01)
## Inc odds ratio 0.64 (0.40, 1.01)
## Attrib risk in the exposed * -8.55 (-17.15, 0.04)
## Attrib fraction in the exposed (%) -40.27 (-98.39, 0.37)
## Attrib risk in the population * -4.22 (-11.92, 3.48)
## Attrib fraction in the population (%) -16.51 (-21.48, -10.31)
## E-value 2.15 (NA, 1.00)
## -------------------------------------------------------------------
## Uncorrected chi2 test that OR = 1: chi2(1) = 3.757 Pr>chi2 = 0.053
## Fisher exact test that OR = 1: Pr>chi2 = 0.063
## Wald confidence limits
## CI: confidence interval
## * Outcomes per 100 population units
epitools# epitools attend la catégorie de référence à la première ligne et
# l'absence d'événement dans la première colonne ; on inverse donc
# les lignes et les colonnes pour obtenir Placebo comme référence.
epitools::riskratio(tab_azt_matrix, rev = "both")
## $data
## Statut_VIH
## Traitement Non infecté Infecté Total
## Placebo 139 59 198
## AZT 152 41 193
## Total 291 100 391
##
## $measure
## risk ratio with 95% C.I.
## Traitement estimate lower upper
## Placebo 1,0000000 NA NA
## AZT 0,7129182 0,5045573 1,007323
##
## $p.value
## two-sided
## Traitement midp.exact fisher.exact chi.square
## Placebo NA NA NA
## AZT 0,05377347 0,0634521 0,05257327
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
epitools::oddsratio(tab_azt_matrix, rev = "both")
## $data
## Statut_VIH
## Traitement Non infecté Infecté Total
## Placebo 139 59 198
## AZT 152 41 193
## Total 291 100 391
##
## $measure
## odds ratio with 95% C.I.
## Traitement estimate lower upper
## Placebo 1,0000000 NA NA
## AZT 0,6368427 0,3996076 1,00732
##
## $p.value
## two-sided
## Traitement midp.exact fisher.exact chi.square
## Placebo NA NA NA
## AZT 0,05377347 0,0634521 0,05257327
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
a <- tab_azt_matrix["AZT", "Infecté"]
b <- tab_azt_matrix["AZT", "Non infecté"]
c <- tab_azt_matrix["Placebo", "Infecté"]
d <- tab_azt_matrix["Placebo", "Non infecté"]
risque_azt <- a / (a + b)
risque_placebo <- c / (c + d)
rr <- risque_azt / risque_placebo
se_log_rr <- sqrt((1 / a) - (1 / (a + b)) + (1 / c) - (1 / (c + d)))
rr_inf <- exp(log(rr) - 1.96 * se_log_rr)
rr_sup <- exp(log(rr) + 1.96 * se_log_rr)
or <- (a * d) / (b * c)
se_log_or <- sqrt(1 / a + 1 / b + 1 / c + 1 / d)
or_inf <- exp(log(or) - 1.96 * se_log_or)
or_sup <- exp(log(or) + 1.96 * se_log_or)
comparaison_mesures <- tibble(
mesure = c("Risque relatif (RR)", "Odds ratio (OR)"),
estimation = c(rr, or),
borne_inferieure = c(rr_inf, or_inf),
borne_superieure = c(rr_sup, or_sup)
)
comparaison_mesures |>
mutate(
`Estimation [IC à 95 %]` = paste0(
number(estimation, accuracy = 0.01),
" [", number(borne_inferieure, accuracy = 0.01),
"–", number(borne_superieure, accuracy = 0.01), "]"
)
) |>
select(Mesure = mesure, `Estimation [IC à 95 %]`) |>
gt() |>
tab_header(
title = "Comparaison du RR et de l'OR pour l'effet de l'AZT"
)
| Comparaison du RR et de l'OR pour l'effet de l'AZT | |
| Mesure | Estimation [IC à 95 %] |
|---|---|
| Risque relatif (RR) | 0.71 [0.50–1.01] |
| Odds ratio (OR) | 0.64 [0.40–1.01] |
ggplot(
comparaison_mesures,
aes(x = estimation, y = reorder(mesure, estimation))
) +
geom_vline(xintercept = 1, linetype = 2, linewidth = 0.6) +
geom_errorbarh(
aes(xmin = borne_inferieure, xmax = borne_superieure),
height = 0.18,
linewidth = 0.8
) +
geom_point(size = 3.2) +
labs(
title = "RR et OR : deux mesures différentes",
subtitle = "L'OR s'éloigne davantage de 1 lorsque l'événement n'est pas rare",
x = "Mesure d'association et IC à 95 %",
y = NULL
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_blank()
)
Interprétation : le RR compare directement les risques. L’OR compare les cotes. Pour cette étude longitudinale randomisée, le RR est la mesure principale à communiquer. L’OR est présenté uniquement pour montrer qu’il peut surestimer ou sousestimer visuellement l’ampleur d’une association lorsqu’il est interprété à tort comme un RR.
Les modèles log-binomiaux ci-dessous fournissent directement les RR bruts et leurs intervalles de confiance.
mod_traitement <- glm(
HIVSTATUS ~ traitement,
family = binomial(link = "log"),
data = tme_assoc
)
mod_site <- glm(
HIVSTATUS ~ site_suivi,
family = binomial(link = "log"),
data = tme_assoc
)
mod_age <- glm(
HIVSTATUS ~ age_groupe,
family = binomial(link = "log"),
data = tme_assoc
)
mod_cd4 <- glm(
HIVSTATUS ~ cd4_groupe,
family = binomial(link = "log"),
data = tme_assoc[!is.na(tme_assoc$CD4VAL),]
)
mod_instruction <- glm(
HIVSTATUS ~ niveau_instruction,
family = binomial(link = "log"),
data = tme_assoc
)
mod_parite <- glm(
HIVSTATUS ~ parite_groupe,
family = binomial(link = "log"),
data = tme_assoc
)
resultats_bivaries |>
select(
variables_modalites,
n,
evenements,
evenement_pct,
rr_ic,
p_affichee
) |>
gt() |>
fmt_markdown(columns = variables_modalites) |>
cols_label(
variables_modalites = "Variables et modalités",
n = "n",
evenements = "n1",
evenement_pct = "%",
rr_ic = "RR [IC95 %]",
p_affichee = "p"
) |>
cols_align(
align = "center",
columns = c(n, evenements, evenement_pct, rr_ic, p_affichee)
) |>
tab_header(
title = "Tableau III. Facteurs associés à l'infection VIH de l'enfant"
) |>
tab_source_note(
source_note = "RR : risque relatif ; IC : intervalle de confiance. La première modalité de chaque variable est la référence."
)
| Tableau III. Facteurs associés à l'infection VIH de l'enfant | |||||
| Variables et modalités | n | n1 | % | RR [IC95 %] | p |
|---|---|---|---|---|---|
| Traitement maternel Placebo |
198 | 59 | 29.8 | 1,00 | |
| AZT | 193 | 41 | 21.2 | 0.71 [0.50–1.00] | 0.055 |
| Site de suivi Abidjan, Côte d’Ivoire |
233 | 53 | 22.7 | 1,00 | |
| Bobo-Dioulasso, Burkina Faso | 158 | 47 | 29.7 | 1.31 [0.93–1.83] | 0.118 |
| Âge maternel ≥ 25 ans |
195 | 61 | 31.3 | 1,00 | |
| < 25 ans | 196 | 39 | 19.9 | 0.64 [0.44–0.90] | 0.011 |
| CD4 maternel à l’inclusion ≥ 350 cellules/mm³ |
295 | 51 | 17.3 | 1,00 | |
| < 350 cellules/mm³ | 89 | 47 | 52.8 | 3.05 [2.22–4.21] | < 0,001 |
| Niveau d’instruction Aucune instruction |
189 | 48 | 25.4 | 1,00 | |
| Primaire | 184 | 45 | 24.5 | 0.96 [0.67–1.37] | 0.834 |
| Secondaire | 18 | 7 | 38.9 | 1.53 [0.72–2.63] | 0.184 |
| Parité Nullipare |
92 | 18 | 19.6 | 1,00 | |
| Primipare | 124 | 31 | 25.0 | 1.28 [0.77–2.19] | 0.350 |
| Paucipare | 136 | 39 | 28.7 | 1.47 [0.91–2.47] | 0.128 |
| Multipare | 39 | 12 | 30.8 | 1.57 [0.81–2.92] | 0.157 |
| RR : risque relatif ; IC : intervalle de confiance. La première modalité de chaque variable est la référence. | |||||
Aide à l’interprétation de l’analyse bivariée
Pour chaque variable, la première modalité constitue la référence. Le pourcentage d’événements est calculé en ligne : il répond à la question « parmi les participantes de cette modalité, quelle proportion d’enfants a été infectée ? ». Un RR inférieur à 1 indique un risque plus faible que dans la référence ; un RR supérieur à 1 indique un risque plus élevé. Si l’IC à 95 % contient 1, les données restent compatibles avec une absence d’association au seuil de 5 %. La p-value renseigne sur la compatibilité avec l’hypothèse nulle, mais l’ampleur du RR et la précision de son intervalle doivent rester prioritaires.
Le tableau de contingence par strate du site s’affiche alors ainsi :
with(
tme_assoc,
ftable(site_suivi, traitement, statut_vih)
)
## statut_vih Non infecté Infecté Indéterminé
## site_suivi traitement
## Abidjan, Côte d'Ivoire Placebo 87 30 0
## AZT 93 23 0
## Bobo-Dioulasso, Burkina Faso Placebo 52 29 0
## AZT 59 18 0
Nous allons alors calculer les RR par strate
strat_site <- tme_assoc |>
group_by(site_suivi, traitement) |>
summarise(
n = n(),
evenements = sum(HIVSTATUS),
risque = mean(HIVSTATUS)
) |>
pivot_wider(
names_from = traitement,
values_from = c(n, evenements, risque)
) |>
mutate(
non_evenements_AZT = n_AZT - evenements_AZT,
non_evenements_Placebo = n_Placebo - evenements_Placebo,
RR = risque_AZT / risque_Placebo,
se_log_rr = sqrt(
1 / evenements_AZT - 1 / n_AZT +
1 / evenements_Placebo - 1 / n_Placebo
),
borne_inferieure = exp(log(RR) - 1.96 * se_log_rr),
borne_superieure = exp(log(RR) + 1.96 * se_log_rr),
placebo = paste0(
evenements_Placebo, "/", n_Placebo,
" (", number(100 * risque_Placebo, accuracy = 0.1), " %)"
),
azt = paste0(
evenements_AZT, "/", n_AZT,
" (", number(100 * risque_AZT, accuracy = 0.1), " %)"
),
rr_ic = paste0(
number(RR, accuracy = 0.01),
" [", number(borne_inferieure, accuracy = 0.01),
"–", number(borne_superieure, accuracy = 0.01), "]"
)
)
strat_site |>
select(
`Site de suivi` = site_suivi,
`Placebo : n0/n (%)` = placebo,
`AZT : n1/n (%)` = azt,
`RR [IC à 95 %]` = rr_ic
) |>
gt() |>
tab_header(
title = "Effet estimé de l'AZT selon le site"
)
| Effet estimé de l'AZT selon le site | ||
| Placebo : n0/n (%) | AZT : n1/n (%) | RR [IC à 95 %] |
|---|---|---|
| Abidjan, Côte d'Ivoire | ||
| 30/117 (25.6 %) | 23/116 (19.8 %) | 0.77 [0.48–1.25] |
| Bobo-Dioulasso, Burkina Faso | ||
| 29/81 (35.8 %) | 18/77 (23.4 %) | 0.65 [0.40–1.07] |
strat_cd4 <- tme_assoc|>
filter(!is.na(cd4_groupe)) |>
group_by(cd4_groupe, traitement) |>
summarise(
n = n(),
evenements = sum(HIVSTATUS),
risque = mean(HIVSTATUS)
) |>
pivot_wider(
names_from = traitement,
values_from = c(n, evenements, risque)
) |>
mutate(
RR = risque_AZT / risque_Placebo,
se_log_rr = sqrt(
1 / evenements_AZT - 1 / n_AZT +
1 / evenements_Placebo - 1 / n_Placebo
),
borne_inferieure = exp(log(RR) - 1.96 * se_log_rr),
borne_superieure = exp(log(RR) + 1.96 * se_log_rr),
placebo = paste0(
evenements_Placebo, "/", n_Placebo,
" (", number(100 * risque_Placebo, accuracy = 0.1), " %)"
),
azt = paste0(
evenements_AZT, "/", n_AZT,
" (", number(100 * risque_AZT, accuracy = 0.1), " %)"
),
rr_ic = paste0(
number(RR, accuracy = 0.01),
" [", number(borne_inferieure, accuracy = 0.01),
"–", number(borne_superieure, accuracy = 0.01), "]"
)
)
with(
tme_assoc,
ftable(cd4_groupe, traitement, infection_2x2)
)
## infection_2x2 Infecté Non infecté
## cd4_groupe traitement
## ≥ 350 cellules/mm³ Placebo 33 117
## AZT 18 127
## < 350 cellules/mm³ Placebo 25 20
## AZT 22 22
strat_cd4 |>
select(
`CD4 maternel` = cd4_groupe,
`Placebo : n0/n (%)` = placebo,
`AZT : n1/n (%)` = azt,
`RR [IC à 95 %]` = rr_ic
) |>
gt() |>
tab_header(
title = "Effet estimé de l'AZT selon le niveau de CD4 à l'inclusion"
)
| Effet estimé de l'AZT selon le niveau de CD4 à l'inclusion | ||
| Placebo : n0/n (%) | AZT : n1/n (%) | RR [IC à 95 %] |
|---|---|---|
| ≥ 350 cellules/mm³ | ||
| 33/150 (22.0 %) | 18/145 (12.4 %) | 0.56 [0.33–0.96] |
| < 350 cellules/mm³ | ||
| 25/45 (55.6 %) | 22/44 (50.0 %) | 0.90 [0.61–1.34] |
tab_site_3d <- xtabs(
~ traitement_2x2 + infection_2x2 + site_suivi,
data = tme_assoc
)
epiR::epi.2by2(
dat = tab_site_3d,
method = "cohort.count",
conf.level = 0.95,
outcome = "as.columns"
)
## Outcome+ Outcome- Total Inc risk *
## Exposure+ 41 152 193 21,24 (15,70 to 27,70)
## Exposure- 59 139 198 29,80 (23,52 to 36,69)
## Total 100 291 391 25,58 (21,32 to 30,20)
##
##
## Point estimates and 95% CIs:
## -------------------------------------------------------------------
## Inc risk ratio (crude) 0.71 (0.50, 1.01)
## Inc risk ratio (M-H) 0.71 (0.51, 1.01)
## Inc risk ratio (crude:M-H) 1.00
## Inc odds ratio (crude) 0.64 (0.40, 1.01)
## Inc odds ratio (M-H) 0.64 (0.40, 1.01)
## Inc odds ratio (crude:M-H) 1.00
## Attrib risk in the exposed (crude) * -8.55 (-17.15, 0.04)
## Attrib risk in the exposed (M-H) * -8.48 (-17.15, 0.18)
## Attrib risk (crude:M-H) 1.01
## E-value (crude) 2.15 (NA, 1.00)
## E-value (M-H) 2.15 (NA, 1.00)
## -------------------------------------------------------------------
## M-H test of homogeneity of IRRs: chi2(1) = 0.230 Pr>chi2 = 0.631
## M-H test of homogeneity of ORs: chi2(1) = 0.317 Pr>chi2 = 0.574
## Test that M-H adjusted OR = 1: chi2(1) = 3.700 Pr>chi2 = 0.054
## Wald confidence limits
## M-H: Mantel-Haenszel; CI: confidence interval
## * Outcomes per 100 population units
modele_interaction_site <- glm(
infection ~ traitement * site_suivi,
family = binomial(link = "log"),
data = tme_assoc
)
broom::tidy(
modele_interaction_site,
exponentiate = TRUE,
conf.int = TRUE
) |>
gt() |>
fmt_number(
columns = c(estimate, conf.low, conf.high, p.value),
decimals = 3
) |>
cols_label(
term = "Terme",
estimate = "RR",
conf.low = "Borne inférieure",
conf.high = "Borne supérieure",
p.value = "Valeur p"
) |>
tab_header(
title = "Interaction entre le traitement et le site"
)
| Interaction entre le traitement et le site | ||||||
| Terme | RR | std.error | statistic | Valeur p | Borne inférieure | Borne supérieure |
|---|---|---|---|---|---|---|
| (Intercept) | 0.256 | 0,1574367 | -8,6445941 | 0.000 | 0.183 | 0.340 |
| traitementAZT | 0.773 | 0,2442210 | -1,0528148 | 0.292 | 0.473 | 1.244 |
| site_suiviBobo-Dioulasso, Burkina Faso | 1.396 | 0,2166181 | 1,5410680 | 0.123 | 0.909 | 2.145 |
| traitementAZT:site_suiviBobo-Dioulasso, Burkina Faso | 0.844 | 0,3526322 | -0,4797092 | 0.631 | 0.419 | 1.683 |
Une différence numérique entre les RR des deux sites ne prouve pas automatiquement une modification d’effet. Le terme d’interaction indique si les données apportent suffisamment d’arguments en faveur d’un effet différent selon le site.
modele_interaction_cd4 <- glm(
infection ~ traitement * cd4_groupe,
family = binomial(link = "log"),
data = tme_assoc
)
broom::tidy(
modele_interaction_cd4,
exponentiate = TRUE,
conf.int = TRUE
) |>
gt() |>
fmt_number(
columns = c(estimate, conf.low, conf.high, p.value),
decimals = 3
) |>
cols_label(
term = "Terme",
estimate = "RR",
conf.low = "Borne inférieure",
conf.high = "Borne supérieure",
p.value = "Valeur p"
) |>
tab_header(
title = "Interaction entre le traitement et le taux de CD4"
)
| Interaction entre le traitement et le taux de CD4 | ||||||
| Terme | RR | std.error | statistic | Valeur p | Borne inférieure | Borne supérieure |
|---|---|---|---|---|---|---|
| (Intercept) | 0.220 | 0,1537412 | -9,848549 | 0.000 | 0.159 | 0.291 |
| traitementAZT | 0.564 | 0,2688776 | -2,128233 | 0.033 | 0.325 | 0.942 |
| cd4_groupe< 350 cellules/mm³ | 2.525 | 0,2035046 | 4,551941 | 0.000 | 1.678 | 3.770 |
| traitementAZT:cd4_groupe< 350 cellules/mm³ | 1.595 | 0,3358574 | 1,390095 | 0.165 | 0.830 | 3.127 |
Aide à l’interprétation de l’analyse stratifiée
Les RR propres à chaque strate permettent de vérifier si l’effet du traitement est semblable dans les sous-groupes. Des RR proches suggèrent un effet relativement homogène. Des RR nettement différents peuvent traduire une modification d’effet, mais celle-ci doit être confirmée par un test d’interaction et interprétée en tenant compte des effectifs et de la largeur des intervalles de confiance. Un RR commun de Mantel-Haenszel résume l’association après contrôle de la variable de stratification, sous l’hypothèse d’un effet suffisamment homogène entre les strates.
Le modèle log-binomial estime directement des risques relatifs, mais il présente fréquemment des difficultés de convergence. Les observations dont le CD4 est manquant ne sont pas supprimées du calcul du RR brut du traitement ; elles sont exclues uniquement des analyses stratifiées ou multivariées qui nécessitent cette covariable. Dans ce script, une régression de Poisson modifiée avec variance robuste est utilisée. Avec une issue binaire et des erreurs-types robustes, les coefficients exponentiés sont interprétés comme des RR ajustés. Les catégories utilisées dans le tableau bivarié sont conservées afin de faciliter la comparaison.
modele1 <- glm(
HIVSTATUS ~ traitement + site_suivi + age_groupe + cd4_groupe +
instruction_groupe + parite_groupe,
family = poisson(link = "log"),
data = tme_assoc[!is.na(tme_assoc$CD4VAL), ]
)
modele_rr_ajuste <- step(modele1, direction = "both",trace=FALSE)
# Erreurs-types robustes (sandwich) pour corriger la sur-dispersion inhérente
vcov_robuste <- vcovHC(modele_rr_ajuste, type = "HC1")
resultats_rr <- coeftest(modele_rr_ajuste, vcov = vcov_robuste)
resultats_rr
##
## z test of coefficients:
##
## Estimate Std. Error z value
## (Intercept) -1,57746 0,18937 -8,3300
## traitementAZT -0,33745 0,16870 -2,0004
## site_suiviBobo-Dioulasso, Burkina Faso 0,34831 0,16362 2,1287
## age_groupe< 25 ans -0,37998 0,17093 -2,2231
## cd4_groupe< 350 cellules/mm³ 1,10910 0,16489 6,7262
## Pr(>|z|)
## (Intercept) < 0,00000000000000022 ***
## traitementAZT 0,04546 *
## site_suiviBobo-Dioulasso, Burkina Faso 0,03328 *
## age_groupe< 25 ans 0,02621 *
## cd4_groupe< 350 cellules/mm³ 0,00000000001742 ***
## ---
## Signif. codes: 0 '***' 0,001 '**' 0,01 '*' 0,05 '.' 0,1 ' ' 1
# IC à 95% robustes
ic_robustes <- coefci(modele_rr_ajuste, vcov. = vcov_robuste)
modele_rr_ajuste$converged
## [1] TRUE
Si le résultat ci-dessus est
TRUE, l’algorithme du modèle de Poisson a convergé. La variance robuste corrige les erreurs-types afin que les intervalles de confiance soient adaptés à une issue binaire.
table_modele <- tibble(
term = rownames(resultats_rr),
estimate = resultats_rr[, "Estimate"],
std.error = resultats_rr[, "Std. Error"],
p.value = resultats_rr[, "Pr(>|z|)"],
conf.low = ic_robustes[, 1],
conf.high = ic_robustes[, 2]
) |>
filter(term != "(Intercept)") |>
mutate(
rr_ajuste = exp(estimate),
rr_ajuste_inf = exp(conf.low),
rr_ajuste_sup = exp(conf.high)
) |>
select(
terme = term,
rr_ajuste,
rr_ajuste_inf,
rr_ajuste_sup,
p_ajustee = p.value
)
# --- Fusion avec le tableau bivarié ---
resultats_multivaries <- resultats_bivaries |>
left_join(table_modele, by = "terme") |>
mutate(
rra_ic = case_when(
is.na(terme) ~ "1,00",
is.na(rr_ajuste) ~ "",
TRUE ~ paste0(
number(rr_ajuste, accuracy = 0.01),
" [", number(rr_ajuste_inf, accuracy = 0.01),
"–", number(rr_ajuste_sup, accuracy = 0.01), "]"
)
),
p_ajustee_affichee = case_when(
is.na(p_ajustee) ~ "",
p_ajustee < 0.001 ~ "< 0,001",
TRUE ~ number(p_ajustee, accuracy = 0.001)
)
)
# --- Tableau final ---
resultats_multivaries |>
select(
variables_modalites,
n,
evenements,
evenement_pct,
rr_ic,
p_affichee,
rra_ic,
p_ajustee_affichee
) |>
gt() |>
fmt_markdown(columns = variables_modalites) |>
cols_label(
variables_modalites = "Variables et modalités",
n = "n",
evenements = "n1",
evenement_pct = "%",
rr_ic = "RRb [IC à 95 %]",
p_affichee = "p",
rra_ic = "RRa [IC à 95 %]",
p_ajustee_affichee = "p ajustée"
) |>
cols_align(
align = "center",
columns = c(n, evenements, evenement_pct, rr_ic, p_affichee, rra_ic, p_ajustee_affichee)
) |>
tab_header(
title = "Tableau IV. Facteurs associés à l'infection : RR bruts et ajustés"
) |>
tab_source_note(
source_note = "RRb : risque relatif brut ; RRa : risque relatif ajusté, estimé par régression de Poisson modifiée avec erreurs-types robustes (sandwich). IC : intervalle de confiance à 95 %."
)
| Tableau IV. Facteurs associés à l'infection : RR bruts et ajustés | |||||||
| Variables et modalités | n | n1 | % | RRb [IC à 95 %] | p | RRa [IC à 95 %] | p ajustée |
|---|---|---|---|---|---|---|---|
| Traitement maternel Placebo |
198 | 59 | 29.8 | 1,00 | 1,00 | ||
| AZT | 193 | 41 | 21.2 | 0.71 [0.50–1.00] | 0.055 | 0.71 [0.51–0.99] | 0.045 |
| Site de suivi Abidjan, Côte d’Ivoire |
233 | 53 | 22.7 | 1,00 | 1,00 | ||
| Bobo-Dioulasso, Burkina Faso | 158 | 47 | 29.7 | 1.31 [0.93–1.83] | 0.118 | 1.42 [1.03–1.95] | 0.033 |
| Âge maternel ≥ 25 ans |
195 | 61 | 31.3 | 1,00 | 1,00 | ||
| < 25 ans | 196 | 39 | 19.9 | 0.64 [0.44–0.90] | 0.011 | 0.68 [0.49–0.96] | 0.026 |
| CD4 maternel à l’inclusion ≥ 350 cellules/mm³ |
295 | 51 | 17.3 | 1,00 | 1,00 | ||
| < 350 cellules/mm³ | 89 | 47 | 52.8 | 3.05 [2.22–4.21] | < 0,001 | 3.03 [2.19–4.19] | < 0,001 |
| Niveau d’instruction Aucune instruction |
189 | 48 | 25.4 | 1,00 | 1,00 | ||
| Primaire | 184 | 45 | 24.5 | 0.96 [0.67–1.37] | 0.834 | ||
| Secondaire | 18 | 7 | 38.9 | 1.53 [0.72–2.63] | 0.184 | ||
| Parité Nullipare |
92 | 18 | 19.6 | 1,00 | 1,00 | ||
| Primipare | 124 | 31 | 25.0 | 1.28 [0.77–2.19] | 0.350 | ||
| Paucipare | 136 | 39 | 28.7 | 1.47 [0.91–2.47] | 0.128 | ||
| Multipare | 39 | 12 | 30.8 | 1.57 [0.81–2.92] | 0.157 | ||
| RRb : risque relatif brut ; RRa : risque relatif ajusté, estimé par régression de Poisson modifiée avec erreurs-types robustes (sandwich). IC : intervalle de confiance à 95 %. | |||||||
forest_rra <- table_modele |>
mutate(
libelle = recode(
terme,
"traitementAZT" = "AZT vs placebo",
"site_suiviBobo-Dioulasso, Burkina Faso" = "Bobo-Dioulasso vs Abidjan",
"age_groupe< 25 ans" = "Âge < 25 ans",
"cd4_groupe< 350 cellules/mm³" = "CD4 < 350 cellules/mm³",
"instruction_groupeAucune ou primaire" = "Instruction : aucune ou primaire",
"parite_groupePrimipare" = "Primipare vs nullipare",
"parite_groupePaucipare" = "Paucipare vs nullipare",
"parite_groupeMultipare" = "Multipare vs nullipare"
)
)
ggplot(
forest_rra,
aes(x = rr_ajuste, y = reorder(libelle, rr_ajuste))
) +
geom_vline(xintercept = 1, linetype = 2, linewidth = 0.6) +
geom_errorbarh(
aes(xmin = rr_ajuste_inf, xmax = rr_ajuste_sup),
height = 0.18,
linewidth = 0.8
) +
geom_point(size = 3) +
scale_x_log10() +
labs(
title = "Facteurs associés à l'infection VIH de l'enfant",
subtitle = "Risques relatifs ajustés et intervalles de confiance à 95 %",
x = "RRa",
y = NULL
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_blank()
)
Aide à l’interprétation du modèle multivarié
Le RRa du traitement compare le risque d’infection sous AZT au risque sous placebo, après prise en compte simultanée des autres variables du modèle. Dans un essai randomisé, cette estimation ajustée complète le RR brut mais ne le remplace pas. Une modification importante entre RR brut et RRa peut résulter d’un déséquilibre fortuit, de données manquantes ou du changement de population analysée. Les variables continues ou catégorisées doivent être interprétées selon l’unité ou la référence affichée. Les résultats du modèle ne doivent pas être interprétés automatiquement comme causaux pour les covariables non randomisées.
Pour un enfant infecté, le temps est calculé entre la naissance et la date du diagnostic. Pour un enfant non infecté, le temps est calculé entre la naissance et la dernière date biologique disponible.
Écart par rapport aux publications : dans la base,
DATINFcorrespond à une date de diagnostic et non nécessairement à la date biologique exacte de contamination. Cette séance utilise donc une approximation ponctuelle compatible avec Kaplan-Meier et Cox standards. Les analyses publiées de suivi prolongé ont tenu compte du fait que l’infection pouvait être connue seulement entre deux tests successifs.
tme_survie_infection <- tme |>
filter(statut_vih %in% c("Infecté", "Non infecté")) |>
mutate(
evenement_infection = if_else(statut_vih == "Infecté", 1, 0),
date_fin_infection = if_else(
evenement_infection == 1,
DATINF,
DATE_LAST_BIO
),
temps_infection_jours = as.numeric(date_fin_infection - DATBIRTH),
temps_infection_mois = temps_infection_jours / 30.44
) |>
filter(
!is.na(temps_infection_mois),
temps_infection_mois >= 0
)
nrow(tme_survie_infection)
## [1] 391
tme_survie_infection |>
group_by(traitement) |>
summarise(
n = n(),
infections = sum(evenement_infection),
censures = sum(evenement_infection == 0),
suivi_median = median(temps_infection_mois),
q1 = quantile(temps_infection_mois, 0.25),
q3 = quantile(temps_infection_mois, 0.75),
personnes_mois = sum(temps_infection_mois),
incidence_100_pm = 100 * infections / personnes_mois
) |>
mutate(
`Suivi médian [Q1–Q3], mois` = paste0(
number(suivi_median, accuracy = 0.1),
" [", number(q1, accuracy = 0.1),
"–", number(q3, accuracy = 0.1), "]"
)
) |>
select(
Traitement = traitement,
n,
Infections = infections,
Censures = censures,
`Suivi médian [Q1–Q3], mois`,
`Incidence pour 100 personnes-mois` = incidence_100_pm
) |>
gt() |>
fmt_number(
columns = `Incidence pour 100 personnes-mois`,
decimals = 2
) |>
tab_header(
title = "Description du suivi jusqu'à l'infection"
)
| Description du suivi jusqu'à l'infection | |||||
| Traitement | n | Infections | Censures | Suivi médian [Q1–Q3], mois | Incidence pour 100 personnes-mois |
|---|---|---|---|---|---|
| Placebo | 198 | 59 | 139 | 15.2 [1.5–18.6] | 2.45 |
| AZT | 193 | 41 | 152 | 18.0 [7.1–20.6] | 1.47 |
Temps d’infection globale dans l’échantillon
km_globale <- survfit(
Surv(temps_infection_mois, evenement_infection) ~ 1,
data = tme_survie_infection
)
summary(km_globale)
## Call: survfit(formula = Surv(temps_infection_mois, evenement_infection) ~
## 1, data = tme_survie_infection)
##
## time n.risk n.event survival std.err lower 95% CI upper 95% CI
## 0,0329 390 9 0,977 0,00760 0,962 0,992
## 0,0657 378 4 0,967 0,00911 0,949 0,985
## 0,0986 371 3 0,959 0,01009 0,939 0,979
## 0,2300 368 3 0,951 0,01097 0,930 0,973
## 0,2628 365 2 0,946 0,01152 0,923 0,969
## 0,2957 362 7 0,927 0,01321 0,902 0,954
## 0,3285 354 4 0,917 0,01406 0,890 0,945
## 0,3614 349 3 0,909 0,01465 0,881 0,938
## 0,3942 346 2 0,904 0,01503 0,875 0,934
## 0,8213 343 1 0,901 0,01522 0,872 0,932
## 1,2812 342 1 0,899 0,01540 0,869 0,929
## 1,3798 341 2 0,893 0,01576 0,863 0,925
## 1,4126 338 1 0,891 0,01593 0,860 0,922
## 1,4455 337 5 0,877 0,01675 0,845 0,911
## 1,4783 331 11 0,848 0,01836 0,813 0,885
## 1,5112 318 3 0,840 0,01876 0,804 0,878
## 1,5440 314 5 0,827 0,01939 0,790 0,866
## 1,5769 309 4 0,816 0,01986 0,778 0,856
## 2,7595 302 1 0,813 0,01998 0,775 0,854
## 2,8909 300 1 0,811 0,02010 0,772 0,851
## 2,9566 296 2 0,805 0,02033 0,766 0,846
## 3,0223 292 1 0,803 0,02045 0,763 0,844
## 3,0552 291 1 0,800 0,02056 0,760 0,841
## 3,0880 290 2 0,794 0,02079 0,755 0,836
## 3,3509 287 1 0,792 0,02090 0,752 0,834
## 5,8804 284 1 0,789 0,02101 0,749 0,831
## 5,9461 283 2 0,783 0,02123 0,743 0,826
## 5,9790 281 1 0,780 0,02134 0,740 0,823
## 6,0775 273 2 0,775 0,02156 0,734 0,818
## 9,0013 262 3 0,766 0,02191 0,724 0,810
## 9,0670 256 1 0,763 0,02203 0,721 0,807
## 10,0854 252 1 0,760 0,02215 0,718 0,804
## 12,0237 245 1 0,757 0,02227 0,714 0,802
## 12,7135 236 1 0,753 0,02241 0,711 0,799
## 14,9146 230 1 0,750 0,02255 0,707 0,796
## 14,9803 227 2 0,744 0,02283 0,700 0,790
## 17,9369 194 1 0,740 0,02303 0,696 0,786
## 17,9698 187 1 0,736 0,02325 0,692 0,783
## 18,0683 159 1 0,731 0,02356 0,686 0,779
## 18,6597 116 1 0,725 0,02418 0,679 0,774
## 21,0578 74 1 0,715 0,02576 0,666 0,767
ggsurvplot(
km_globale,
data = tme_survie_infection,
color ="blue",
risk.table = TRUE,
conf.int = TRUE,
xlab = "Temps depuis la naissance (mois)",
ylab = "Probabilité de rester non infecté",
ggtheme = theme_survminer(base_size = 12),
risk.table.height = 0.25
)
km_infection <- survfit(
Surv(temps_infection_mois, evenement_infection) ~ traitement,
data = tme_survie_infection
)
ggsurvplot(
km_infection,
data = tme_survie_infection,
risk.table = TRUE,
pval = TRUE,
conf.int = FALSE,
palette = unname(couleurs_traitement),
xlab = "Temps depuis la naissance (mois)",
ylab = "Probabilité de rester non infecté",
legend.title = "Traitement",
legend.labs = c("Placebo", "AZT"),
ggtheme = theme_minimal(base_size = 12),
risk.table.height = 0.25
)
Une courbe plus élevée indique une probabilité plus importante de rester non infecté. La p-value affichée correspond au test du log-rank.
modele2 <- coxph(
Surv(temps_infection_mois, evenement_infection) ~
traitement + site_suivi + AGEINC + cd4_groupe +
niveau_instruction + parite_groupe,
data = tme_survie_infection[!is.na(tme_survie_infection$CD4VAL),]
)
cox_infection <- step(modele2, direction = "backward",trace=FALSE)
cox_infection |>
tbl_regression(
exponentiate = TRUE,
label = list(
traitement ~ "Traitement maternel",
site_suivi ~ "Site de suivi",
AGEINC ~ "Âge maternel",
cd4_groupe ~ "CD4 maternel"
)
) |>
modify_header(
label ~ "**Variables et modalités**",
estimate ~ "**HR [IC à 95 %]**",
p.value ~ "**Valeur p**"
) |>
bold_labels() |>
modify_caption(
"**Tableau 5. Modèle de Cox du délai jusqu'à l'infection VIH**"
)
| Variables et modalités | HR [IC à 95 %] | 95% CI | Valeur p |
|---|---|---|---|
| Traitement maternel | |||
| Placebo | — | — | |
| AZT | 0,66 | 0,44, 0,99 | 0,044 |
| Site de suivi | |||
| Abidjan, Côte d'Ivoire | — | — | |
| Bobo-Dioulasso, Burkina Faso | 1,50 | 1,00, 2,24 | 0,048 |
| Âge maternel | 1,03 | 0,99, 1,07 | 0,11 |
| CD4 maternel | |||
| ≥ 350 cellules/mm³ | — | — | |
| < 350 cellules/mm³ | 3,81 | 2,54, 5,69 | <0,001 |
| Abbreviations: CI = Confidence Interval, HR = Hazard Ratio | |||
Le hazard ratio (HR) compare le taux instantané d’infection entre les groupes. Il ne doit pas être interprété comme un risque relatif cumulé.
Aide à l’interprétation de l’analyse de survie
- La courbe de Kaplan-Meier représente ici la probabilité de rester non infecté.
- Une courbe AZT située au-dessus de la courbe placebo suggère une meilleure survie sans infection.
- Le test du log-rank compare globalement les courbes sur toute la durée du suivi.
- Le HR du traitement compare le taux instantané d’infection sous AZT à celui du placebo. Un HR inférieur à 1 indique une survenue moins rapide de l’infection sous AZT.
- Le HR n’est pas un RR : il ne compare pas directement les proportions cumulées infectées.
- L’hypothèse de proportionnalité doit être examinée avant de résumer l’effet par un HR unique.
test_ph_infection <- cox.zph(cox_infection)
test_ph_infection
## chisq df p
## traitement 0,1424 1 0,71
## site_suivi 0,0406 1 0,84
## AGEINC 0,0858 1 0,77
## cd4_groupe 6,5634 1 0,01
## GLOBAL 6,9439 4 0,14
plot(test_ph_infection)
Une p-value élevée ne met pas en évidence de violation de l’hypothèse des risques proportionnels. Il faut toutefois examiner séparément chaque covariable et ne pas se limiter au test global. Une p-value inférieure à 0,05 pour une variable suggère que son effet pourrait varier au cours du temps ; une stratification, une interaction avec le temps ou une présentation temporelle de l’effet peut alors être envisagée. L’inspection des graphiques reste indispensable.
Qu’en est-il du temps jusqu’au décès ?
tme_survie_deces <- tme |>
mutate(
evenement_deces = deces,
date_fin_deces = if_else(
evenement_deces == 1,
DATE_DTH,
DATE_LAST_BIO
),
temps_deces_jours = as.numeric(date_fin_deces - DATBIRTH),
temps_deces_mois = temps_deces_jours / 30.45
) |>
filter(
!is.na(temps_deces_mois),
temps_deces_mois >= 0
)
km_globale <- survfit(
Surv(temps_deces_mois, evenement_deces) ~ 1,
data = tme_survie_deces
)
summary(tme_survie_deces)
## ID TTTGRP AGEINC CD4VAL
## Length :397 Min. :0,0000 Min. :18,00 Min. : 11,0
## N.unique :397 1st Qu.:0,0000 1st Qu.:21,00 1st Qu.: 359,0
## N.blank : 0 Median :0,0000 Median :24,00 Median : 543,0
## Min.nchar: 5 Mean :0,4962 Mean :25,58 Mean : 576,5
## Max.nchar: 5 3rd Qu.:1,0000 3rd Qu.:29,00 3rd Qu.: 741,0
## Max. :1,0000 Max. :43,00 Max. :1870,0
## NAs :8
## NIVINSTRUC PARITY HIVSTATUS DATINF
## Min. : 0,000 Min. :0,000 Min. :0,0000 Min. :1996-01-07
## 1st Qu.: 0,000 1st Qu.:1,000 1st Qu.:0,0000 1st Qu.:1996-09-20
## Median : 1,000 Median :1,000 Median :0,0000 Median :1997-10-03
## Mean : 1,552 Mean :1,907 Mean :0,3879 Mean :1997-07-21
## 3rd Qu.: 2,000 3rd Qu.:3,000 3rd Qu.:1,0000 3rd Qu.:1998-01-15
## Max. :12,000 Max. :9,000 Max. :9,0000 Max. :1999-08-12
## NAs :297
## DATBIRTH DTH_CH DATE_DTH
## Min. :1995-10-01 Min. :0,0000 Min. :1995-10-18
## 1st Qu.:1996-06-21 1st Qu.:0,0000 1st Qu.:1997-05-27
## Median :1997-07-01 Median :0,0000 Median :1998-02-25
## Mean :1997-03-16 Mean :0,2242 Mean :1998-01-17
## 3rd Qu.:1997-10-31 3rd Qu.:0,0000 3rd Qu.:1998-08-03
## Max. :1998-03-23 Max. :1,0000 Max. :2000-02-20
## NAs :308
## DATE_LAST_BIO SITE traitement
## Min. :1996-02-17 Length :397 Placebo:200
## 1st Qu.:1997-11-27 N.unique : 2 AZT :197
## Median :1998-06-02 N.blank : 0
## Mean :1998-06-21 Min.nchar: 2
## 3rd Qu.:1999-03-12 Max.nchar: 2
## Max. :2000-04-04
## NAs :6
## site_suivi statut_vih statut_deces
## Abidjan, Côte d'Ivoire :235 Non infecté:291 Vivant:308
## Bobo-Dioulasso, Burkina Faso:162 Infecté :100 Décédé: 89
## Indéterminé: 6
##
##
##
##
## infection deces niveau_instruction age_groupe
## Min. :0,0000 Min. :0,0000 Aucune instruction:192 ≥ 25 ans:197
## 1st Qu.:0,0000 1st Qu.:0,0000 Primaire :187 < 25 ans:200
## Median :0,0000 Median :0,0000 Secondaire : 18
## Mean :0,2558 Mean :0,2242
## 3rd Qu.:1,0000 3rd Qu.:0,0000
## Max. :1,0000 Max. :1,0000
## NAs :6
## cd4_groupe instruction_groupe parite_groupe
## ≥ 350 cellules/mm³:299 Secondaire ou supérieur: 18 Nullipare: 95
## < 350 cellules/mm³: 90 Aucune ou primaire :379 Primipare:126
## NAs : 8 Paucipare:136
## Multipare: 40
##
##
##
## evenement_deces date_fin_deces temps_deces_jours temps_deces_mois
## Min. :0,0000 Min. :1995-10-18 Min. : 0,0 Min. : 0,000
## 1st Qu.:0,0000 1st Qu.:1997-12-01 1st Qu.:303,0 1st Qu.: 9,951
## Median :0,0000 Median :1998-06-22 Median :549,0 Median :18,030
## Mean :0,2242 Mean :1998-07-01 Mean :471,7 Mean :15,492
## 3rd Qu.:0,0000 3rd Qu.:1999-03-12 3rd Qu.:618,0 3rd Qu.:20,296
## Max. :1,0000 Max. :2000-04-04 Max. :971,0 Max. :31,888
##
ggsurvplot(
km_globale,
data = tme_survie_deces,
color ="red",
risk.table = TRUE,
conf.int = TRUE,
xlab = "Temps depuis la naissance (mois)",
ylab = "Probabilité de rester non infecté",
ggtheme = theme_survminer(base_size = 12),
risk.table.height = 0.25
)
km_deces <- survfit(
Surv(temps_deces_mois, evenement_deces) ~ traitement,
data = tme_survie_deces
)
ggsurvplot(
km_deces,
data = tme_survie_deces,
risk.table = TRUE,
pval = TRUE,
conf.int = TRUE,
palette = unname(couleurs_traitement),
xlab = "Âge de l'enfant (mois)",
ylab = "Probabilité de survie",
legend.title = "Traitement",
legend.labs = c("Placebo", "AZT"),
ggtheme = theme_minimal(base_size = 12),
risk.table.height = 0.25
)
Dans le modèle principal de mortalité, le statut VIH de l’enfant
n’est pas ajouté comme covariable, car il peut se situer sur le chemin
causal entre le traitement et le décès. Pour les enfants vivants,
DATE_LAST_BIO est utilisée comme date de dernière
observation, faute de date clinique de dernière nouvelle distincte dans
la base pédagogique.
modele3 <- coxph(
Surv(temps_deces_mois, evenement_deces) ~
traitement + site_suivi + age_groupe + cd4_groupe +
niveau_instruction + parite_groupe,
data = tme_survie_deces[!is.na(tme_survie_deces$CD4VAL),]
)
cox_deces <- step(modele3, direction = "backward",trace=FALSE)
cox_deces |>
tbl_regression(
exponentiate = TRUE,
label = list(
traitement ~ "Traitement maternel",
age_groupe ~ "Âge maternel",
cd4_groupe ~ "CD4 maternel"
)
) |>
modify_header(
label ~ "**Variables et modalités**",
estimate ~ "**HR [IC à 95 %]**",
p.value ~ "**Valeur p**"
) |>
bold_labels() |>
modify_caption(
"**Tableau 6. Modèle de Cox du délai jusqu'au décès de l'enfant**"
)
| Variables et modalités | HR [IC à 95 %] | 95% CI | Valeur p |
|---|---|---|---|
| Traitement maternel | |||
| Placebo | — | — | |
| AZT | 0,65 | 0,43, 1,00 | 0,051 |
| Âge maternel | |||
| ≥ 25 ans | — | — | |
| < 25 ans | 0,65 | 0,42, 1,00 | 0,050 |
| CD4 maternel | |||
| ≥ 350 cellules/mm³ | — | — | |
| < 350 cellules/mm³ | 2,92 | 1,87, 4,54 | <0,001 |
| Abbreviations: CI = Confidence Interval, HR = Hazard Ratio | |||
ggcoef_model(cox_deces, exponentiate = TRUE)
Aide à l’interprétation de la mortalité
La courbe de survie globale décrit la probabilité de rester vivant au cours du suivi. Dans le modèle de Cox, un HR de décès inférieur à 1 pour l’AZT suggère un taux instantané de décès plus faible que sous placebo. L’absence de significativité ne prouve pas l’absence d’effet : elle peut refléter un effet modéré, un nombre d’événements insuffisant ou une incertitude élevée. Le statut VIH de l’enfant n’est pas ajusté dans le modèle principal de mortalité, car il peut constituer un mécanisme intermédiaire par lequel l’AZT influence le décès.
Quatre scénarios sont comparés :
| Analyses de sensibilité des statuts VIH indéterminés | |
| Scénario | RR de l'AZT versus placebo |
|---|---|
| Statuts connus uniquement | 0.71 |
| Tous les indéterminés infectés | 0.78 |
| Tous les indéterminés non infectés | 0.70 |
| Scénario défavorable à l'AZT | 0.82 |
ggplot(
resultats_sensibilite,
aes(x = RR, y = reorder(scenario, RR))
) +
geom_vline(xintercept = 1, linetype = 2) +
geom_point(size = 3) +
labs(
title = "Robustesse de l'effet estimé de l'AZT",
x = "Risque relatif",
y = NULL
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_blank()
)
Si les conclusions restent similaires dans les différents scénarios, elles sont moins sensibles au traitement des statuts indéterminés.
La synthèse doit distinguer les différentes mesures :
difference_risque <- risque_azt - risque_placebo
reduction_relative <- 1 - rr
nnt <- 1 / abs(difference_risque)
synthese <- tibble(
indicateur = c(
"Risque d'infection sous placebo",
"Risque d'infection sous AZT",
"Risque relatif",
"Réduction relative du risque",
"Différence de risques",
"Nombre nécessaire à traiter"
),
valeur = c(
percent(risque_placebo, accuracy = 0.1),
percent(risque_azt, accuracy = 0.1),
number(rr, accuracy = 0.01),
percent(reduction_relative, accuracy = 0.1),
percent(difference_risque, accuracy = 0.1),
number(nnt, accuracy = 0.1)
)
)
synthese |>
gt() |>
cols_label(
indicateur = "Indicateur",
valeur = "Estimation"
) |>
tab_header(
title = "Synthèse de l'efficacité estimée de l'AZT"
)
| Synthèse de l'efficacité estimée de l'AZT | |
| Indicateur | Estimation |
|---|---|
| Risque d'infection sous placebo | 29.8% |
| Risque d'infection sous AZT | 21.2% |
| Risque relatif | 0.71 |
| Réduction relative du risque | 28.7% |
| Différence de risques | -8.6% |
| Nombre nécessaire à traiter | 11.7 |
Parmi les enfants dont le statut VIH était connu, le risque d’infection était de 29.8% dans le groupe placebo contre 21.2% dans le groupe AZT. Le RR brut de l’AZT par rapport au placebo était de 0.71 [IC à 95 % : 0.50–1.01]. L’estimation correspond à une réduction relative du risque de 28.7% et à une différence absolue de -8.6%. Il faudrait traiter environ 11.7 femmes par ce schéma pour éviter une infection supplémentaire, si l’association observée reflète l’effet causal et si les conditions de l’étude sont transposables.
L’estimation brute est donc orientée vers un effet protecteur, mais avec un intervalle de confiance incluant 1. L’intervalle de confiance est particulièrement important : il indique les valeurs de l’effet encore compatibles avec les données et empêche de réduire la conclusion à la seule p-value.
L’OR était de 0.64, contre un RR de 0.71. L’OR est plus éloigné de 1 que le RR et suggère visuellement un effet plus fort. Dans cet essai longitudinal, le RR doit être privilégié, car il compare directement les probabilités d’infection dans les deux groupes. L’OR ne doit pas être interprété comme une réduction du risque.
L’effet estimé de l’AZT était orienté dans le sens protecteur dans les deux sites : RR = 0.77 à Abidjan et RR = 0.65 à Bobo-Dioulasso. Les intervalles de confiance propres aux sites étaient larges, ce qui traduit une précision limitée dans les sous-groupes. L’absence d’interaction statistiquement mise en évidence signifie que les données ne démontrent pas formellement une différence d’efficacité entre les deux sites.
La stratification selon les CD4 suggère un effet plus marqué chez les femmes ayant un taux de CD4 d’au moins 350 cellules/mm³, avec un RR de 0.56, que chez celles présentant moins de 350 cellules/mm³, avec un RR de 0.90. Cette observation est cohérente avec les publications de suivi de DITRAME, qui rapportaient une efficacité plus faible chez les femmes présentant une immunodépression plus avancée. Elle doit néanmoins rester prudente : les analyses de sous-groupes comportent moins d’observations et peuvent être instables.
Après ajustement sur le site, l’âge maternel, le niveau de CD4, l’instruction et la parité, le RR ajusté de l’AZT était de 0.71 [IC à 95 % : 0.51–0.99 ; p = 0.045]. Le modèle ajusté doit être interprété comme une analyse complémentaire au RR brut randomisé. Il porte sur les observations complètes pour les covariables, notamment les CD4, et peut donc concerner une population légèrement différente de celle du calcul brut.
Dans le modèle de Cox, le HR de l’AZT pour l’infection était de 0.66 [IC à 95 % : 0.44–0.99 ; p = 0.044]. Cette estimation est statistiquement compatible avec une réduction du taux instantané d’infection. Ainsi, le RR et le HR vont dans la même direction : l’AZT est associé à moins d’infections cumulées et à une survenue plus lente de l’infection pendant le suivi.
Le RR et le HR ne répondent toutefois pas à la même question :
Le HR de décès associé à l’AZT était de 0.65 [IC à 95 % : 0.43–1.00 ; p = 0.051]. L’estimation est orientée vers une réduction du taux instantané de décès, mais sans preuve statistique formelle au seuil de 5 %. Les données suggèrent donc un bénéfice possible sur la survie, mais la précision de l’estimation doit être examinée avant de conclure à un effet démontré sur la mortalité.
L’infection VIH est susceptible de se situer sur le chemin causal entre l’AZT et le décès. Pour cette raison, elle n’a pas été introduite comme covariable dans le modèle principal de mortalité : l’objectif était d’estimer l’effet total du traitement, direct et indirect.
Dans l’ensemble, les estimations vont majoritairement dans le sens d’un bénéfice de l’AZT :
Les analyses de sensibilité permettent enfin de vérifier si la conclusion principale reste stable lorsque différentes hypothèses sont appliquées aux statuts VIH indéterminés. La conclusion la plus fiable doit reposer sur la convergence entre le RR brut, le RR ajusté, le HR d’infection, les analyses stratifiées et les scénarios de sensibilité, plutôt que sur une seule p-value.
Dans l’article principal, la probabilité d’infection à 6 mois estimée par Kaplan-Meier était de 18,0 % dans le groupe zidovudine et de 27,5 % dans le groupe placebo, soit une efficacité relative publiée de 38 %. L’extrait pédagogique donne une estimation de même direction, mais moins marquée et moins précise, ce qui peut s’expliquer par la définition simplifiée de l’issue, la durée de suivi disponible et le fait que la base ne contient pas l’ensemble des informations du protocole original.
Pour la mortalité, la publication à 18 mois rapportait un effet du traitement qui variait au cours du temps, avec un hazard relatif inférieur à 1 au début du suivi. Le HR unique estimé dans le présent script est donc une synthèse pédagogique et doit être interprété après vérification de l’hypothèse des risques proportionnels. De même, l’analyse publiée à 24 mois utilisait des méthodes adaptées à l’infection connue par intervalle et montrait que l’efficacité à long terme dépendait fortement du niveau de CD4 maternel.
Dabis F, Msellati P, Meda N, et al. 6-month efficacy, tolerance, and acceptability of a short regimen of oral zidovudine to reduce vertical transmission of HIV in breastfed children in Côte d’Ivoire and Burkina Faso: a double-blind placebo-controlled multicentre trial. Lancet. 1999;353(9155):786–792. doi:10.1016/S0140-6736(98)11046-2.
DITRAME ANRS 049 Study Group. 15-month efficacy of maternal oral zidovudine to decrease vertical transmission of HIV-1 in breastfed African children. Lancet. 1999;354:2050–2051.
Dabis F, Elenga N, Meda N, et al. 18-month mortality and perinatal exposure to zidovudine in West Africa. AIDS. 2001;15(6):771–779.
Leroy V, Montcho C, Manigart O, et al. Maternal plasma viral load, zidovudine and mother-to-child transmission of HIV-1 in Africa: DITRAME ANRS 049a trial. AIDS. 2001;15(4):517–522.
Leroy V, Karon JM, Alioum A, et al. Twenty-four month efficacy of a maternal short-course zidovudine regimen to prevent mother-to-child transmission of HIV-1 in West Africa. AIDS. 2002;16(4):631–641.
Leroy V, Karon JM, Alioum A, et al. Postnatal transmission of HIV-1 after a maternal short-course zidovudine peripartum regimen in West Africa. AIDS. 2003;17(10):1493–1501.