diff --git a/locale/fr/episodes/create-forecast.Rmd b/locale/fr/episodes/create-forecast.Rmd new file mode 100644 index 00000000..43a49c0e --- /dev/null +++ b/locale/fr/episodes/create-forecast.Rmd @@ -0,0 +1,540 @@ +--- +title: Établir des prévisions à court terme +teaching: 30 +exercises: 30 +editor_options: + chunk_output_type: inline +--- + +```{r setup, echo=FALSE, warning=FALSE, message=FALSE} +withr::local_options(base::list(mc.cores = 4)) +``` + +:::::::::::::::::::::::::::::::::::::: questions + +- Comment créer des prévisions à court terme à partir de données de cas ? +- Comment tenir compte des rapports incomplets dans les prévisions ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Apprenez à faire des prévisions de cas à l'aide du progiciel R `EpiNow2` +- Apprenez à inclure un processus d'observation dans l'estimation + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +- Compléter le tutoriel [Quantifier la transmission](../episodes/quantify-transmissibility.md) + +Les apprenants doivent se familiariser avec les dépendances conceptuelles suivantes avant de suivre ce tutoriel : + +**Statistiques**: distributions de probabilités, principe de [Analyse bayésienne](../learners/reference.md#bayesian). + +**Théorie des épidémies**: [Nombre de reproduction effectif](../learners/reference.md#effectiverepro). + +::::::::::::::::::::::::::::::::: + +## Introduction + +À partir des données relatives aux cas d'une épidémie, il est possible d'estimer le nombre actuel et futur de cas en tenant compte à la fois des retards et de l'évolution de l'épidémie. +de la déclaration et de la sous-déclaration. Pour faire des prévisions sur l'évolution future de l'épidémie, nous devons faire une hypothèse sur la façon dont les cas sont déclarés. +observations faites jusqu'à présent sont liées à ce que nous attendons à l'avenir. La façon la plus simple de procéder est de supposer qu'il n'y a pas de changement, c'est-à-dire que le nombre de reproduction reste le même à l'avenir que celui qui a été observé en dernier lieu. Dans ce tutoriel, nous créerons des [prévisions](../learners/reference.md#forecast) en supposant que le nombre de reproductions restera le même que son estimation à la dernière date pour laquelle des données étaient disponibles. + +Dans ce tutoriel, nous allons apprendre à utiliser la fonction `{EpiNow2}` pour prévoir les cas en tenant compte des observations incomplètes et pour prévoir les observations secondaires telles que les décès. + +Nous utiliserons le tuyau `%>%` pour connecter des fonctions, donc appelons aussi l'opérateur `{tidyverse}` au paquetage : + +```r +library(EpiNow2) +library(tidyverse) +``` + +```{r, echo=FALSE, eval=TRUE, message=FALSE, warning=FALSE} +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### Le double point-virgule + +Le double point-virgule `::` dans R vous permettent d'appeler une fonction spécifique d'un paquetage sans charger le paquetage entier dans l'environnement actuel. + +Par exemple, vous pouvez appeler une fonction spécifique d'un paquet sans charger le paquet entier dans l'environnement actuel, `dplyr::filter(data, condition)` utilise `filter()` à partir de l'outil `{dplyr}` paquet. + +Cela nous permet de nous souvenir des fonctions du paquet et d'éviter les conflits d'espace de noms. + +::::::::::::::::::: + +## Créez une prévision à court terme + +La fonction `epinow()` décrite dans le [quantifier la transmission](../episodes/quantify-transmissibility.md) est une enveloppe pour les fonctions : + +- `estimate_infections()` utilisées pour estimer le nombre de cas par date d'infection. +- `forecast_infections()` utilisé pour simuler des infections à l'aide d'un ajustement existant (estimation) aux cas observés. + +Utilisons le même code que celui utilisé dans [quantifier la transmission](../episodes/quantify-transmissibility.md) pour obtenir les données d'entrée, les délais et les priorités : + +```{r, echo=TRUE} +# Read cases dataset +cases <- incidence2::covidregionaldataUK %>% + # use {tidyr} to preprocess missing values + tidyr::replace_na(base::list(cases_new = 0)) %>% + # use {incidence2} to compute the daily incidence + incidence2::incidence( + date_index = "date", + counts = "cases_new", + count_values_to = "confirm", + date_names_to = "date", + complete_dates = TRUE + ) %>% + dplyr::select(-count_variable) # Drop count_variable as no longer needed + +# Incubation period +incubation_period_fixed <- EpiNow2::Gamma( + mean = 4, + sd = 2, + max = 20 +) + +# Log-tranformed mean +log_mean <- EpiNow2::convert_to_logmean(mean = 2, sd = 1) + +# Log-transformed std +log_sd <- EpiNow2::convert_to_logsd(mean = 2, sd = 1) + +# Reporting delay +reporting_delay_fixed <- EpiNow2::LogNormal( + mean = log_mean, + sd = log_sd, + max = 10 +) + +# Generation time +generation_time_fixed <- EpiNow2::LogNormal( + mean = 3.6, + sd = 3.1, + max = 20 +) + +# define Rt prior distribution +rt_prior <- EpiNow2::rt_opts(prior = EpiNow2::LogNormal(mean = 2, sd = 2)) +``` + +Nous pouvons maintenant extraire les prévisions à court terme à l'aide de : + +```{r, message=FALSE, warning=FALSE, eval=TRUE} +# Assume we only have the first 90 days of this data +reported_cases <- cases %>% + dplyr::slice(1:90) + +# Estimate and forecast +estimates <- EpiNow2::epinow( + data = reported_cases, + generation_time = EpiNow2::generation_time_opts(generation_time_fixed), + delays = EpiNow2::delay_opts(incubation_period_fixed + reporting_delay_fixed), + rt = rt_prior +) +``` + +::::::::::::::::::::::::::::::::: callout + +### N'attendez pas que cela se termine ! + +Ce dernier morceau peut prendre 10 minutes à s'exécuter. Continuez à lire cet épisode du tutoriel pendant qu'il s'exécute en arrière-plan. Pour plus d'informations sur le temps de calcul, lisez la section "Inférence bayésienne à l'aide de Stan" dans la section [quantifier la transmission](../episodes/quantify-transmissibility.md) de quantification de la transmission. + +::::::::::::::::::::::::::::::::: + +Nous pouvons visualiser les estimations du nombre de reproductions effectives et du nombre estimé de cas à l'aide de `plot()`. Les estimations sont réparties en trois catégories : + +- **Estimation** (vert) : utilise toutes les données, + +- **Estimation basée sur des données partielles** (orange) : contient un degré d'incertitude plus élevé car ces estimations sont basées sur moins de données, + +- **Prévision** (violet) : prévisions pour l'avenir. + +```{r} +plot(estimates) +``` + +### Prévision avec des observations incomplètes + +Dans le cadre de la [quantifier la transmission](../episodes/quantify-transmissibility.md) nous avons tenu compte des délais de déclaration. Dans l'épisode de quantification de la transmission, nous avons tenu compte des retards de déclaration. `EpiNow2` nous pouvons également tenir compte des observations incomplètes, car dans la réalité, 100 % des cas ne sont pas déclarés. +Nous passerons un argument supplémentaire appelé `obs` dans le `epinow()` pour définir un modèle d'observation. Le format de `obs` est défini par la fonction `obs_opt()` (voir `?EpiNow2::obs_opts` pour plus de détails). + +Supposons que nous croyons que les données de l'épidémie COVID-19 dans l'article `cases` n'incluent pas tous les cas déclarés. Nous estimons que seuls 40 % des cas réels sont déclarés. Pour spécifier cela dans le modèle d'observation, nous devons passer un facteur d'échelle avec une moyenne et un écart type. Si nous supposons que 40 % des cas sont déclarés (avec un écart-type de 1 %), nous spécifions alors le facteur d'échelle `scale` à `obs_opts()` comme suit : + +```{r} +obs_scale <- EpiNow2::Normal(mean = 0.4, sd = 0.01) +``` + +Pour exécuter le cadre d'inférence avec ce processus d'observation, nous ajoutons `obs = obs_opts(scale = obs_scale)` aux arguments d'entrée de `epinow()`: + +```{r, message=FALSE, warning=FALSE, eval=TRUE} +# Define observation model +obs_scale <- EpiNow2::Normal(mean = 0.4, sd = 0.01) + +# Assume we only have the first 90 days of this data +reported_cases <- cases %>% + dplyr::slice(1:90) + +# Estimate and forecast +estimates <- EpiNow2::epinow( + data = reported_cases, + generation_time = EpiNow2::generation_time_opts(generation_time_fixed), + delays = EpiNow2::delay_opts(incubation_period_fixed + reporting_delay_fixed), + rt = rt_prior, + # Add observation model + obs = EpiNow2::obs_opts(scale = obs_scale) +) + +base::summary(estimates) +``` + +Les estimations des mesures de transmission telles que le nombre de reproduction efficace et le taux de croissance sont similaires (ou de même valeur) par rapport à la situation où nous n'avons pas tenu compte des observations incomplètes (voir [quantifier l'épisode de transmission](../episodes/quantify-transmissibility.md) dans la section "Recherche d'estimations"). Cependant, le nombre de nouveaux cas confirmés par date d'infection a considérablement changé d'ampleur pour refléter l'hypothèse selon laquelle seuls 40 % des cas sont déclarés. + +Nous pouvons également changer la distribution par défaut de Binomiale négative à Poisson, supprimer l'effet de semaine par défaut (qui tient compte des schémas hebdomadaires de déclaration) et bien d'autres choses encore. Voir `?EpiNow2::obs_opts` pour plus de détails. + +::::::::::::::::::::::::::: discussion + +### Quelles sont les implications de ce changement ? + +- Comparer différents pourcentages d'observations % +- En quoi diffèrent-ils en ce qui concerne le nombre d'infections estimées ? +- Quelles sont les implications de ce changement pour la santé publique ? + +::::::::::::::::::::::::::: + +## Prévision des observations secondaires + +`EpiNow2` L'outil de prévision de l'épidémie de COVID-19 permet également d'estimer et de prévoir les observations secondaires, par exemple les décès et les hospitalisations, à partir d'une observation primaire, par exemple le nombre de cas. Nous illustrerons ici comment prévoir le nombre de décès découlant des cas observés de COVID-19 dans les premiers stades de l'épidémie au Royaume-Uni. + +Tout d'abord, nous devons formater nos données de manière à ce qu'elles comportent les colonnes suivantes : + +- `date` la date (en tant qu'objet date, voir `?is.Date()`), +- `primary`: nombre d'observations primaires à cette date, dans cet exemple **cas**, +- `secondary`: nombre de dates d'observations secondaires, dans cet exemple **décès**. + +```{r} +reported_cases_deaths <- incidence2::covidregionaldataUK %>% + # use {tidyr} to preprocess missing values + tidyr::replace_na(base::list(cases_new = 0, deaths_new = 0)) %>% + # use {incidence2} to compute the daily incidence + incidence2::incidence( + date_index = "date", + counts = c(primary = "cases_new", secondary = "deaths_new"), + date_names_to = "date", + complete_dates = TRUE + ) %>% + # rearrange to wide format for {EpiNow2} + pivot_wider(names_from = count_variable, values_from = count) +``` + +```{r, echo=FALSE, fig.cap="Distribution of secondary cases (deaths). We will drop the first 30 days with no observed deaths. We will use the deaths between day 31 and day 60 to estimate the secondary observations. We will forecast deaths from day 61 to day 90."} + +# distribution of secondary observations +estimate_forecast <- reported_cases_deaths %>% + slice_head(n = 90) %>% + identity() + +ggplot2::ggplot() + + geom_col( + data = estimate_forecast %>% slice(1:60), + mapping = aes(x = date, y = secondary), + fill = "black" + ) + + geom_col( + data = estimate_forecast %>% slice(61:90), + mapping = aes(x = date, y = secondary), + fill = "gray80" + ) + + geom_vline(aes(xintercept = ymd(20200131)), linetype = 2) + + geom_vline(aes(xintercept = ymd(20200228)), linetype = 2) + + geom_vline(aes(xintercept = ymd(20200329)), linetype = 2) + + geom_vline(aes(xintercept = ymd(20200428)), linetype = 2) + + annotate( + "text", label = "drop", + x = ymd(20200131) %m+% days(5), + y = 2000, + size = 8, + colour = "red" + ) + + annotate( + "text", label = "estimate", + x = ymd(20200228) %m+% days(10), + y = 2000, + size = 8, + colour = "red" + ) + + annotate( + "text", label = "forecast", + x = ymd(20200329) %m+% days(10), + y = 2000, + size = 8, + colour = "red" + ) + + NULL +``` + +En utilisant les données sur les cas et les décès entre le 31e et le 60e jour, nous estimerons la relation entre les observations primaires et secondaires à l'aide de la méthode suivante `estimate_secondary()` puis nous prévoyons les décès futurs à l'aide de `forecast_secondary()`. Pour plus de détails sur le modèle, voir le [documentation du modèle](https://epiforecasts.io/EpiNow2/dev/articles/estimate_secondary.html). + +Nous devons spécifier le type d'observation en utilisant `type` en `secondary_opts()` Les options sont les suivantes : + +- "incidence" : les observations secondaires découlent d'observations primaires antérieures, c'est-à-dire de décès survenus à la suite de cas enregistrés. +- "prévalence" : les observations secondaires résultent d'une combinaison d'observations primaires actuelles et d'observations secondaires antérieures, c'est-à-dire l'utilisation des lits d'hôpitaux à partir des admissions actuelles à l'hôpital et de l'utilisation passée des lits d'hôpitaux. + +Dans cet exemple, nous spécifions `secondary_opts(type = "incidence")`. Voir `?EpiNow2::secondary_opts` pour plus de détails. + +La dernière donnée clé est la distribution des délais entre les observations primaires et secondaires. Il s'agit ici du délai entre le signalement du cas et le décès. Nous supposons que ce délai suit une distribution gamma avec une moyenne de 14 jours et un écart-type de 5 jours. `{epiparameter}` pour [accéder aux délais épidémiologiques](https://epiverse-trace.github.io/tutorials-early/delays-reuse.html)). L'utilisation de `Gamma()` nous spécifions une distribution gamma fixe. + +Il existe d'autres fonctions d'entrée pour `estimate_secondary()` qui peuvent être spécifiées, y compris l'ajout d'un processus d'observation, voir `?EpiNow2::estimate_secondary` pour plus de détails sur ces options. + +Pour trouver l'ajustement du modèle entre les cas et les décès : + +```{r, warning=FALSE, message=FALSE} +# Estimate from day 31 to day 60 of this data +cases_to_estimate <- reported_cases_deaths %>% + slice(31:60) + +# Delay distribution between case report and deaths +delay_report_to_death <- EpiNow2::Gamma( + mean = EpiNow2::Normal(mean = 14, sd = 0.5), + sd = EpiNow2::Normal(mean = 5, sd = 0.5), + max = 30 +) + +# Estimate secondary cases +estimate_cases_to_deaths <- EpiNow2::estimate_secondary( + data = cases_to_estimate, + secondary = EpiNow2::secondary_opts(type = "incidence"), + delays = EpiNow2::delay_opts(delay_report_to_death) +) +``` + +::::::::::::::::::::::::::::::::::::: callout + +### Soyez prudent avec l'échelle de temps + +Au début d'une épidémie, il peut y avoir des changements substantiels dans les tests et les rapports. Si les tests changent d'un mois à l'autre, l'ajustement du modèle sera biaisé. Vous devez donc être prudent quant à l'échelle temporelle des données utilisées dans l'ajustement du modèle et les prévisions. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +Nous représentons l'ajustement du modèle (rubans ombrés) avec les observations secondaires (diagramme à barres) et les observations primaires (ligne pointillée) comme suit : + +```{r} +plot(estimate_cases_to_deaths, primary = TRUE) +``` + +Pour utiliser cet ajustement de modèle afin de prévoir les décès, nous passons un cadre de données composé de l'observation primaire (cas) pour les dates non utilisées dans l'ajustement de modèle. + +*Remarque : dans cet épisode, nous utilisons des données dont nous connaissons les décès et les cas, nous créons donc une base de données en extrayant les cas. Mais dans la pratique, il s'agirait d'un ensemble de données différent composé uniquement de cas.* + +```{r} +# Forecast from day 61 to day 90 +cases_to_forecast <- reported_cases_deaths %>% + dplyr::slice(61:90) %>% + dplyr::mutate(value = primary) +``` + +Pour faire des prévisions, nous utilisons l'ajustement du modèle `estimate_cases_to_deaths`: + +```{r, warning=FALSE, message=FALSE} +# Forecast secondary cases +deaths_forecast <- EpiNow2::forecast_secondary( + estimate = estimate_cases_to_deaths, + primary = cases_to_forecast +) + +plot(deaths_forecast) +``` + +Le graphique montre les observations secondaires prévues (décès) pour les dates pour lesquelles nous avons enregistré des cas. +Il est également possible de prévoir les décès à l'aide des cas prévus ; dans ce cas, vous devez spécifier `primary` comme `estimates` sortie de `estimate_infections()`. + +:::::::::::::::::::::::::: callout + +### Intervalles crédibles + +Dans tous les cas `{EpiNow2}` les régions ombrées reflètent les intervalles de crédibilité de 90 %, 50 % et 20 %, dans l'ordre du plus clair au plus foncé. + +:::::::::::::::::::::::::: + +## Défi : Analyse de l'épidémie d'Ebola + +::::::::::::::::::::::::::::::::::::: challenge + +Téléchargez le fichier [`ebola_cases.csv`](data/ebola_cases.csv) et lisez-le dans R. Les données simulées sont la date d'apparition des symptômes et le nombre de cas confirmés aux premiers stades de l'épidémie d'Ebola en Sierra Leone en 2014. + +En utilisant les 3 premiers mois (120 jours) de données : + +1. Estimez si les cas augmentent ou diminuent au 120e jour de l'épidémie. +2. Tenir compte d'une capacité d'observation de 80 % des cas. +3. Établissez une prévision à deux semaines du nombre de cas. + +Vous pouvez utiliser les valeurs de paramètres suivantes pour la (les) distribution(s) des délais et la distribution du temps de génération. + +- Période d'incubation : Log normal$(2.487,0.330)$ ([Eichner et al. 2011](https://doi.org/10.1016/j.phrp.2011.04.001) via `{epiparameter}`) +- Temps de génération : Gamma$(15.3, 10.1)$ ([Équipe d'intervention de l'OMS contre Ebola 2014](https://www.nejm.org/doi/full/10.1056/NEJMoa1411100)) + +Vous pouvez inclure une certaine incertitude autour de la moyenne et de l'écart-type de ces distributions. + +::::::::::::::::: hint + +Nous utilisons le nombre de reproduction effectif et le taux de croissance pour estimer si les cas augmentent ou diminuent. + +Nous pouvons utiliser le `horizon` à l'intérieur de la `forecast_opts()` fourni pour `forecast` argument dans `epinow()` pour étendre la durée de la prévision. La valeur par défaut est de sept jours. + +Assurez-vous que les données sont au bon format : + +- `date` la date (en tant qu'objet de date, voir `?is.Date()`), +- `confirm` nombre de cas confirmés à cette date. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +### SOLUTION + +Pour estimer le nombre de reproductions effectives et le taux de croissance, nous utiliserons la fonction `epinow()`. + +Les données étant constituées de la date d'apparition des symptômes, il nous suffit de spécifier une distribution des retards pour la période d'incubation et le temps de génération. + +Nous spécifions les distributions avec une certaine incertitude autour de la moyenne et de l'écart-type de la distribution log-normale pour la période d'incubation et de la distribution Gamma pour le temps de génération. + +```{r, eval=TRUE, echo=TRUE, warning=FALSE, message=FALSE} +epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "incubation" +) %>% + epiparameter::parameter_tbl() + +ebola_eichner <- epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "incubation", + author = "Eichner" +) + +ebola_eichner_parameters <- epiparameter::get_parameters(ebola_eichner) + +ebola_incubation_period <- EpiNow2::LogNormal( + meanlog = EpiNow2::Normal( + mean = ebola_eichner_parameters["meanlog"], + sd = 0.5 + ), + sdlog = EpiNow2::Normal( + mean = ebola_eichner_parameters["sdlog"], + sd = 0.5 + ), + max = 20 +) + +ebola_generation_time <- EpiNow2::Gamma( + mean = EpiNow2::Normal(mean = 15.3, sd = 0.5), + sd = EpiNow2::Normal(mean = 10.1, sd = 0.5), + max = 30 +) +``` + +Nous lisons les données en utilisant `readr::read_csv()`. Cette fonction reconnaît que la colonne `date` est une `` vecteur de classe. + +```{r, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE} +# read data from the tutorial repository R project +ebola_cases_raw <- readr::read_csv(file.path("data", "ebola_cases.csv")) +``` + +```{r, eval=FALSE, echo=TRUE, warning=FALSE, message=FALSE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +ebola_cases_raw <- readr::read_csv( + here::here("data", "raw-data", "ebola_cases.csv") +) +``` + +Prétraiter et adapter les données brutes pour `{EpiNow2}`: + +```{r} +ebola_cases <- ebola_cases_raw %>% + # use {tidyr} to preprocess missing values + tidyr::replace_na(base::list(confirm = 0)) %>% + # use {incidence2} to compute the daily incidence + incidence2::incidence( + date_index = "date", + counts = "confirm", + count_values_to = "confirm", + date_names_to = "date", + complete_dates = TRUE + ) %>% + dplyr::select(-count_variable) + +dplyr::as_tibble(ebola_cases) +``` + +Nous définissons un modèle d'observation pour mettre à l'échelle le nombre estimé et prévu de nouvelles infections : + +```{r} +# Define observation model +# mean of 80% and standard deviation of 1% +ebola_obs_scale <- EpiNow2::Normal(mean = 0.8, sd = 0.01) +``` + +Comme nous voulons également créer une prévision sur deux semaines, nous spécifions `horizon = 14` pour prévoir 14 jours au lieu des 7 jours par défaut. + +```{r, eval=TRUE, echo=TRUE, message=FALSE} +ebola_estimates <- EpiNow2::epinow( + data = ebola_cases %>% dplyr::slice(1:120), # first 3 months of data only + generation_time = EpiNow2::generation_time_opts(ebola_generation_time), + delays = EpiNow2::delay_opts(ebola_incubation_period), + # Add observation model + obs = EpiNow2::obs_opts(scale = ebola_obs_scale), + # horizon needs to be 14 days to create two week forecast (default is 7 days) + forecast = EpiNow2::forecast_opts(horizon = 14) +) + +summary(ebola_estimates) +``` + +Le numéro de reproduction effectif $R_t$ (à la dernière date des données) est de `r summary(ebola_estimates)[measure=="Effective reproduction no."]$estimate`. Le taux de croissance exponentiel du nombre de cas est de `r summary(ebola_estimates)[measure=="Rate of growth"]$estimate`. + +Visualisez les estimations : + +```{r, eval=FALSE, echo=TRUE} +plot(ebola_estimates) +``` + +::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: callout + +### Prévision avec des estimations de $R_t$ + +Par défaut, les prévisions à court terme sont créées en utilisant la dernière estimation du nombre de reproductions $R_t$. Cette estimation étant basée sur des données partielles, elle présente une grande incertitude. + +Le nombre de reproductions projeté dans le futur peut être remplacé par une estimation moins récente, basée sur des données plus nombreuses, à l'aide de `rt_opts()`: + +```{r, eval=FALSE} +EpiNow2::rt_opts(future = "estimate") +``` + +Il en résultera des prévisions moins incertaines (puisqu'elles sont basées sur les données de l $R_t$ avec un intervalle d'incertitude plus étroit), mais les prévisions seront basées sur des estimations moins récentes de $R_t$ et supposeront qu'il n'y a pas eu de changement depuis lors. + +En outre, il est possible de [projeter](../learners/reference.md#projection) la valeur de $R_t$ dans le futur à l'aide d'un modèle générique en fixant `future = "project"`. Comme cette option utilise un modèle pour prévoir la valeur de $R_t$ il en résultera des prévisions plus incertaines que la valeur de `estimate` pour un exemple [voir ici](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections_options.html#projecting-the-reproduction-number-with-the-gaussian-process). + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Résumé + +`EpiNow2` peut être utilisé pour créer des prévisions à court terme et pour estimer la relation entre différents résultats. Il existe une série d'options de modèle qui peuvent être mises en œuvre pour différentes analyses, y compris l'ajout d'un processus d'observation pour tenir compte des déclarations incomplètes. Voir le site web de l'Agence européenne pour la sécurité et la santé au travail. [vignette](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections_options.html) pour plus de détails sur les différentes options de modèle dans `EpiNow2` qui ne sont pas abordées dans ces tutoriels. + +::::::::::::::::::::::::::::::::::::: keypoints + +- Nous pouvons créer des prévisions à court terme en faisant des hypothèses sur le comportement futur du nombre de reproduction. +- Les estimations peuvent tenir compte des déclarations de cas incomplètes. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/fr/episodes/delays-access.Rmd b/locale/fr/episodes/delays-access.Rmd new file mode 100644 index 00000000..4c68c1b3 --- /dev/null +++ b/locale/fr/episodes/delays-access.Rmd @@ -0,0 +1,641 @@ +--- +title: Accéder aux distributions des retards épidémiologiques +teaching: 20 +exercises: 10 +editor_options: + chunk_output_type: inline +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- Comment accéder aux distributions des délais des maladies à partir d'une base de données préétablie pour les utiliser dans l'analyse ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Obtenez les délais à partir d'une base de données de recherche documentaire avec `{epiparameter}`. +- Obtenez les paramètres de distribution et les statistiques sommaires des distributions de retards. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +Cet épisode nécessite que vous soyez familier avec : + +**la science des données** Programmation de base avec R. + +**Théorie des épidémies** La théorie des épidémies est basée sur les paramètres épidémiologiques, les périodes de la maladie, telles que la période d'incubation, le temps de génération et l'intervalle sériel. + +::::::::::::::::::::::::::::::::: + +## Introduction + +Les maladies infectieuses suivent un cycle infectieux qui comprend généralement les phases suivantes : période présymptomatique, période symptomatique et période de guérison, comme le décrivent leurs [histoire naturelle](../learners/reference.md#naturalhistory). Ces périodes peuvent être utilisées pour comprendre la dynamique de la transmission et informer les interventions de prévention et de contrôle des maladies. + +![Définition des périodes clés. A partir de [Xiang et al, 2021](https://www.sciencedirect.com/science/article/pii/S2468042721000038)](fig/time-periods.jpg) + +::::::::::::::::: callout + +### Définitions + +Regardez le [glossaire](../learners/reference.md) pour connaître les définitions de toutes les périodes de la figure ci-dessus ! + +::::::::::::::::::::::::: + +Toutefois, au début d'une épidémie, les efforts visant à comprendre l'épidémie et les implications pour la lutte peuvent être retardés par l'absence d'un moyen facile d'accéder aux paramètres clés de la maladie en question ([Nash et al., 2023](https://mrc-ide.github.io/epireview/)). Des projets tels que `{epiparameter}` et `{epireview}` construisent des catalogues en ligne en suivant des protocoles de synthèse de la littérature qui peuvent aider à informer l'analyse et à paramétrer les modèles en fournissant une bibliothèque de paramètres épidémiologiques précédemment estimés à partir d'épidémies passées. + + + +Pour illustrer l'utilisation de l'outil `{epiparameter}` R dans votre pipeline d'analyse, notre objectif dans cet épisode sera d'accéder à un ensemble spécifique de paramètres épidémiologiques de la littérature, au lieu d'extraire des articles et de les copier-coller à la main. Nous les insérerons ensuite dans un `{EpiNow2}` flux de travail d'analyse. + + + +Commençons par charger le fichier `{epiparameter}` paquetage. Nous utiliserons le tube `%>%` pour connecter certaines de ses fonctions, certaines `{tibble}` et `{dplyr}` donc appelons aussi à la fonction `{tidyverse}` paquetage : + +```{r, warning=FALSE, message=FALSE} +library(epiparameter) +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### Le double point-virgule + +Le double point-virgule `::` dans R vous permet d'appeler une fonction spécifique d'un paquetage sans charger l'ensemble du paquetage dans l'environnement actuel. + +Par exemple, vous pouvez appeler une fonction spécifique d'un package sans charger le package entier dans l'environnement actuel, `dplyr::filter(data, condition)` utilise `filter()` à partir de l'outil `{dplyr}` paquet. + +Cela nous permet de nous souvenir des fonctions du paquet et d'éviter les conflits d'espace de noms. + +::::::::::::::::::: + +## Le problème + +Si nous voulons estimer la transmissibilité d'une infection, il est courant d'utiliser un package tel que `{EpiEstim}` ou `{EpiNow2}`. Le paquet `{EpiEstim}` permet d'estimer en temps réel le nombre de reproductions à l'aide des données relatives aux cas dans le temps, reflétant ainsi l'évolution de la transmission en fonction de la date d'apparition des symptômes. Pour estimer la transmission en fonction du moment où les personnes ont été effectivement infectées (plutôt que de l'apparition des symptômes), le logiciel `{EpiNow2}` étend cette idée en la combinant avec un modèle qui tient compte des retards dans les données observées. Les deux logiciels requièrent certaines informations épidémiologiques en entrée. Par exemple, dans `{EpiNow2}` nous utilisons `EpiNow2::Gamma()` pour spécifier un [temps de génération](../learners/reference.md#generationtime) sous la forme d'une distribution de probabilité ajoutant son `mean` l'écart-type (`sd`) et sa valeur maximale (`max`). + +Pour spécifier une valeur `generation_time` qui suit un *Gamma* avec une moyenne $\mu = 4$ écart-type $\sigma = 2$ et une valeur maximale de 20, nous écrivons : + +```r +generation_time <- + EpiNow2::Gamma( + mean = 4, + sd = 2, + max = 20 + ) +``` + +Il est courant que les analystes recherchent manuellement la littérature disponible et copient et collent les résultats de la recherche. **statistiques sommaires** ou les **paramètres de distribution** des publications scientifiques. Une difficulté à laquelle on est souvent confronté est que la présentation des différentes distributions statistiques n'est pas cohérente dans la littérature (par exemple, un article peut ne présenter que la moyenne, plutôt que la distribution sous-jacente complète). `{epiparameter}` L'objectif du projet est de faciliter l'accès à des estimations fiables des paramètres de distribution pour une série de maladies infectieuses, afin qu'elles puissent être facilement mises en œuvre dans les pipelines d'analyse des épidémies. + +Dans cet épisode, nous allons *accéder* les statistiques sommaires du temps de génération pour COVID-19 à partir de la bibliothèque de paramètres épidémiologiques fournie par l'Agence européenne pour la sécurité et la santé au travail (ESA). `{epiparameter}`. Ces paramètres peuvent être utilisés pour estimer la transmissibilité de cette maladie à l'aide de l'outil `{EpiNow2}` dans les épisodes suivants. + +Commençons par examiner le nombre d'entrées actuellement disponibles dans la base de données des **base de données des distributions épidémiologiques** en `{epiparameter}` en utilisant `epiparameter_db()` pour la distribution épidémiologique `epi_name` appelé temps de génération avec la chaîne `"generation"`: + +```{r} +epiparameter::epiparameter_db( + epi_name = "generation" +) +``` + +Dans la bibliothèque des paramètres épidémiologiques, on peut ne pas disposer d'un `"generation"` pour la maladie qui nous intéresse. À la place, nous pouvons consulter le `serial` intervalles pour COVID-19. Voyons ce qu'il faut prendre en compte pour cela ! + +::::::::::::::::: callout + +### Analyse systématique des données relatives aux agents pathogènes prioritaires + +Les données de l'examen systématique des pathogènes prioritaires [`{epireview}` paquet R](https://mrc-ide.github.io/epireview/) contient des paramètres sur Ebola, Marburg et Lassa issus de revues systématiques récentes. D'autres agents pathogènes prioritaires sont prévus pour les prochaines versions. Jetez un coup d'œil à [cette vignette](https://epiverse-trace.github.io/epiparameter/articles/data_from_epireview.html) pour plus d'informations sur l'utilisation de ces paramètres avec `{epiparameter}`. + +::::::::::::::::::::::::: + +## Temps de génération vs intervalle série + +Le temps de génération, conjointement avec le nombre de reproduction ($R$), peut fournir des indications précieuses sur le taux de croissance probable de l'épidémie et, partant, sur la mise en œuvre de mesures de lutte. Plus la valeur de $R$ et/ou plus le temps de génération est court, plus le nombre de nouvelles infections attendues par jour est élevé, et donc plus l'incidence des cas de maladie augmentera rapidement. + +![Vidéo du MRC Centre for Global Infectious Disease Analysis, Ep 76. Science In Context - Epi Parameter Review Group avec le Dr Anne Cori (27-07-2023) at ](fig/reproduction-generation-time.png) + +Pour calculer le nombre effectif de reproduction ($R_{t}$), le *temps de génération* (c'est-à-dire le délai entre une infection et la suivante) est souvent approximée par la distribution des temps de génération. [intervalle sériel](../learners/reference.md#serialinterval) (c'est-à-dire le délai entre l'apparition des symptômes chez l'infecteur et l'apparition des symptômes chez l'infecté). +Cette approximation est fréquemment utilisée car il est plus facile d'observer et d'enregistrer l'apparition des symptômes que le moment exact de l'infection. + +![Schéma de la relation entre les différentes périodes de transmission entre un infecteur et un infecté dans une paire de transmission. La fenêtre d'exposition est définie comme l'intervalle de temps entre l'exposition au virus et la fenêtre de transmission est définie comme l'intervalle de temps pour la transmission ultérieure par rapport à la durée de l'infection ([Chung Lau et al., 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)).](fig/serial-interval-observed.jpeg) + +Cependant, l'utilisation de la *intervalle sériel* comme approximation de l'intervalle *temps de génération* est plus appropriée pour les maladies dans lesquelles l'infectiosité commence après l'apparition des symptômes ([Chung Lau et al., 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)). Dans les cas où l'infectiosité commence avant l'apparition des symptômes, les intervalles sériels peuvent avoir des valeurs négatives, ce qui se produit lorsque l'infecté développe des symptômes avant l'infecteur dans une paire de transmission ([Nishiura et al., 2020](https://www.ijidonline.com/article/S1201-9712\(20\)30119-3/fulltext#gr2)). + +::::::::::::::::: callout + +### Des délais moyens aux distributions de probabilité + +Si nous mesurons les *intervalle sériel* dans des données réelles, nous constatons généralement que toutes les paires de cas n'ont pas le même délai d'apparition. Nous pouvons également observer cette variabilité pour d'autres délais épidémiologiques clés, notamment le délai d'apparition de la maladie. [la période d'incubation](../learners/reference.md#incubation) et [période infectieuse](../learners/reference.md#infectiousness). + +![Intervalles sériels des paires de cas possibles dans (a) COVID-19 et (b) MERS-CoV. Les paires représentent un infecteur présumé et son contaminé présumé en fonction de la date d'apparition des symptômes ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#fig6)).](fig/serial-interval-pairs.jpg) + +Pour résumer ces données relatives aux périodes individuelles et aux paires, il est donc utile de quantifier les **distribution statistique** des retards qui correspond le mieux aux données, plutôt que de se concentrer sur la moyenne ([McFarland et al., 2023](https://www.eurosurveillance.org/content/10.2807/1560-7917.ES.2023.28.27.2200806)). + + + +![Distribution d'intervalles sériels ajustée pour (a) COVID-19 et (b) MERS-CoV sur la base des paires de transmission signalées en Arabie saoudite. Nous avons ajusté trois distributions couramment utilisées, les distributions Log normal, Gamma et Weibull, respectivement ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#fig5)).](fig/seria-interval-fitted-distributions.jpg) + +Les distributions statistiques sont résumées en fonction de leur **statistiques sommaires** comme la *l'emplacement* (moyenne et percentiles) et *l'étendue* (variance ou écart-type) de la distribution, ou avec leur **paramètres de distribution** qui renseignent sur la *forme* (forme et taux/échelle) de la distribution. Ces valeurs estimées peuvent être rapportées avec leur **incertitude** (intervalles de confiance à 95 %). + +| Gamma | moyenne | forme | taux/échelle | +| :--------- | :--------------- | :-------------- | :-------------- | +| MERS-CoV | 14\.13(13.9-14.7) | 6\.31(4.88-8.52) | 0\.43(0.33-0.60) | +| COVID-19 | 5\.1(5.0-5.5) | 2\.77(2.09-3.88) | 0\.53(0.38-0.76) | + +| Weibull | moyenne | forme | taux/échelle | +| :--------- | :--------------- | :-------------- | :-------------- | +| MERS-CoV | 14\.2(13.3-15.2) | 3\.07(2.64-3.63) | 16\.1(15.0-17.1) | +| COVID-19 | 5\.2(4.6-5.9) | 1\.74(1.46-2.11) | 5\.83(5.08-6.67) | + +| Log normal | moyenne | moyenne-log | sd-log | +| :--------- | :--------------- | :-------------- | :-------------- | +| MERS-CoV | 14\.08(13.1-15.2) | 2\.58(2.50-2.68) | 0\.44(0.39-0.5) | +| COVID-19 | 5\.2(4.2-6.5) | 1\.45(1.31-1.61) | 0\.63(0.54-0.74) | + +Tableau : Estimations des intervalles de série à l'aide des distributions Gamma, Weibull et Log Normal. Les intervalles de confiance à 95 % pour les paramètres de forme et d'échelle (logmoy et sd pour Log Normal) sont indiqués entre parenthèses ([Althobaity et al, 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#tbl3)). + +::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Intervalle de série + +Supposons que COVID-19 et le SRAS aient des valeurs de nombre de reproduction similaires et que l'intervalle de série soit proche du temps de génération. + +Étant donné l'intervalle sériel des deux infections dans la figure ci-dessous : + +- Laquelle serait la plus difficile à contrôler ? +- Pourquoi en concluez-vous ainsi ? + +![Intervalle en série des infections par le nouveau coronavirus (COVID-19) superposé à une distribution publiée du SRAS. ([Nishiura et al., 2020](https://www.ijidonline.com/article/S1201-9712\(20\)30119-3/fulltext))](fig/serial-interval-covid-sars.jpg) + +::::::::::::::::: hint + +Le sommet de chaque courbe peut vous renseigner sur l'emplacement de la moyenne de chaque distribution. Une moyenne plus élevée indique un délai plus long entre l'apparition des symptômes chez l'infecteur et l'infecté. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +**Laquelle serait la plus difficile à contrôler ?** + +COVID-19 + +**Pourquoi concluez-vous cela ?** + +L'intervalle sériel moyen de COVID-19 est plus faible. La valeur moyenne approximative de l'intervalle sériel de COVID-19 est d'environ quatre jours, alors que celle du SRAS est d'environ sept jours. Par conséquent, s'il y a beaucoup d'infections dans la population, COVID-19 produira en moyenne plus de nouvelles générations d'infections en moins de temps que le SRAS, en supposant des nombres de reproduction similaires. Cela signifie qu'il faudrait beaucoup plus de ressources pour lutter contre l'épidémie. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::: instructor + +L'objectif de l'évaluation ci-dessus est d'évaluer l'interprétation d'un temps de génération plus long ou plus court. + +:::::::::::::::::::::: + +## Choix des paramètres épidémiologiques + +Dans cette section, nous utiliserons `{epiparameter}` pour obtenir l'intervalle sériel de COVID-19, comme alternative au temps de génération. + +Tout d'abord, voyons combien de paramètres nous avons dans la base de données des distributions épidémiologiques (`epiparameter_db()`) avec l'option `disease` nommé `covid`\-19. Exécutez ce code : + +```{r, eval=FALSE} +epiparameter::epiparameter_db( + disease = "covid" +) +``` + +A partir du `{epiparameter}` nous pouvons utiliser le paquet `epiparameter_db()` pour demander n'importe quel `disease` ainsi qu'une distribution épidémiologique spécifique (`epi_name`). Exécutez cette fonction dans votre console : + +```{r, eval=FALSE} +epiparameter::epiparameter_db( + disease = "COVID", + epi_name = "serial" +) +``` + +Avec cette combinaison de requêtes, nous obtenons plus d'une distribution des délais (parce que la base de données a plusieurs entrées). Cette sortie est un `` objet de classe. + +::::::::::::::::: callout + +### INSENSIBLE À LA CASSE + +`epiparameter_db` est [insensible à la casse](https://dillionmegida.com/p/case-sensitivity-vs-case-insensitivity/#case-insensitivity). Cela signifie que vous pouvez utiliser des chaînes avec des lettres en majuscules ou en minuscules indistinctement. Des chaînes comme `"serial"`, `"serial interval"` ou `"serial_interval"` sont également valables. + +::::::::::::::::::::::::: + +Comme le suggèrent les résultats, pour résumer une `` et obtenir les noms des colonnes de la base de données de paramètres sous-jacente, nous pouvons ajouter l'élément `epiparameter::parameter_tbl()` au code précédent à l'aide du tuyau `%>%`: + +```{r} +epiparameter::epiparameter_db( + disease = "covid", + epi_name = "serial" +) %>% + epiparameter::parameter_tbl() +``` + +Dans le `epiparameter::parameter_tbl()` nous pouvons également trouver différents types de distributions de probabilité (par exemple, Log-normal, Weibull, Normal). + +`{epiparameter}` utilise la fonction `base` R pour les distributions. C'est pourquoi **Log normal** s'appelle `lnorm`. + +::::::::::::::::: spoiler + +### Pourquoi avons-nous une entrée "NA" ? + +Les entrées avec une valeur manquante (``) dans le `prob_distribution` sont *non paramétrés* non paramétrées. Elles présentent des statistiques sommaires (par exemple, une moyenne et un écart type), mais aucune distribution de probabilité n'est spécifiée. Comparez ces deux résultats : + +```{r, eval=FALSE} +# get an object +distribution <- + epiparameter::epiparameter_db( + disease = "covid", + epi_name = "serial" + ) + +distribution %>% + # pluck the first entry in the object class + pluck(1) %>% + # check if object have distribution parameters + is_parameterised() + +# check if the second object +# have distribution parameters +distribution %>% + pluck(2) %>% + is_parameterised() +``` + +### Les entrées paramétrées ont une méthode d'inférence + +Comme indiqué dans `?is_parameterised` une distribution paramétrée est l'entrée à laquelle est associée une distribution de probabilité fournie par une méthode d'inférence. `inference_method` comme indiqué dans `metadata`: + +```{r, eval=FALSE} +distribution[[1]]$metadata$inference_method +distribution[[2]]$metadata$inference_method +distribution[[4]]$metadata$inference_method +``` + +::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Trouvez vos distributions de retard ! + +Prenez 2 minutes pour explorer les `{epiparameter}` bibliothèque. + +**Choisissez** une maladie d'intérêt (par exemple, la grippe, la rougeole, etc.) et une distribution des délais (par exemple, la période d'incubation, le début de la maladie jusqu'au décès, etc.) + +Trouvez : + +- Combien y a-t-il de distributions de délais pour cette maladie ? + +- Combien de types de distribution de probabilité (par exemple, gamma, log normale) y a-t-il pour un délai donné dans cette maladie ? + +Posez la question : + +- Reconnaissez-vous les journaux ? + +- Devrait `{epiparameter}` l'analyse documentaire devrait-elle prendre en compte un autre article ? + +::::::::::::::::: hint + +L'analyse `epiparameter_db()` fonction avec `disease` compte à elle seule le nombre d'entrées comme : + +- études, et +- les répartitions des retards. + +Les `epiparameter_db()` avec `disease` et `epi_name` obtient une liste de toutes les entrées avec : + +- la citation complète, +- la **type** d'une distribution de probabilité, et +- les valeurs des paramètres de la distribution. + +La combinaison de `epiparameter_db()` plus `parameter_tbl()` permet d'obtenir un cadre de données de toutes les entrées avec des colonnes comme : + +- les **type** de la distribution de probabilité par délai, et +- l'auteur et l'année de l'étude. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +Nous avons choisi d'explorer les distributions des retards d'Ebola : + +```{r} +# we expect 16 delay distributions for Ebola +epiparameter::epiparameter_db( + disease = "ebola" +) +``` + +Maintenant, à partir de la sortie de `epiparameter::epiparameter_db()` Quel est un [distribution de la descendance](../learners/reference.md#offspringdist)? + +Nous choisissons de trouver les périodes d'incubation d'Ebola. Cette sortie liste tous les articles et paramètres trouvés. Exécutez-la localement si nécessaire : + +```{r, eval=FALSE} +epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "incubation" +) +``` + +Nous utilisons `parameter_tbl()` pour obtenir un récapitulatif de toutes les données : + +```{r, eval=TRUE} +# we expect 2 different types of delay distributions +# for ebola incubation period +epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "incubation" +) %>% + parameter_tbl() +``` + +Nous trouvons deux types de distributions de probabilités pour cette requête : *log normale* et *gamma*. + +Comment le `{epiparameter}` collecte-t-elle et examine-t-elle la littérature évaluée par les pairs ? Nous vous invitons à lire la vignette sur ["Protocole de collecte et de synthèse des données](https://epiverse-trace.github.io/epiparameter/articles/data_protocol.html)! + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Sélectionnez une distribution unique + +Les `epiparameter::epiparameter_db()` fonctionne comme une fonction de filtrage ou de sous-ensemble. Nous pouvons utiliser la fonction `author` pour conserver `Hiroshi Nishiura` ou l'argument `subset` pour conserver les paramètres des études dont la taille de l'échantillon est supérieure à 10 : + +```{r, eval=FALSE} +epiparameter::epiparameter_db( + disease = "covid", + epi_name = "serial", + author = "Nishiura", + subset = sample_size > 10 +) %>% + epiparameter::parameter_tbl() +``` + +Nous obtenons toujours plus d'un paramètre épidémiologique. Au lieu de cela, nous pouvons définir l'argument `single_epiparameter` à `TRUE` pour n'en obtenir qu'un seul : + +```{r} +epiparameter::epiparameter_db( + disease = "covid", + epi_name = "serial", + single_epiparameter = TRUE +) +``` + +::::::::::::::::: callout + +### Comment fonctionne "single\_epiparameter" ? + +En regardant la documentation d'aide pour `?epiparameter::epiparameter_db()`: + +- Si plusieurs entrées correspondent aux arguments fournis et que `single_epiparameter = TRUE` alors l'entrée paramétrée + `` avec l'entrée *la plus grande taille d'échantillon* sera renvoyée. +- Si plusieurs entrées sont égales après ce tri, l'option *première entrée* de la liste sera retournée. + +Qu'est-ce qu'un *paramétré* ``? Regardez `?is_parameterised`. + +::::::::::::::::::::::::: + +Attribuons cette `` à l'objet de classe `covid_serialint` objet. + +```{r, message=FALSE} +covid_serialint <- + epiparameter::epiparameter_db( + disease = "covid", + epi_name = "serial", + single_epiparameter = TRUE + ) +``` + +Vous pouvez utiliser `plot()` pour `` pour visualiser les objets : + +- le *Fonction de densité de probabilité (PDF)* et +- la *Fonction de distribution cumulative (FDC)*. + +```{r} +# plot object +plot(covid_serialint) +``` + +Avec la `xlim` vous pouvez modifier la durée ou le nombre de jours de la période d'essai. `x` de l'axe. Découvrez à quoi cela ressemble : + +```{r, eval=FALSE} +# plot object +plot(covid_serialint, xlim = c(1, 60)) +``` + +## Extrayez les statistiques récapitulatives + +Nous pouvons obtenir les `mean` et l'écart-type (`sd`) à partir de ce `` plonger dans le `summary_stats` l'objet : + +```{r} +# get the mean +covid_serialint$summary_stats$mean +``` + +Nous avons maintenant un paramètre épidémiologique que nous pouvons réutiliser ! Étant donné que l'objet `covid_serialint` est un `lnorm` ou une distribution log-normale, nous pouvons remplacer le **statistiques sommaires** que nous introduisons dans la base de données `EpiNow2::LogNormal()` dans la fonction + +```r +generation_time <- + EpiNow2::LogNormal( + mean = covid_serialint$summary_stats$mean, # replaced! + sd = covid_serialint$summary_stats$sd, # replaced! + max = 20 + ) +``` + +Dans le prochain épisode, nous apprendrons à utiliser la fonction `{EpiNow2}` pour spécifier correctement les distributions et estimer la transmissibilité. Ensuite, comment utiliser **fonctions de distribution** pour obtenir une valeur maximale (`max`) pour `EpiNow2::LogNormal()` et utiliser `{epiparameter}` dans votre analyse. + +:::::::::::::::::::::::::::::: callout + +### Distributions logarithmiques normales + +Si vous avez besoin de la distribution log-normale **de la distribution logarithmique** au lieu des statistiques sommaires, vous pouvez utiliser `epiparameter::get_parameters()`: + +```{r} +covid_serialint_parameters <- + epiparameter::get_parameters(covid_serialint) + +covid_serialint_parameters +``` + +Cela permet d'obtenir un vecteur de classe `` prêt à être utilisé comme entrée pour n'importe quel autre paquet ! + +Considérez que {EpiNow2} acceptent également les paramètres de distribution comme données d'entrée. Exécutez `?EpiNow2::LogNormal` pour lire les [Distributions de probabilités](https://epiforecasts.io/EpiNow2/reference/Distributions.html) de référence. + +:::::::::::::::::::::::::::::: + +## Défis + +:::::::::::::::::::::::::::::: challenge + +### L'intervalle sériel d'Ebola + +Prenez 1 minute pour : + +Accédez à l'intervalle de série Ebola avec la taille d'échantillon la plus élevée. + +Réponse : + +- Qu'est-ce que le `sd` de la distribution épidémiologique ? + +- Quelle est la `sample_size` utilisée dans cette étude ? + +::::::::: hint + +Utilisez le `$` et l'opérateur tabulation ou pour les explorer sous la forme d'une liste extensible : + +```r +covid_serialint$ +``` + +Utilisez la touche `str()` pour afficher la structure du `` R. + +:::::::::::::::::: + +:::::::::: solution + +```{r, eval=TRUE} +# ebola serial interval +ebola_serial <- + epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "serial", + single_epiparameter = TRUE + ) + +ebola_serial +``` + +```{r, eval=TRUE} +# get the sd +ebola_serial$summary_stats$sd + +# get the sample_size +ebola_serial$metadata$sample_size +``` + +Essayez de visualiser cette distribution en utilisant `plot()`. + +Explorez également tous les autres éléments imbriqués dans l'élément `` à l'intérieur de l'objet. + +Partagez sur : + +- Quels sont les éléments que vous trouvez utiles pour votre analyse ? +- Quels autres éléments souhaiteriez-vous voir figurer dans cet objet ? Comment ? + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::: instructor + +Un élément intéressant est le `method_assess` qui fait référence aux méthodes utilisées par les auteurs de l'étude pour évaluer les biais lors de l'estimation de la distribution des intervalles sériels. + +```{r} +covid_serialint$method_assess +``` + +Nous explorerons ces concepts au fil des épisodes ! + +:::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Le paramètre de gravité d'Ebola + +Un paramètre de gravité tel que la durée de l'hospitalisation pourrait compléter les informations nécessaires sur la capacité d'accueil en cas d'épidémie ([Cori et al.](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + + + +Pour Ebola : + +- Qu'est-ce qui est rapporté ? *estimation ponctuelle* de la durée moyenne des soins de santé et de l'isolement des cas ? + +::::::::::::::::: hint + +Un délai informatif devrait mesurer le temps écoulé entre l'apparition des symptômes et la guérison ou le décès. + +Trouver un moyen d'accéder à l'ensemble `{epiparameter}` base de données et de trouver comment ce délai peut être stocké. Les `parameter_tbl()` est un tableau de données. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE} +# one way to get the list of all the available parameters +epiparameter_db(disease = "all") %>% + parameter_tbl() %>% + as_tibble() %>% + distinct(epi_name) + +ebola_severity <- epiparameter_db( + disease = "ebola", + epi_name = "onset to discharge" +) + +# point estimate +ebola_severity$summary_stats$mean +``` + +Vérifiez que pour certains `{epiparameter}` vous disposerez également de l'élément *incertitude* autour de la *estimation ponctuelle* de chaque statistique sommaire : + +```{r} +# 95% confidence intervals +ebola_severity$summary_stats$mean_ci +# limits of the confidence intervals +ebola_severity$summary_stats$mean_ci_limits +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::: discussion + +### La distribution zoo + +Explorez cette shinyapp appelée **Le zoo de la distribution**! + +Suivez les étapes suivantes pour reproduire la forme de la distribution d'intervalles sériels COVID à partir de `{epiparameter}` (`covid_serialint` objet) : + +1. Accédez au site web de l'application shiny, +2. Allez dans le panneau de gauche, +3. Gardez l'option *Catégorie de distribution*: `Continuous Univariate`, +4. Sélectionnez un nouveau *Type de distribution*: `Log-Normal`, +5. Déplacez le **curseurs** c'est-à-dire l'élément de contrôle graphique qui vous permet d'ajuster une valeur en déplaçant une poignée le long d'une piste ou d'une barre horizontale jusqu'à l'emplacement du curseur. `covid_serialint` paramètres. + +Reproduisez ces éléments à l'aide de l'outil `distribution` et tous ses éléments de liste : `[[2]]`, `[[3]]` et `[[4]]`. Explorez comment la forme d'une distribution change lorsque ses paramètres changent. + +Partagez à propos de : + +- Quelles sont les autres fonctionnalités du site web que vous trouvez utiles ? + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: instructor + +Dans le contexte des interfaces utilisateurs et des interfaces graphiques (GUI), comme le [Zoo de la distribution](https://ben18785.shinyapps.io/distribution-zoo/) une application **glissière** est un élément de contrôle graphique qui permet aux utilisateurs d'ajuster une valeur en déplaçant une poignée le long d'une piste ou d'une barre. Conceptuellement, il permet de sélectionner une valeur numérique dans une plage spécifiée en faisant glisser visuellement un pointeur (la poignée) le long d'un axe continu. + +::::::::::::::::::::::::: + + + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utilisez `{epiparameter}` pour accéder au catalogue des distributions de retards épidémiologiques. +- Utilisez cette fonction pour accéder au catalogue de la littérature sur les distributions de délais épidémiologiques. `epiparameter_db()` pour sélectionner une seule distribution de délais. +- Utilisez cette option pour sélectionner les distributions à retard unique. `parameter_tbl()` pour obtenir une vue d'ensemble des distributions de délais multiples. +- Réutiliser les estimations connues pour une maladie inconnue au début d'une épidémie lorsqu'il n'y a pas de données sur la recherche des contacts. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/fr/episodes/delays-functions.Rmd b/locale/fr/episodes/delays-functions.Rmd new file mode 100644 index 00000000..0ffac86f --- /dev/null +++ b/locale/fr/episodes/delays-functions.Rmd @@ -0,0 +1,790 @@ +--- +title: Utiliser les distributions de retard dans l'analyse +teaching: 20 +exercises: 10 +editor_options: + chunk_output_type: inline +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- Comment réutiliser les retards stockés dans le `{epiparameter}` avec mon pipeline d'analyse existant ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Utilisez les fonctions de distribution pour les distributions continues et discrètes stockées en tant que `` objets. +- Convertissez une distribution continue en distribution discrète à l'aide de la fonction `{epiparameter}`. +- Connecter `{epiparameter}` sorties avec `{EpiNow2}` entrées. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +- Compléter le tutoriel [Quantifier la transmission](https://epiverse-trace.github.io/tutorials-middle/quantify-transmissibility.html) + +Pour cet épisode, vous devez vous familiariser avec + +**Science des données** Programmation de base avec R. + +**Statistiques** : Distributions de probabilités. + +**Théorie des épidémies** La théorie de l'épidémie : paramètres épidémiologiques, périodes de temps, nombre reproductif effectif. + +::::::::::::::::::::::::::::::::: + +## Introduction + +`{epiparameter}` nous aider à *choisir* un ensemble spécifique de paramètres épidémiologiques issus de la littérature, au lieu de les copier/coller. *à la main*: + +```{r, message=FALSE} +covid_serialint <- + epiparameter::epiparameter_db( + disease = "covid", + epi_name = "serial", + author = "Nishiura", + single_epiparameter = TRUE + ) +``` + +Nous avons maintenant un paramètre épidémiologique que nous pouvons utiliser dans notre analyse ! Dans le morceau ci-dessous, nous avons remplacé l'un des paramètres **statistiques sommaires** en `EpiNow2::LogNormal()` + +```r +generation_time <- + EpiNow2::LogNormal( + mean = covid_serialint$summary_stats$mean, # replaced! + sd = covid_serialint$summary_stats$sd, # replaced! + max = 20 + ) +``` + +Dans cet épisode, nous utiliserons la fonction **fonctions de distribution** qui `{epiparameter}` permet d'obtenir une valeur maximale (`max`) pour ce paquet et tout autre paquet en aval dans votre pipeline d'analyse ! + +Chargeons le paquet `{epiparameter}` et `{EpiNow2}` . Pour `{EpiNow2}` nous mettrons 4 cœurs à utiliser pour les calculs parallèles. Nous utiliserons le tube `%>%`, quelques `{dplyr}` verbes et `{ggplot2}` et donc appelons aussi à la `{tidyverse}` paquet : + +```{r, warning=FALSE, message=FALSE} +library(epiparameter) +library(EpiNow2) +library(tidyverse) + +withr::local_options(list(mc.cores = 4)) +``` + +::::::::::::::::::: checklist + +### Le double point-virgule + +Le double point-virgule `::` dans R vous permet d'appeler une fonction spécifique d'un paquetage sans charger l'ensemble du paquetage dans l'environnement actuel. + +Par exemple, vous pouvez appeler une fonction spécifique d'un package sans charger le package entier dans l'environnement actuel, `dplyr::filter(data, condition)` utilise `filter()` à partir de l'outil `{dplyr}` paquet. + +Cela nous permet de nous souvenir des fonctions du paquet et d'éviter les conflits d'espace de noms en spécifiant explicitement la fonction du paquet à utiliser lorsque plusieurs paquets ont des fonctions portant le même nom. + +::::::::::::::::::: + +## Fonctions de distribution + +En R, toutes les distributions statistiques disposent de fonctions permettant d'accéder aux éléments suivants : + +- `density()`: Probabilité **Densité** (PDF), +- `cdf()` fonction de distribution cumulative (**FDC**), +- `quantile()`: **Quantile** et +- `generate()`: **Aléatoire** valeurs aléatoires de la distribution donnée. + +:::::::::::: checklist + +### Fonctions pour la distribution normale + +Si vous en avez besoin, lisez en détail la rubrique [Fonctions de probabilité R pour la distribution normale](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc) Pour en savoir plus sur les fonctions de probabilité de la loi normale, lisez les définitions de chacune d'entre elles et identifiez la partie de la loi dans laquelle elles se situent ! + +![Les quatre fonctions de probabilité de la loi normale ([Jack Weiss, 2012](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc))](fig/fig5a-normaldistribution.png) + +:::::::::::::::::::: + +Si vous regardez `?stats::Distributions` chaque type de distribution possède un ensemble unique de fonctions. Cependant, `{epiparameter}` vous donne les mêmes quatre fonctions pour accéder à chacune des valeurs ci-dessus pour n'importe quelle `` objet de votre choix ! + +```{r, eval=FALSE} +# plot this to have a visual reference +plot(covid_serialint, day_range = 0:20) +``` + +```{r} +# the density value at quantile value of 10 (days) +density(covid_serialint, at = 10) + +# the cumulative probability at quantile value of 10 (days) +cdf(covid_serialint, q = 10) + +# the quantile value (day) at a cumulative probability of 60% +quantile(covid_serialint, p = 0.6) + +# generate 10 random values (days) given +# the distribution family and its parameters +generate(covid_serialint, times = 10) +``` + +::::::::: instructor + +L'accès à la documentation de référence (fichiers d'aide) de ces fonctions est accessible avec la notation à trois doubles points : `epiparameter:::` + +- `?epiparameter:::density.epiparameter()` +- `?epiparameter:::cdf.epiparameter()` +- `?epiparameter:::quantile.epiparameter()` +- `?epiparameter:::generate.epiparameter()` + +:::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Fenêtre pour la recherche de contact et l'intervalle sériel + +La fenêtre **intervalle sériel** est important pour l'optimisation de la recherche des contacts, car il fournit une fenêtre temporelle pour l'endiguement de la propagation d'une maladie ([Fine, 2003](https://academic.oup.com/aje/article/158/11/1039/162725)). En fonction de l'intervalle sériel, nous pouvons évaluer la nécessité d'augmenter le nombre de jours pris en compte pour la recherche des contacts afin d'inclure un plus grand nombre de contacts rétrogrades ([Davis et al., 2020](https://assets.publishing.service.gov.uk/media/61e9ab3f8fa8f50597fb3078/S0523_Oxford_-_Backwards_contact_tracing.pdf)). + +Avec l'intervalle sériel COVID-19 (`covid_serialint`), calculez : + +- Quelle proportion supplémentaire des cas rétrogrades pourrait être capturée si la méthode de recherche des contacts prenait en compte les contacts jusqu'à 6 jours avant l'apparition de la maladie par rapport à 2 jours avant l'apparition de la maladie ? + +::::::::::::::::: hint + +Dans la figure 5 du [Fonctions de probabilité R pour la distribution normale](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc) la partie ombrée représente une probabilité cumulée de `0.997` pour la valeur du quantile à `x = 2`. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=FALSE} +plot(covid_serialint) +``` + +```{r, eval=TRUE} +cdf(covid_serialint, q = 2) +cdf(covid_serialint, q = 6) +``` + +Étant donné l'intervalle sériel COVID-19 : + +- Une méthode de recherche des contacts prenant en compte les contacts jusqu'à 2 jours avant l'apparition de la maladie permettra d'identifier environ 11,1 % des cas rétrogrades. + +- Si cette période est étendue à 6 jours avant l'apparition de la maladie, 76,2 % des contacts rétrospectifs pourraient être pris en compte. + +:::::::::::::::::::::::::: + +::::::::::::::::: solution + +### Que se passerait-il si + +Si nous échangeons la question entre les jours et la probabilité cumulée à : + +- Si l'on considère les cas secondaires, combien de jours après l'apparition des symptômes des cas primaires peut-on s'attendre à ce que 55 % des symptômes apparaissent ? + +```{r, eval=FALSE} +quantile(covid_serialint, p = 0.55) +``` + +L'interprétation pourrait être la suivante : + +- Les 55 % de cas secondaires se manifestent 4,2 jours après l'apparition des symptômes des cas primaires. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Discrétiser une distribution continue + +Nous nous rapprochons de la fin ! `EpiNow2::LogNormal()` a encore besoin d'une valeur maximale (`max`). + +Une façon d'y parvenir est d'obtenir la valeur du quantile pour le 99e percentile de la distribution ou `0.99` probabilité cumulative de la distribution. Pour ce faire, nous devons avoir accès à l'ensemble des fonctions de distribution de notre `` objet. + +Nous pouvons utiliser l'ensemble des fonctions de distribution d'un *continue* distribution continue (comme ci-dessus). Cependant, ces valeurs seront *continues* nombres continus. Nous pouvons **discrétiser** la distribution continue stockée dans notre `` pour obtenir des valeurs discrètes à partir d'une distribution continue. + +Lorsque nous `epiparameter::discretise()` la distribution continue, nous obtenons un **discrète** discrète : + +```{r} +covid_serialint_discrete <- + epiparameter::discretise(covid_serialint) + +covid_serialint_discrete +``` + +Nous identifions ce changement dans la `Distribution:` ligne de sortie de la `` objet. Vérifiez à nouveau cette ligne : + +``` +Distribution: discrete lnorm +``` + +Alors que pour un **continu** nous traçons la courbe de la *Fonction de densité de probabilité (PDF)* pour une **discrète** pour une distribution discrète, nous traçons la *Fonction de masse de probabilité (PMF)*: + +```{r, eval=FALSE} +# continuous +plot(covid_serialint) + +# discrete +plot(covid_serialint_discrete) +``` + +Pour obtenir enfin une `max` accédons à la valeur du quantile du 99e percentile ou `0.99` de la distribution à l'aide de la fonction `prob_dist$q` de la même manière que nous accédons à la valeur du quantile du 99ème centile ou de la probabilité de la distribution avec la notation `summary_stats` valeurs. + +```{r} +covid_serialint_discrete_max <- + quantile(covid_serialint_discrete, p = 0.99) +``` + +::::::::::::::::::::::::::::::::: challenge + +### Durée de la quarantaine et de la période d'incubation + +Les **période d'incubation** est un délai utile pour évaluer la durée de la surveillance active ou de la quarantaine ([Lauer et al., 2020](https://www.acpjournals.org/doi/10.7326/M20-0504)). De même, les délais entre l'apparition des symptômes et la guérison (ou le décès) détermineront la durée nécessaire des soins de santé et de l'isolement des cas ([Cori et al.](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +Calculez : + +- Dans quel délai exact 99 % des personnes présentant les symptômes de COVID-19 les manifestent-elles après l'infection ? + +::::::::::::::::: hint + +Quelle est la distribution des délais qui mesure le temps écoulé entre l'infection et l'apparition des symptômes ? + +Les fonctions de probabilité pour `` **discrètes** sont les mêmes que celles que nous avons utilisées pour les *continues* continues ! + +```{r, eval=FALSE} +# plot to have a visual reference +plot(covid_serialint_discrete, day_range = 0:20) + +# density value at quantile value 10 (day) +density(covid_serialint_discrete, at = 10) + +# cumulative probability at quantile value 10 (day) +cdf(covid_serialint_discrete, q = 10) + +# In what quantile value (days) do we have the 60% cumulative probability? +quantile(covid_serialint_discrete, p = 0.6) + +# generate random values +generate(covid_serialint_discrete, times = 10) +``` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE} +covid_incubation <- + epiparameter::epiparameter_db( + disease = "covid", + epi_name = "incubation", + single_epiparameter = TRUE + ) + +covid_incubation_discrete <- epiparameter::discretise(covid_incubation) + +quantile(covid_incubation_discrete, p = 0.99) +``` + +99% des personnes qui développent les symptômes du COVID-19 le font dans les 16 jours suivant l'infection. + +Aujourd'hui, *Ce résultat est-il attendu en termes épidémiologiques ?* + +:::::::::::::::::::::::::: + +::::::::::::::::: solution + +### Comment créer un diagramme de distribution ? + +A partir d'une valeur maximale avec `quantile()` nous pouvons créer une séquence de valeurs de quantiles sous la forme d'un tableau numérique et calculer `density()` pour chacune d'entre elles : + +```{r, eval=TRUE} +# create a discrete distribution visualisation +# from a maximum value from the distribution +quantile(covid_serialint_discrete, p = 0.99) %>% + # generate quantile values + # as a sequence for each natural number + seq(1L, to = ., by = 1L) %>% + # coerce numeric vector to data frame + as_tibble_col(column_name = "quantile_values") %>% + mutate( + # calculate density values + # for each quantile in the density function + density_values = + density( + x = covid_serialint_discrete, + at = quantile_values + ) + ) %>% + # create plot + ggplot( + aes( + x = quantile_values, + y = density_values + ) + ) + + geom_col() +``` + +**Rappelez-vous :** Dans les infections à transmission pré-symptomatique, les intervalles sériels peuvent avoir des valeurs négatives ([Nishiura et al., 2020](https://www.ijidonline.com/article/S1201-9712\(20\)30119-3/fulltext)). Lorsque nous utilisons la méthode *intervalle sériel* pour approximer l'intervalle *temps de génération* nous devons effectuer cette distribution avec des valeurs positives uniquement ! + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Plug-in `{epiparameter}` pour `{EpiNow2}` + +Maintenant, nous pouvons brancher le tout dans le `EpiNow2::LogNormal()` ! + +- la **statistiques sommaires** `mean` et `sd` de la distribution, +- une valeur maximale `max`, +- le `distribution` nom. + +Lors de l'utilisation de `EpiNow2::LogNormal()` pour définir un **normale logarithmique** comme celle de l'article `covid_serialint` nous pouvons spécifier la moyenne et l'écart-type comme paramètres. Pour obtenir les paramètres "naturels" d'une distribution log-normale, nous pouvons également convertir ses statistiques sommaires en paramètres de distribution nommés `meanlog` et `sdlog`. Avec `{epiparameter}` nous pouvons obtenir directement les *paramètres de distribution* en utilisant `epiparameter::get_parameters()`: + +```{r} +covid_serialint_parameters <- + epiparameter::get_parameters(covid_serialint) +``` + +On a alors : + +```{r} +serial_interval_covid <- + EpiNow2::LogNormal( + meanlog = covid_serialint_parameters["meanlog"], + sdlog = covid_serialint_parameters["sdlog"], + max = covid_serialint_discrete_max + ) + +serial_interval_covid +``` + +Dans l'hypothèse d'un scénario COVID-19, utilisons les 60 premiers jours de l'année de référence. `example_confirmed` de l'ensemble de données du `{EpiNow2}` comme `reported_cases` et l'ensemble de données récemment créé `serial_interval_covid` en tant que données d'entrée pour estimer le nombre de reproduction variable dans le temps à l'aide de l'objet `EpiNow2::epinow()`. + +```{r, message=FALSE} +epinow_estimates_cg <- epinow( + # cases + data = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(serial_interval_covid) +) + +base::plot(epinow_estimates_cg) +``` + +Les `plot()` comprend les cas estimés par date d'infection, qui sont reconstitués à partir des cas déclarés et des retards. + +:::::::::: callout + +### Avertissement + +L'utilisation de l'intervalle sériel au lieu du temps de génération est une alternative qui peut propager un biais dans vos estimations, d'autant plus pour les maladies dont la transmission pré-symptomatique est signalée. ([Chung Lau et al, 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)) + +:::::::::::::::::: + +## Ajustement pour tenir compte des délais de déclaration + +Estimation $R_t$ nécessite des données sur le nombre quotidien de nouvelles infections. En raison des retards dans le développement de charges virales détectables, l'apparition des symptômes, la recherche de soins et la déclaration, ces chiffres ne sont pas facilement disponibles. Toutes les observations reflètent des événements de transmission survenus dans le passé. En d'autres termes, si $d$ est le délai entre l'infection et l'observation, alors les observations au temps $t$ informent $R_{t−d}$ et non $R_t$. [(Gostic et al., 2020)](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409#sec007) + +![**Calendrier pour la déclaration de la chaîne de la maladie, Pays-Bas.** Lab, laboratoire ; PHA, autorité de santé publique. A partir de [Marinović et al, 2015](https://wwwnc.cdc.gov/eid/article/21/2/13-0504_article)](fig/disease-reporting.jpg) + +Les **distribution des délais** pourrait être déduite conjointement avec les délais d'infection sous-jacents ou estimée comme la somme des délais d'infection. [période d'incubation](../learners/reference.md#incubation) et de la distribution des délais entre l'apparition des symptômes et l'observation à partir des données de la liste d'attente ([délai de déclaration](../learners/reference.md#reportingdelay)). Pour les `{EpiNow2}` nous pouvons spécifier ces deux distributions de délais complémentaires dans le fichier `delays` argument. + +![**$R_{t}$ est une mesure de la transmission au moment $t$.** Observations après le temps $t$ doivent être ajustées. ICU, unité de soins intensifs. A partir de [Gostic et al, 2020](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409#sec007)](fig/rt-adjusting-delays.png) + +::::::::::::::::::::::::::::::::: challenge + +### Utiliser une période d'incubation pour COVID-19 afin d'estimer Rt + +Estimez le nombre de reproduction variable dans le temps pour les 60 premiers jours de la période d'incubation de COVID-19. `example_confirmed` de l'ensemble de données de `{EpiNow2}`. Accédez à une période d'incubation pour COVID-19 à partir de `{epiparameter}` pour l'utiliser comme délai de déclaration. + +::::::::::::::::: hint + +Utilisez le dernier `epinow()` calcul à l'aide de l'outil `delays` et l'argument `delay_opts()` fonction d'aide. + +L'argument `delays` et l'argument `delay_opts()` sont analogues à la fonction d'aide `generation_time` et à l'argument `generation_time_opts()` sont analogues à l'argument et à la fonction d'aide. + +```r +epinow_estimates <- epinow( + # cases + reported_cases = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(covid_serial_interval), + delays = delay_opts(covid_incubation_time) +) +``` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE, message=FALSE} + +# generation time --------------------------------------------------------- + +# get covid serial interval +covid_serialint <- + epiparameter::epiparameter_db( + disease = "covid", + epi_name = "serial", + author = "Nishiura", + single_epiparameter = TRUE + ) + +# adapt epiparameter to epinow2 +covid_serialint_discrete_max <- covid_serialint %>% + epiparameter::discretise() %>% + quantile(p = 0.99) + +covid_serialint_parameters <- + epiparameter::get_parameters(covid_serialint) + +covid_serial_interval <- + EpiNow2::LogNormal( + meanlog = covid_serialint_parameters["meanlog"], + sdlog = covid_serialint_parameters["sdlog"], + max = covid_serialint_discrete_max + ) + +# incubation time --------------------------------------------------------- + +# get covid incubation period +covid_incubation <- epiparameter::epiparameter_db( + disease = "covid", + epi_name = "incubation", + author = "Natalie", + single_epiparameter = TRUE +) + +# adapt epiparameter to epinow2 +covid_incubation_discrete_max <- covid_incubation %>% + epiparameter::discretise() %>% + quantile(p = 0.99) + +covid_incubation_parameters <- + epiparameter::get_parameters(covid_incubation) + +covid_incubation_time <- + EpiNow2::LogNormal( + meanlog = covid_incubation_parameters["meanlog"], + sdlog = covid_incubation_parameters["sdlog"], + max = covid_incubation_discrete_max + ) + +# epinow ------------------------------------------------------------------ + +# run epinow +epinow_estimates_cgi <- epinow( + # cases + data = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(covid_serial_interval), + delays = delay_opts(covid_incubation_time) +) + +base::plot(epinow_estimates_cgi) +``` + +Essayez de compléter le `delays` avec un délai de déclaration comme le `reporting_delay_fixed` de l'épisode précédent. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::: discussion + +### Dans quelle mesure a-t-il changé ? + +Après avoir ajouté la période d'incubation, discutez-en : + +- La tendance de l'ajustement du modèle dans la section "Estimation" change-t-elle ? +- L'incertitude a-t-elle changé ? +- Comment expliqueriez-vous ou interpréteriez-vous ces changements ? + +Comparez tous les `{EpiNow2}` figures générées précédemment. + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +## Défis + +:::::::::::::::::::::::::::::: callout + +### Une astuce pour compléter le code + +Si nous écrivons l'élément `[]` à côté de l'objet `covid_serialint_parameters[]` à l'intérieur de `[]` nous pouvons utiliser le +Touche de tabulation +pour [fonctionnalité de complétion de code](https://support.posit.co/hc/en-us/articles/205273297-Code-Completion-in-the-RStudio-IDE) + +Elle permet d'accéder rapidement aux éléments suivants `covid_serialint_parameters["meanlog"]` et `covid_serialint_parameters["sdlog"]`. + +Nous vous invitons à tester ceci dans des morceaux de code et dans la console R ! + +:::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Nombre de reproductions effectives d'Ebola ajusté en fonction des délais de déclaration + +Téléchargez et lisez le [données Ebola](data/ebola_cases.csv): + +- Estimez le nombre de reproductions effectives en utilisant `{EpiNow2}` +- Ajustez l'estimation en fonction des délais de déclaration disponibles en `{epiparameter}` +- Pourquoi avez-vous choisi ce paramètre ? + +::::::::::::::::: hint + +Pour calculer la $R_t$ en utilisant `{EpiNow2}` nous avons besoin de : + +- Incidence agrégée `data` avec les cas confirmés par jour, et +- L'incidence `generation` distribution du temps. +- Optionnellement, le rapport `delays` lorsqu'elle est disponible (par exemple, la période d'incubation). + +Pour obtenir la distribution des retards à l'aide de `{epiparameter}` nous pouvons utiliser des fonctions comme : + +- `epiparameter::epiparameter_db()` +- `epiparameter::parameter_tbl()` +- `discretise()` +- `quantile()` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE, echo=FALSE, message=FALSE} +# read data from the tutorial repository R project +ebola_confirmed <- + read_csv(file.path("data", "ebola_cases.csv")) %>% + incidence2::incidence( + date_index = "date", + counts = "confirm", + count_values_to = "confirm", + date_names_to = "date", + complete_dates = TRUE + ) %>% + dplyr::select(-count_variable) +``` + +```{r, eval=FALSE, echo=TRUE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +ebola_confirmed <- + read_csv(here::here("data", "raw-data", "ebola_cases.csv")) %>% + incidence2::incidence( + date_index = "date", + counts = "confirm", + count_values_to = "confirm", + date_names_to = "date", + complete_dates = TRUE + ) %>% + dplyr::select(-count_variable) + +# list distributions +epiparameter::epiparameter_db(disease = "ebola") %>% + epiparameter::parameter_tbl() +``` + +```{r, message=FALSE, eval=TRUE} + +# generation time --------------------------------------------------------- + +# subset one distribution for the generation time +ebola_serial <- epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "serial", + single_epiparameter = TRUE +) + +# adapt epiparameter to epinow2 +ebola_serial_discrete <- epiparameter::discretise(ebola_serial) + +serial_interval_ebola <- + EpiNow2::Gamma( + mean = ebola_serial$summary_stats$mean, + sd = ebola_serial$summary_stats$sd, + max = quantile(ebola_serial_discrete, p = 0.99) + ) + +# incubation time --------------------------------------------------------- + +# subset one distribution for delay of the incubation period +ebola_incubation <- epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "incubation", + single_epiparameter = TRUE +) + +# adapt epiparameter to epinow2 +ebola_incubation_discrete <- epiparameter::discretise(ebola_incubation) + +incubation_period_ebola <- + EpiNow2::Gamma( + mean = ebola_incubation$summary_stats$mean, + sd = ebola_incubation$summary_stats$sd, + max = quantile(ebola_serial_discrete, p = 0.99) + ) + +# epinow ------------------------------------------------------------------ + +# run epinow +epinow_estimates_egi <- epinow( + # cases + data = ebola_confirmed, + # delays + generation_time = generation_time_opts(serial_interval_ebola), + delays = delay_opts(incubation_period_ebola) +) + +plot(epinow_estimates_egi) +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Que faire avec les distributions de Weibull ? + +Utilisez les `influenza_england_1978_school` de la base de données `{outbreaks}` pour calculer le nombre de reproductions effectives à l'aide de `{EpiNow2}` en ajustant en fonction des délais de déclaration disponibles dans `{epiparameter}`. + +::::::::::::::::: hint + +`EpiNow2::NonParametric()` accepte les fonctions de masse de probabilité (PMF) de n'importe quelle famille de distribution. Lisez le guide de référence sur [Distributions de probabilités](https://epiforecasts.io/EpiNow2/reference/Distributions.html). + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, message=FALSE, eval=TRUE} +# What parameters are available for Influenza? +epiparameter::epiparameter_db(disease = "influenza") %>% + epiparameter::parameter_tbl() %>% + count(epi_name) + +# generation time --------------------------------------------------------- + +# Read the generation time +influenza_generation <- + epiparameter::epiparameter_db( + disease = "influenza", + epi_name = "generation" + ) + +influenza_generation + +# EpiNow2 currently accepts Gamma or LogNormal +# other can pass the PMF function + +influenza_generation_discrete <- + epiparameter::discretise(influenza_generation) + +influenza_generation_max <- + quantile(influenza_generation_discrete, p = 0.99) + +influenza_generation_pmf <- + density( + influenza_generation_discrete, + at = 0:influenza_generation_max + ) + +influenza_generation_pmf + +# EpiNow2::NonParametric() can also accept the PMF values +generation_time_influenza <- + EpiNow2::NonParametric( + pmf = influenza_generation_pmf + ) + +# incubation period ------------------------------------------------------- + +# Read the incubation period +influenza_incubation <- + epiparameter::epiparameter_db( + disease = "influenza", + epi_name = "incubation", + single_epiparameter = TRUE + ) + +# Discretize incubation period +influenza_incubation_discrete <- + epiparameter::discretise(influenza_incubation) + +influenza_incubation_max <- + quantile(influenza_incubation_discrete, p = 0.99) + +influenza_incubation_pmf <- + density( + influenza_incubation_discrete, + at = 0:influenza_incubation_max + ) + +influenza_incubation_pmf + +# EpiNow2::NonParametric() can also accept the PMF values +incubation_time_influenza <- + EpiNow2::NonParametric( + pmf = influenza_incubation_pmf + ) + +# epinow ------------------------------------------------------------------ + +# Read data +influenza_cleaned <- + outbreaks::influenza_england_1978_school %>% + select(date, confirm = in_bed) + +# Run epinow() +epinow_estimates_igi <- epinow( + # cases + data = influenza_cleaned, + # delays + generation_time = generation_time_opts(generation_time_influenza), + delays = delay_opts(incubation_time_influenza) +) + +plot(epinow_estimates_igi) +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Prochaines étapes + +::::::::::::::::: testimonial + +### Comment obtenir des paramètres de distribution à partir de distributions statistiques ? + +Comment obtenir la moyenne et l'écart-type d'un temps de génération avec *seulement* mais pas de statistiques sommaires telles que `mean` ou `sd` pour `EpiNow2::Gamma()` ou `EpiNow2::LogNormal()`? + +Regardez le `{epiparameter}` vignette sur [l'extraction et la conversion des paramètres](https://epiverse-trace.github.io/epiparameter/articles/extract_convert.html) et son [cas d'utilisation](https://epiverse-trace.github.io/epiparameter/articles/extract_convert.html#use-cases)! + +::::::::::::::::::::::::::::: + +::::::::::::::::: testimonial + +### Comment estimer la distribution des délais pour la maladie X ? + +Consultez cet excellent tutoriel sur l'estimation de l'intervalle sériel et de la période d'incubation de la maladie X en tenant compte des éléments suivants *la censure* en utilisant l'inférence bayésienne avec des logiciels comme `{rstan}` et `{coarseDataTools}`. + +- Tutoriel en anglais : +- Tutoriel en Español : + +**Ensuite,** Après avoir obtenu vos valeurs estimées, vous pouvez créer manuellement vos propres` ` à l'aide de la fonction `epiparameter::epiparameter()`! Jetez un coup d'œil à ses [guide de référence sur "Créer un `` objet"](https://epiverse-trace.github.io/epiparameter/reference/epiparameter.html#ref-examples)! + +Enfin, jetez un coup d'œil au dernier [`{epidist}` paquet R](https://epidist.epinowcast.org/) qui fournissent des méthodes pour relever les principaux défis de l'estimation des distributions, y compris la troncature, la censure par intervalle et les biais dynamiques. + +::::::::::::::::::::::::::::: + + + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utilisez les fonctions de distribution avec `` pour obtenir des statistiques sommaires et des paramètres informatifs pour les interventions de santé publique, comme la fenêtre de recherche des contacts et la durée de la quarantaine. +- Utilisez `discretise()` pour convertir les distributions de délais continues en distributions discrètes. +- Utilisez cette fonction pour convertir les distributions continues en distributions discrètes. `{epiparameter}` pour obtenir les délais de déclaration requis dans les estimations de transmissibilité. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/fr/episodes/quantify-transmissibility.Rmd b/locale/fr/episodes/quantify-transmissibility.Rmd new file mode 100644 index 00000000..dd3a45a5 --- /dev/null +++ b/locale/fr/episodes/quantify-transmissibility.Rmd @@ -0,0 +1,593 @@ +--- +title: Quantifier la transmission +teaching: 30 +exercises: 0 +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- Comment puis-je estimer le nombre de reproduction variable dans le temps ($Rt$) et le taux de croissance à partir d'une série chronologique de données de cas ? +- Comment quantifier l'hétérogénéité géographique à partir de ces paramètres de transmission ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Apprenez à estimer les paramètres de transmission à partir d'une série chronologique de données sur les cas à l'aide du progiciel R. `EpiNow2` + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +Les apprenants doivent se familiariser avec les concepts suivants avant de suivre ce tutoriel : + +**Statistiques**: distributions de probabilités, principe de l'analyse bayésienne. + +**Théorie des épidémies**: Nombre de reproductions effectives. + +**Science des données**: la transformation et la visualisation des données. Vous pouvez revoir l'épisode sur [Agréger et visualiser](https://epiverse-trace.github.io/tutorials-early/describe-cases.html) les données d'incidence. + +::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: callout + +### Rappel : l'indice de reproduction effectif, $R_t$ + +Le [numéro de reproduction de base](../learners/reference.md#basic), $R_0$ est le nombre moyen de cas causés par un individu infectieux dans une population entièrement sensible. + +Mais dans une épidémie en cours, la population ne reste pas entièrement sensible, car les personnes qui se remettent de l'infection sont généralement immunisées. En outre, il peut y avoir des changements de comportement ou d'autres facteurs qui affectent la transmission. Lorsque nous voulons surveiller les changements dans la transmission, nous nous intéressons donc davantage à la valeur de la **nombre de reproduction efficace**, $R_t$ qui représente le nombre moyen de cas causés par un individu infectieux dans la population au temps $t$ compte tenu de l'état actuel de la population (y compris les niveaux d'immunité et les mesures de contrôle). + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Introduction + +L'intensité de la transmission d'un foyer est quantifiée à l'aide de deux paramètres clés : le nombre de reproduction, qui renseigne sur la force de la transmission en indiquant le nombre de nouveaux cas attendus pour chaque cas existant, et le nombre de décès. [taux de croissance](../learners/reference.md#growth) qui renseigne sur la vitesse de transmission en indiquant la rapidité avec laquelle le foyer se propage ou décline (temps de doublement/halving) au sein d'une population. Pour plus de détails sur la distinction entre la vitesse et la force de la transmission et les implications pour la lutte, consultez le site [Dushoff \& Park, 2021](https://royalsocietypublishing.org/doi/full/10.1098/rspb.2020.1556). + +Pour estimer ces paramètres clés à l'aide des données relatives aux cas, nous devons tenir compte des délais entre la date des infections et la date des cas déclarés. Dans une situation d'épidémie, les données ne sont généralement disponibles qu'à partir des dates déclarées. Nous devons donc utiliser des méthodes d'estimation pour tenir compte de ces retards lorsque nous essayons de comprendre les changements dans la transmission au fil du temps. + +Dans les prochains tutoriels, nous nous concentrerons sur la manière d'utiliser les fonctions de `{EpiNow2}` pour estimer les paramètres de transmission des données de cas. Nous ne couvrirons pas le contexte théorique des modèles ou du cadre d'inférence, pour plus de détails sur ces concepts, consultez le site Web de la Commission européenne. [vignette](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections.html). + +Dans ce tutoriel, nous allons apprendre à utiliser la fonction `{EpiNow2}` pour estimer le nombre de reproduction variable dans le temps. Nous obtiendrons les données d'entrée de `{incidence2}`. Nous utiliserons le paquet `{tidyr}` et `{dplyr}` pour organiser certains de ses résultats, `{ggplot2}` pour visualiser la distribution des cas, et le tuyau `%>%` pour relier certaines de leurs fonctions, alors appelons aussi la fonction `{tidyverse}` paquet : + +```r +library(EpiNow2) +library(incidence2) +library(tidyverse) +``` + +```{r, echo=FALSE, eval=TRUE, message=FALSE, warning=FALSE} +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### Le double point-virgule + +Le double point-virgule `::` dans R vous permet d'appeler une fonction spécifique d'un paquetage sans charger l'ensemble du paquetage dans l'environnement actuel. + +Par exemple, vous pouvez appeler une fonction spécifique d'un package sans charger le package entier dans l'environnement actuel, `dplyr::filter(data, condition)` utilise `filter()` à partir de l'outil `{dplyr}` paquet. + +Cela nous permet de nous souvenir des fonctions du paquet et d'éviter les conflits d'espace de noms. + +::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: instructor + +Ce tutoriel illustre l'utilisation de `epinow()` pour estimer le nombre de reproduction et les durées d'infection variables dans le temps. Les apprenants doivent comprendre les données d'entrée nécessaires au modèle et les limites des résultats du modèle. + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: callout + +### Inférence bayésienne + +Le paquetage R `EpiNow2` utilise une méthode d'inférence bayésienne [inférence bayésienne](../learners/reference.md#bayesian) pour estimer les nombres de reproduction et les durées d'infection sur la base des dates de déclaration. En d'autres termes, il estime la transmission en fonction de la date à laquelle les personnes ont été effectivement infectées (plutôt que de l'apparition des symptômes), en tenant compte des retards dans les données observées. En revanche, l'approche `{EpiEstim}` permet une estimation en temps réel plus rapide et plus simple du nombre de reproductions en utilisant uniquement les données de cas au fil du temps, reflétant la façon dont la transmission change en fonction du moment où les symptômes apparaissent. + +Dans l'inférence bayésienne, nous utilisons les connaissances antérieures (distributions antérieures) avec les données (dans une fonction de vraisemblance) pour trouver la probabilité postérieure : + +$Posterior , probability \propto likelihood \times prior , probability$ + +:::::::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::: instructor + +Faites référence à la distribution de probabilité préalable et à la [probabilité postérieure](https://en.wikipedia.org/wiki/Posterior_probability) postérieure. + +Dans la ["`Expected change in reports`", l'appel](#expected-change-in-daily-cases) par "la probabilité postérieure que $R_t < 1$"nous nous référons spécifiquement à la [aire sous la courbe de distribution de la probabilité postérieure](https://www.nature.com/articles/nmeth.3368/figures/1). + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Distributions de délais et données de cas + +### Données de cas + +Pour illustrer les fonctions des `EpiNow2` nous utiliserons les données relatives au début de la pandémie de COVID-19 au Royaume-Uni. Les données sont disponibles dans le paquetage R `{incidence2}`. + +```{r} +dplyr::as_tibble(incidence2::covidregionaldataUK) +``` + +Pour utiliser les données, nous devons les formater de manière à ce qu'elles comportent deux colonnes : + +- `date` la date (en tant qu'objet date, voir `?is.Date()`), +- `confirm`: nombre de déclarations de maladie (confirmer) à cette date. + +Utilisons `{tidyr}` et `{incidence2}` pour cela : + +```{r, warning=FALSE, message=FALSE} +cases <- incidence2::covidregionaldataUK %>% + # Preprocess missing values + tidyr::replace_na(base::list(cases_new = 0)) %>% + # Compute the daily incidence + incidence2::incidence( + date_index = "date", + counts = "cases_new", + count_values_to = "confirm", + date_names_to = "date", + complete_dates = TRUE + ) %>% + # Drop column for {EpiNow2} input format + dplyr::select(-count_variable) %>% + # Keep the first 90 dates + dplyr::slice_head(n = 90) + +cases +``` + +Avec `incidence2::incidence()` nous agrégeons des cas dans différentes périodes de temps *intervalles* (c'est-à-dire des jours, des semaines ou des mois) ou par *groupe* par groupe. Nous pouvons également obtenir des dates complètes pour tous les intervalles de dates par catégorie de groupe à l'aide de la fonction `complete_dates = TRUE` +Explorez plus tard les [`incidence2::incidence()` manuel de référence](https://www.reconverse.org/incidence2/reference/incidence.html) + +::::::::::::::::::::::::: spoiler + +### Pouvons-nous reproduire {incidence2} avec {dplyr}? + +Nous pouvons obtenir un objet similaire à `cases` à partir de l'objet `incidence2::covidregionaldataUK` à l'aide de la fonction `{dplyr}` paquet. + +```{r, warning=FALSE, message=FALSE, eval=FALSE} +incidence2::covidregionaldataUK %>% + dplyr::select(date, cases_new) %>% + dplyr::group_by(date) %>% + dplyr::summarise(confirm = sum(cases_new, na.rm = TRUE)) %>% + dplyr::ungroup() %>% + dplyr::slice_head(n = 90) +``` + +Cependant, le `incidence2::incidence()` contient des arguments pratiques comme `complete_dates` qui facilitent l'obtention d'un objet d'incidence avec le même intervalle de dates pour chaque groupe sans nécessiter de lignes de code supplémentaires ou un paquetage de séries temporelles. + +::::::::::::::::::::::::: + +Dans une situation d'épidémie, il est probable que nous n'ayons accès qu'au début de l'ensemble des données d'entrée. Nous supposons donc que nous ne disposons que des 90 premiers jours de ces données. + +```{r, echo=FALSE} +cases %>% + # use ggplot2 + ggplot(aes(x = date, y = confirm)) + + geom_col() + + theme_grey( + base_size = 15 + ) +``` + +### Distribution des délais + +Nous supposons qu'il existe des délais entre le moment de l'infection et le moment où un cas est signalé. Nous spécifions ces délais sous forme de distributions pour tenir compte de l'incertitude des différences au niveau individuel. Le délai peut impliquer plusieurs types de processus. Un délai typique entre le moment de l'infection et la déclaration du cas peut consister en ce qui suit + +> **le temps écoulé entre l'infection et l'apparition des symptômes** (le [période d'incubation](../learners/reference.md#incubation)) + **délai entre l'apparition des symptômes et la notification du cas** (délai de déclaration) +> . + +La distribution des délais pour chacun de ces processus peut être estimée à partir de données ou obtenue à partir de la littérature. Nous pouvons exprimer l'incertitude quant aux paramètres corrects des distributions en supposant que les distributions ont **fixe** fixes ou qu'elles ont **variables** variables. Pour comprendre la différence entre **fixe** et **variables** considérons la période d'incubation. + +::::::::::::::::::::::::::::::::::::: callout + +### Délais et données + +Le nombre de retards et le type de retard sont des données flexibles qui dépendent des données. Les exemples ci-dessous montrent comment les délais peuvent être spécifiés pour différentes sources de données : + +
+ +| Source de données | Délai (s) | +| -------------------------------- | ----------------------------------------------------------------------------------------- | +| Heure d'apparition des symptômes | Période d'incubation | +| Date de la déclaration du cas | Période d'incubation + délai entre l'apparition des symptômes et la notification du cas | +| Durée de l'hospitalisation | Période d'incubation + temps écoulé entre l'apparition des symptômes et l'hospitalisation | + +
+ +:::::::::::::::::::::::::::::::::::::::::::::::: + +#### Distribution de la période d'incubation + +La distribution de la période d'incubation pour de nombreuses maladies peut généralement être obtenue à partir de la littérature. L'ensemble `{epiparameter}` contient une bibliothèque de paramètres épidémiologiques pour différentes maladies, obtenus à partir de la littérature. + +Nous spécifions une distribution gamma (fixe) avec moyenne $\mu = 4$ et un écart-type $\sigma = 2$ (forme = $4$, échelle = $1$) en utilisant la fonction `Gamma()` comme suit : + +```{r} +incubation_period_fixed <- EpiNow2::Gamma( + mean = 4, + sd = 2, + max = 20 +) + +incubation_period_fixed +``` + +L'argument `max` est la valeur maximale que la distribution peut prendre ; dans cet exemple, 20 jours. + +::::::::::::::::::::::::::::::::::::: callout + +### Pourquoi une distribution gamma ? + +La période d'incubation doit être une valeur positive. Nous devons donc spécifier une distribution en `{EpiNow2}` qui ne concerne que les valeurs positives. + +`Gamma()` prend en charge les distributions Gamma et `LogNormal()` les distributions log-normales, qui sont des distributions pour les valeurs positives uniquement. + +Pour tous les types de retard, nous devrons utiliser des distributions pour les valeurs positives uniquement - nous ne voulons pas inclure les retards de jours négatifs dans notre analyse ! + +:::::::::::::::::::::::::::::::::::::::::::::::: + +#### Prise en compte de l'incertitude de la distribution + +Pour spécifier une **variable** nous incluons l'incertitude autour de la moyenne $\mu$ et de l'écart-type $\sigma$ de notre distribution gamma. Si notre distribution de la période d'incubation a une moyenne $\mu$ et un écart-type $\sigma$ nous supposons que la moyenne ($\mu$) suit une distribution normale avec un écart type $\sigma_{\mu}$: + +$$\mbox{Normal}(\mu,\sigma_{\mu}^2)$$ + +et un écart-type ($\sigma$) suit une distribution normale avec un écart type $\sigma_{\sigma}$: + +$$\mbox{Normal}(\sigma,\sigma_{\sigma}^2).$$ + +Nous spécifions ceci en utilisant `Normal()` pour chaque argument : la moyenne ($\mu = 4$ avec $\sigma_{\mu} = 0.5$) et l'écart-type ($\sigma = 2$ avec $\sigma_{\sigma} = 0.5$). + +```{r, warning=FALSE, message=FALSE} +incubation_period_variable <- EpiNow2::Gamma( + mean = EpiNow2::Normal(mean = 4, sd = 0.5), + sd = EpiNow2::Normal(mean = 2, sd = 0.5), + max = 20 +) + +incubation_period_variable +``` + +#### Retards dans l'établissement des rapports + +Après la période d'incubation, il s'écoule un délai supplémentaire entre l'apparition des symptômes et la notification du cas : le délai de déclaration. Nous pouvons le spécifier comme une distribution fixe ou variable, ou estimer une distribution à partir de données. + +Lorsque vous spécifiez une distribution, il est utile de visualiser la densité de probabilité pour voir le pic et l'étendue de la distribution. *log normale* normale. + +Si nous voulons supposer que le délai de déclaration moyen est de 2 jours (avec une incertitude de 0,5 jour) et que l'écart type est de 1 jour (avec une incertitude de 0,5 jour), nous pouvons spécifier une distribution variable à l'aide de la commande `LogNormal()` comme précédemment : + +```{r, warning=FALSE, message=FALSE} +reporting_delay_variable <- EpiNow2::LogNormal( + meanlog = EpiNow2::Normal(mean = 2, sd = 0.5), + sdlog = EpiNow2::Normal(mean = 1, sd = 0.5), + max = 10 +) +``` + +:::::::::::::::::::::: spoiler + +### Visualisez une distribution log-normale en utilisant {epiparameter} + +En utilisant `epiparameter::epiparameter()` nous pouvons créer une distribution personnalisée. La distribution normale à logarithme fixe aura l'aspect suivant : + +```r +library(epiparameter) +``` + +```{r, message=FALSE, warning=FALSE} +epiparameter::epiparameter( + disease = "covid", + epi_name = "reporting delay", + prob_distribution = + epiparameter::create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c( + meanlog = 2, + sdlog = 1 + ) + ) +) %>% + plot() +``` + +:::::::::::::::::::::: + +Nous pouvons tracer les distributions simples et combinées générées par `{EpiNow2}` en utilisant `plot()`. Combinons dans un même graphique le délai entre l'infection et la déclaration, qui comprend la période d'incubation et le délai de déclaration : + +```{r} +plot(incubation_period_variable + reporting_delay_variable) +``` + +:::::::::::::::::: callout + +Si l'on dispose de données sur le délai entre l'apparition des symptômes et la déclaration, on peut utiliser la fonction `estimate_delay()` pour estimer une distribution log-normale à partir d'un vecteur de délais. Le code ci-dessous illustre comment utiliser la fonction `estimate_delay()` avec des données synthétiques sur les délais. + +```{r, eval=FALSE} +delay_data <- rlnorm(500, log(5), 1) # synthetic delay data + +reporting_delay <- EpiNow2::estimate_delay( + delay_data, + samples = 1000, + bootstraps = 10 +) +``` + +:::::::::::::::::: + +#### Temps de génération + +Nous devons également spécifier une distribution pour le temps de génération. Nous utiliserons ici une distribution log-normale avec une moyenne de 3,6 et un écart-type de 3,1 ([Ganyani et al. 2020](https://doi.org/10.2807/1560-7917.ES.2020.25.17.2000257)). + +```{r, warning=FALSE, message=FALSE} +generation_time_variable <- EpiNow2::LogNormal( + mean = EpiNow2::Normal(mean = 3.6, sd = 0.5), + sd = EpiNow2::Normal(mean = 3.1, sd = 0.5), + max = 20 +) +``` + +## Trouver des estimations + +La fonction `epinow()` est une enveloppe pour la fonction `estimate_infections()` utilisée pour estimer les cas par date d'infection. La distribution du temps de génération et la distribution des délais doivent être transmises à l'aide des fonctions ` generation_time_opts()` et `delay_opts()` respectivement. + +Il existe de nombreuses autres entrées qui peuvent être transmises à `epinow()` voir `?EpiNow2::epinow()` pour plus de détails. +Une entrée optionnelle consiste à spécifier un *normale du journal* pour le nombre de reproduction effectif $R_t$ au début de l'épidémie. Nous spécifions une moyenne de 2 jours et un écart-type de 2 jours comme arguments de la commande `prior` dans `rt_opts()`: + +```{r, eval=TRUE} +# define Rt prior distribution +rt_prior <- EpiNow2::rt_opts(prior = EpiNow2::LogNormal(mean = 2, sd = 2)) +``` + +::::::::::::::::::::::::::::::::::::: callout + +### Inférence bayésienne à l'aide de Stan + +L'inférence bayésienne est réalisée à l'aide de méthodes MCMC avec le programme [Stan](https://mc-stan.org/). Les fonctions Stan disposent d'un certain nombre d'entrées par défaut, notamment le nombre de chaînes et le nombre d'échantillons par chaîne (voir `?EpiNow2::stan_opts()`). + +Pour réduire le temps de calcul, nous pouvons exécuter les chaînes en parallèle. Pour ce faire, nous devons définir le nombre de cœurs à utiliser. Par défaut, 4 chaînes MCMC sont exécutées (voir `stan_opts()$chains`), nous pouvons donc définir un nombre égal de cœurs à utiliser en parallèle comme suit : + +```{r, warning=FALSE, message=FALSE} +withr::local_options(base::list(mc.cores = 4)) +``` + +Pour connaître le nombre maximal de cœurs disponibles sur votre machine, utilisez la commande `parallel::detectCores()`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::: checklist + +**Note :** Dans le code ci-dessous `_fixed` les distributions sont utilisées à la place de `_variable` (distributions de retard avec incertitude). Cela permet d'accélérer le temps de calcul. Il est généralement recommandé d'utiliser des distributions variables qui tiennent compte d'une incertitude supplémentaire. + +```{r, echo=TRUE} +# fixed alternatives +generation_time_fixed <- EpiNow2::LogNormal( + mean = 3.6, + sd = 3.1, + max = 20 +) + +reporting_delay_fixed <- EpiNow2::LogNormal( + mean = 2, + sd = 1, + max = 10 +) +``` + +::::::::::::::::::::::::: + +Vous êtes maintenant prêt à exécuter `EpiNow2::epinow()` pour estimer le nombre de reproduction variable dans le temps pour les 90 premiers jours : + +```{r, message=FALSE, eval=TRUE, echo=TRUE} +estimates <- EpiNow2::epinow( + # reported cases + data = cases, + # delays + generation_time = EpiNow2::generation_time_opts(generation_time_fixed), + delays = EpiNow2::delay_opts(incubation_period_fixed + reporting_delay_fixed), + # prior + rt = rt_prior +) +``` + + + + + + + + + + + + + + + + + + + + + + + + + +::::::::::::::::::::::::::::::::: callout + +### N'attendez pas que cela se poursuive + +Pour les besoins de ce tutoriel, nous pouvons optionnellement utiliser `EpiNow2::stan_opts()` pour réduire le temps de calcul. Nous pouvons spécifier un nombre fixe de `samples = 1000` et `chains = 2` aux `stan` l'argument de la `EpiNow2::epinow()` de la fonction. Cette opération devrait prendre environ 3 minutes. + + + +```r +# you can add the `stan` argument +EpiNow2::epinow( + ..., + stan = EpiNow2::stan_opts(samples = 1000, chains = 3) +) +``` + +**Rappelez-vous :** En utilisant un nombre approprié de *échantillons* et *chaînes* est cruciale pour garantir la convergence et obtenir des estimations fiables dans les calculs bayésiens utilisant Stan. L'obtention de résultats plus précis se fait au détriment de la vitesse. + +::::::::::::::::::::::::::::::::: + +### Résultats + +Nous pouvons extraire et visualiser des estimations du nombre de reproductions effectives au fil du temps : + +```{r} +estimates$plots$R +``` + +L'incertitude des estimations augmente avec le temps. Cela s'explique par le fait que les estimations sont fondées sur des données antérieures, c'est-à-dire sur les périodes de retard. Cette différence d'incertitude est classée dans les catégories suivantes **Estimation** (vert) utilise toutes les données et **Estimation basée sur des données partielles** (orange) des estimations basées sur moins de données (parce que les infections qui se sont produites à l'époque sont plus susceptibles de ne pas avoir encore été observées) et qui ont donc des intervalles de plus en plus larges vers la date du dernier point de données. Enfin, les **Prévision** (violet) est une projection dans le temps. + +Nous pouvons également visualiser l'estimation du taux de croissance dans le temps : + +```{r} +estimates$plots$growth_rate +``` + +Pour extraire un résumé des principaux paramètres de transmission à l'échelle de l'Union européenne, il est possible d'utiliser les données de la base de données de l'Union européenne. *dernière date* dans les données : + +```{r} +summary(estimates) +``` + +Ces estimations étant basées sur des données partielles, elles présentent un large intervalle d'incertitude. + +- Le résumé de notre analyse montre que le changement attendu dans les déclarations est de `r summary(estimates)$estimate[summary(estimates)$measure=="Expected change in reports"]` avec l'estimation des nouvelles infections `r summary(estimates)$estimate[summary(estimates)$measure=="New infections per day"]`. + +- Le nombre effectif de reproduction $R_t$ (à la dernière date des données) est de `r summary(estimates)$estimate[summary(estimates)$measure=="Effective reproduction no."]`. + +- Le taux de croissance exponentiel du nombre de cas est de `r summary(estimates)$estimate[summary(estimates)$measure=="Rate of growth"]`. + +- Le temps de doublement (le temps nécessaire pour que le nombre de cas double) est de `r summary(estimates)$estimate[summary(estimates)$measure=="Doubling/halving time (days)"]`. + +::::::::::::::::::::::::::::::::::::: callout + +### `Expected change in reports` + +Un facteur décrivant l'évolution attendue des déclarations sur la base de la probabilité a posteriori que $R_t < 1$. + +
+| Probabilité ($p$) | Changement attendu ($p$) +| ------------- |-------------| +|p < 0.05$ |Augmentation |p < 0.05$ |Augmentation +| 0,05$ \leq p< 0,4$ |Augmentation probable | +| 0,4$ \leq p< 0,6$ |Stable | +| 0,6$ \leq p < 0,95$ |Vraisemblablement décroissante | +| 0,95$ \leq p \leq 1$ |Décroissante | +
+ +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::: callout + +### Intervalles crédibles + +En tout `{EpiNow2}` les régions ombrées reflètent les intervalles de crédibilité de 90 %, 50 % et 20 %, du plus clair au plus foncé. + +:::::::::::::::::::::::::: + +::::::::::: checklist + +`EpiNow2` peut être utilisé pour estimer les paramètres de transmission à partir des données relatives aux cas, à tout moment de l'évolution d'une épidémie. La fiabilité de ces estimations dépend de la qualité des données et du choix approprié des distributions de délais. Dans le prochain tutoriel, nous apprendrons à faire des prévisions et nous étudierons certaines des options d'inférence supplémentaires disponibles dans le logiciel `EpiNow2`. + +::::::::::: + +## Défi + +::::::::::::::::::: challenge + +**Quantifier l'hétérogénéité géographique** + +Les données relatives au début de la pandémie de COVID-19 au Royaume-Uni proviennent du paquetage R `{incidence2}` comprennent la région dans laquelle les cas ont été enregistrés. Pour obtenir des estimations régionales du nombre effectif de reproductions et de cas, nous devons formater les données de manière à ce qu'elles comportent trois colonnes : + +- `date` la date, +- `region`: la région, +- `confirm` le nombre de déclarations de maladies (confirmées) pour une région à une date donnée. + +Générer des estimations régionales de Rt à partir des `incidence2::covidregionaldataUK` à partir de la base de données : + +- utiliser `{incidence2}` pour convertir les données agrégées en données d'incidence par la variable `region`, +- conserver les 90 premières dates pour toutes les régions, +- estimer le Rt par région en utilisant le temps de génération défini et les retards dans cet épisode. + +```{r} +regional_cases <- incidence2::covidregionaldataUK %>% + # use {tidyr} to preprocess missing values + tidyr::replace_na(base::list(cases_new = 0)) +``` + +::::::::: hint + +Pour manipuler les données, vous pouvez + +```{r} +regional_cases <- incidence2::covidregionaldataUK %>% + # use {tidyr} to preprocess missing values + tidyr::replace_na(base::list(cases_new = 0)) %>% + # use {incidence2} to convert aggregated data to incidence data + incidence2::incidence( + date_index = "date", + groups = "region", + counts = "cases_new", + count_values_to = "confirm", + date_names_to = "date", + complete_dates = TRUE + ) %>% + dplyr::select(-count_variable) %>% + dplyr::filter(date < ymd(20200301)) +``` + +Pour apprendre à faire l'estimation régionale de Rt, lisez la section de la vignette "Get started" sur `regional_epinow()` à l'adresse + +::::::::: + +:::::::::::: solution + +Pour obtenir des estimations régionales, nous utilisons les mêmes données que celles utilisées pour l'estimation de l'indice des prix à la consommation (IPC). `epinow()` à la fonction `regional_epinow()`: + +```{r, message=FALSE, eval=FALSE} +estimates_regional <- EpiNow2::regional_epinow( + # cases + data = regional_cases, + # delays + generation_time = EpiNow2::generation_time_opts(generation_time_fixed), + delays = EpiNow2::delay_opts(incubation_period_fixed + reporting_delay_fixed), + # prior + rt = rt_prior +) +``` + +Tracez les résultats avec : + +```{r, message=FALSE, eval=FALSE} +estimates_regional$summary$summarised_results$table + +estimates_regional$summary$plots$R +``` + +![](fig/quantify-transmissibility-regional.png) + +:::::::::::: + +::::::::::::::::::: + + + + + + + +::::::::::::::::::::::::::::::::::::: keypoints + +- Les paramètres de transmission peuvent être estimés à partir des données du cas après prise en compte des retards. +- L'incertitude peut être prise en compte dans la distribution des retards. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/fr/episodes/severity-static.Rmd b/locale/fr/episodes/severity-static.Rmd new file mode 100644 index 00000000..6c78bd79 --- /dev/null +++ b/locale/fr/episodes/severity-static.Rmd @@ -0,0 +1,869 @@ +--- +title: Estimation de la gravité de l'épidémie +teaching: 10 +exercises: 2 +editor_options: + chunk_output_type: inline +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- Pourquoi estime-t-on la gravité clinique d'une épidémie ? + +- Comment peut-on estimer le risque de létalité (CFR) au début d'une épidémie en cours ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Estimez le risque de létalité à partir de données agrégées sur les cas en utilisant les éléments suivants `{cfr}`. + +- Estimez un CFR ajusté aux délais en utilisant `{epiparameter}` et `{cfr}`. + +- Estimez une sévérité ajustée au retard pour une série temporelle en expansion en utilisant `{cfr}`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +Cet épisode nécessite que vous soyez familier avec : + +**la science des données** Programmation de base avec R. + +**Théorie des épidémies**: [Distributions de délais](../learners/reference.md#delaydist). + +::::::::::::::::::::::::::::::::: + +## Introduction + +Au début d'une épidémie, les questions les plus fréquentes sont les suivantes : + +- Quel est l'impact probable de l'épidémie sur la santé publique en termes de gravité clinique ? +- Quels sont les groupes les plus gravement touchés ? +- L'épidémie risque-t-elle de provoquer une pandémie très grave ? + +Nous pouvons évaluer le potentiel pandémique d'une épidémie à l'aide de deux mesures essentielles : la transmissibilité et la gravité clinique. +([Fraser et al. 2009](https://www.science.org/doi/full/10.1126/science.1176062), +[CDC, 2016](https://www.cdc.gov/flu/pandemic-resources/national-strategy/severity-assessment-framework-508.html)). + +![HHS Pandemic Planning Scenarios based on the Pandemic Severity Assessment Framework. This uses a combined measure of clinical severity and transmissibility to characterise influenza pandemic scenarios. **HHS**: United States Department of Health and Human Services ([CDC, 2016](https://www.cdc.gov/flu/pandemic-resources/national-strategy/severity-assessment-framework-508.html)).](fig/cfr-hhs-scenarios-psaf.png){alt='The horizontal axis is the scaled measure of clinical severity, ranging from 1 to 7, where 1 is low, 4 is moderate, and 7 is very severe. The vertical axis is the scaled measure of transmissibility, ranging from 1 to 5, where 1 is low, 3 is moderate, and 5 is highly transmissible. On the graph, HHS pandemic planning scenarios are labeled across four quadrants (A, B, C and D). From left to right, the scenarios are “seasonal range,” “moderate pandemic,” “severe pandemic” and “very severe pandemic.” As clinical severity increases along the horizontal axis, or as transmissibility increases along the vertical axis, the severity of the pandemic planning scenario also increases.'} + +Une approche épidémiologique pour estimer la gravité clinique consiste à quantifier le risque de létalité (CFR). Le risque de létalité est la probabilité conditionnelle de décès en cas de diagnostic confirmé, calculée comme le rapport entre le nombre cumulé de décès dus à une maladie infectieuse et le nombre de cas diagnostiqués confirmés. Toutefois, le calcul de ce risque directement au cours d'une épidémie tend à aboutir à un CFR naïf ou biaisé, compte tenu de la durée de l'épidémie et de l'évolution de l'épidémie. [délai](../learners/reference.md#delaydist) entre l'apparition de la maladie et le décès, qui varie considérablement au fur et à mesure que l'épidémie progresse et se stabilise aux derniers stades de l'épidémie ([Ghani et al. 2005](https://academic.oup.com/aje/article/162/5/479/82647?login=false#620743)). + +![Estimations du risque de létalité (CFR) observé et confirmé biaisé en fonction du temps (ligne épaisse), calculé comme le nombre cumulé de cas de létalité confirmés. +L'estimation à la fin d'une épidémie (~30 mai) est le risque de létalité réalisé à la fin de l'épidémie. +La ligne horizontale continue et les lignes pointillées indiquent la valeur attendue et les intervalles de confiance à 95 % ($95%$ IC) de la valeur prédite du taux de mortalité ajusté au délai. +en utilisant uniquement les données observées jusqu'au 27 mars 2003. +([Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852))](fig/cfr-pone.0006852.g003-fig_c.png){fig-alt="Les périodes sont pertinentes : Période 1 -- 15 jours où le CFR est nul, ce qui indique qu'aucun décès n'a été signalé ; Période du 15 mars au 26 avril où le CFR semble augmenter ; Période du 30 avril au 30 mai où l'estimation du CFR se stabilise."} + +::::::::::::::::::::::: instructor + +Les périodes sont pertinentes : Période 1 -- 15 jours où le CFR est nul, ce qui indique qu'aucun décès n'a été signalé ; Période du 15 mars au 26 avril où le CFR semble augmenter ; Période du 30 avril au 30 mai où l'estimation du CFR se stabilise. + +::::::::::::::::::::::: + +Plus généralement, l'estimation de la gravité peut être utile même en dehors d'un scénario de planification d'une pandémie et dans le contexte de la santé publique courante. +Le fait de savoir si une épidémie a ou a eu une gravité différente de celle observée dans le passé peut motiver des recherches de causes, +qui pourraient être intrinsèques à l'agent infectieux (par exemple, une nouvelle souche plus grave) ou dues à des facteurs sous-jacents dans la population (par exemple, une immunité réduite ou des facteurs de morbidité) ([Lipsitch et al., 2015](https://journals.plos.org/plosntds/article?id=10.1371/journal.pntd.0003846)). + +Dans ce tutoriel, nous allons apprendre à utiliser la fonction `{cfr}` pour calculer et ajuster l'estimation d'un CFR à l'aide de l'outil [des distributions de retard](../learners/reference.md#delaydist) de `{epiparameter}` ou d'ailleurs, sur la base des méthodes développées par [Nishiura et al. 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) En outre, comment nous pouvons réutiliser les `{cfr}` pour des mesures plus sévères. + +Nous utiliserons le tuyau `%>%` pour connecter les fonctions, donc appelons aussi l'opérateur `{tidyverse}` au paquetage : + +```{r, message=FALSE, warning=FALSE} +library(cfr) +library(epiparameter) +library(tidyverse) +library(outbreaks) +``` + +::::::::::::::::::: checklist + +### Le double point-virgule + +Le double point-virgule `::` dans R vous permet d'appeler une fonction spécifique d'un paquetage sans charger l'ensemble du paquetage dans l'environnement actuel. + +Par exemple, vous pouvez appeler une fonction spécifique d'un package sans charger le package entier dans l'environnement actuel, `dplyr::filter(data, condition)` utilise `filter()` à partir de l'outil `{dplyr}` paquet. + +Cela nous permet de nous souvenir des fonctions du paquet et d'éviter les conflits d'espace de noms. + +::::::::::::::::::: + +:::::::::::::::::::: discussion + +Sur la base de votre expérience : + +- Faites part de toute épidémie antérieure à laquelle vous avez participé. + +Répondez à ces questions : + +- Comment avez-vous évalué la gravité clinique de l'épidémie ? +- Quelles ont été les principales sources de biais ? +- Qu'avez-vous fait pour prendre en compte les biais identifiés ? +- Quelle analyse complémentaire feriez-vous pour résoudre le biais ? + +:::::::::::::::::::: + +## Sources de données pour la gravité clinique + +Quelles sources de données pouvons-nous utiliser pour estimer la gravité clinique d'un foyer de maladie ? [Verity et al, 2020](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099\(20\)30243-7/fulltext) résume le spectre des cas de COVID-19 : + +![Spectre des cas de COVID-19. Le CFR vise à estimer la proportion de décès parmi les cas confirmés d'une épidémie. +([Verity et al., 2020](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099\(20\)30243-7/fulltext#gr1))](fig/cfr-spectrum-cases-covid19.jpg) + +- Au sommet de la pyramide, les personnes qui répondent aux critères de l'OMS en matière de **grave** ou critiques auraient probablement été identifiés en milieu hospitalier, présentant une pneumonie virale atypique. Ces cas auraient été identifiés en Chine continentale et parmi ceux classés au niveau international comme relevant d'une transmission locale. +- Il est probable que de nombreux autres cas aient été identifiés en Chine continentale. **symptomatiques** (c'est-à-dire avec de la fièvre, de la toux ou des myalgies), mais ne nécessiteront peut-être pas d'hospitalisation. Ces cas auraient été identifiés grâce à des liens avec des voyages internationaux dans des zones à haut risque et grâce à la recherche des contacts des cas confirmés. Ils pourraient être identifiés grâce à la surveillance de la population, par exemple en cas de syndrome grippal. +- La partie inférieure de la pyramide représente **les maladies bénignes** (et éventuellement **asymptomatique**). Ces cas pourraient être identifiés par la recherche des contacts et, par la suite, par des tests sérologiques. + +## CFR naïf + +Nous mesurons la gravité de la maladie en termes de risque de létalité (CFR). Le RCF est interprété comme la probabilité conditionnelle de décès en cas de diagnostic confirmé, calculée comme le ratio du nombre cumulé de décès $D_{t}$ sur le nombre cumulé de cas confirmés $C_{t}$ à un moment donné $t$. On peut se référer au *CFR naïf* (également CFR brut ou biaisé, $b_{t}$) : + +$$ b_{t} = \frac{D_{t}}{C_{t}} $$ + +Ce calcul est *naïf* car il tend à produire un TFC biaisé et largement sous-estimé en raison du délai entre l'apparition de la maladie et le décès, qui ne se stabilise qu'aux derniers stades de l'épidémie. + +Pour calculer le TFC naïf, le `{cfr}` a besoin d'un cadre de données d'entrée comportant trois colonnes nommées : + +- `date` +- `cases` +- `deaths` + +Explorons la base de données `ebola1976` inclus dans le paquet {cfr} qui provient de la première épidémie d'Ebola dans ce qui s'appelait alors le Zaïre (aujourd'hui la République démocratique du Congo) en 1976, comme l'ont analysé Camacho et al. (2014). + +```{r} +# Load the Ebola 1976 data provided with the {cfr} package +data("ebola1976") + +# Plot the incidence of cases and death reports +ebola1976 %>% + incidence2::incidence( + date_index = "date", + counts = c("cases", "deaths") + ) %>% + plot() +``` + +Nous replacerons cet épisode dans le contexte d'une épidémie d'Ebola. **épidémie en cours** avec seulement le **30 premiers jours** de données observées. + +```{r} +# Assume we only have the first 30 days of this data +ebola_30days <- ebola1976 %>% + dplyr::slice_head(n = 30) %>% + dplyr::as_tibble() + +ebola_30days +``` + +:::::::::::::::::: callout + +### Nous avons besoin de données agrégées sur l'incidence + +`{cfr}` lit **agrégé** données d'incidence. + + + +```{r, eval=FALSE, echo=FALSE} +EpiNow2::example_confirmed %>% + dplyr::as_tibble() +``` + +Cette entrée de données devrait être **agrégées** par jour, ce qui signifie qu'une observation *par jour* contenant les *quotidien* nombre quotidien de cas et de décès déclarés. Les observations comportant des valeurs nulles ou manquantes doivent également être incluses, comme pour les données de séries chronologiques. + +En outre, `{cfr}` fonctionne actuellement pour *tous les jours* mais pas pour d'autres unités temporelles d'agrégation de données, par exemple les semaines. + + + + + +:::::::::::::::::: + +Lorsque nous appliquons `cfr_static()` à `data` directement, nous calculons le CFR naïf : + +```{r} +# Calculate the naive CFR for the first 30 days +cfr::cfr_static(data = ebola_30days) +``` + +:::::::::::::::::::::::::::::::::::::::: challenge + +Téléchargez le fichier [sarscov2\_cases\_deaths.csv](data/sarscov2_cases_deaths.csv) et lisez-le dans R. + +Estimez le CFR naïf. + +:::::::::::::::::::: hint + +Contrôlez le format des données saisies. + +- Contient-il des données quotidiennes ? +- Les noms des colonnes sont-ils conformes aux exigences de la `cfr_static()`? +- Comment renommer les noms de colonnes d'une base de données ? + +:::::::::::::::::::: + +:::::::::::::::::::: solution + +Nous lisons les données saisies à l'aide de `readr::read_csv()`. Cette fonction reconnaît que la colonne `date` est une `` vecteur de classe. + +```{r, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE} +# read data from the tutorial repository R project +sarscov2_input <- + readr::read_csv(file.path("data", "sarscov2_cases_deaths.csv")) +``` + +```{r, eval=FALSE, echo=TRUE, warning=FALSE, message=FALSE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +sarscov2_input <- + readr::read_csv(here::here("data", "raw-data", "sarscov2_cases_deaths.csv")) +``` + +```{r} +# Inspect data +sarscov2_input +``` + +Nous pouvons utiliser `dplyr::rename()` pour adapter les données externes aux données d'entrée de l'application `cfr_static()`. + +```{r} +# Rename before Estimate naive CFR +sarscov2_input %>% + dplyr::rename( + cases = cases_jpn, + deaths = deaths_jpn + ) %>% + cfr::cfr_static() +``` + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: + +## Biais affectant l'estimation du CFR + +::::::::::::::::::::::::::::: discussion + +### Deux biais qui affectent l'estimation du CFR + +[Lipsitch et al, 2015](https://journals.plos.org/plosntds/article?id=10.1371/journal.pntd.0003846) décrivent deux biais potentiels qui peuvent affecter l'estimation de la CFR (et leurs solutions potentielles) : + +::::::::::::::::::::::::::::: + +::::::::::::: solution + +### 1\. Vérification préférentielle des cas graves + +Pour les maladies ayant un *spectre* de présentations cliniques, les cas qui sont portés à l'attention des autorités de santé publique et enregistrés dans les bases de données de surveillance sont généralement des personnes présentant les symptômes les plus graves, qui consultent un médecin, sont admises à l'hôpital ou décèdent. + +Par conséquent, le TFC est généralement plus élevé chez les personnes qui présentent les symptômes les plus graves. *cas détectés* que dans l'ensemble de la population des cas, étant donné que cette dernière peut inclure des personnes présentant des symptômes légers, subcliniques et (selon certaines définitions de "cas") asymptomatiques. + +::::::::::::: + +:::::::::::: solution + +### 2\. Biais dû à une déclaration tardive du décès + +Au cours d'une *en cours* Il y a un délai entre le moment où une personne décède et le moment où son décès est signalé. Par conséquent, à tout moment, la liste des cas comprend des personnes qui vont mourir et dont le décès n'est pas encore survenu ou qui est survenu mais n'a pas encore été signalé. Par conséquent, la division du nombre cumulé de décès déclarés par le nombre cumulé de cas déclarés à un moment précis d'une épidémie sous-estimera le véritable TFC. + +Les principaux facteurs déterminants de l'ampleur du biais sont l'épidémie, le nombre de décès et le nombre de cas. *taux de croissance de l'* et le *distribution des retards* entre la déclaration des cas et la déclaration des décès ; plus les délais sont longs et plus le taux de croissance est rapide, plus le biais est important. + +Dans cet épisode du tutoriel, nous allons nous concentrer sur les solutions pour traiter ce biais spécifique en utilisant `{cfr}`! + +:::::::::::: + +:::::::::::::::::::: solution + +### Étude de cas : Grippe A (H1N1), Mexique, 2009 + +Amélioration d'une *précoce* L'amélioration de l'évaluation épidémiologique précoce d'un TFC ajusté au retard est cruciale pour déterminer la virulence, déterminer le niveau et les choix de l'intervention de santé publique et fournir des conseils au grand public. + +En 2009, lors de l'épidémie de grippe porcine A (H1N1), le Mexique a bénéficié d'une estimation précoce biaisée du RCF. Les premiers rapports du gouvernement mexicain faisaient état d'une infection virulente, alors que dans d'autres pays, le même virus était perçu comme bénin ([TIME, 2009](https://content.time.com/time/health/article/0,8599,1894534,00.html)). + +Aux États-Unis et au Canada, aucun décès n'a été attribué au virus dans les dix jours qui ont suivi la déclaration d'urgence de santé publique par l'Organisation mondiale de la santé. Même dans des circonstances similaires, au début de la pandémie mondiale, les responsables de la santé publique, les décideurs et le grand public veulent connaître la virulence d'un agent infectieux émergent. + +[Fraser et al, 2009](https://www.science.org/doi/full/10.1126/science.1176062) a réinterprété les données en évaluant les biais et en obtenant une gravité clinique inférieure à celle de la pandémie de grippe de 1918, mais comparable à celle observée lors de la pandémie de 1957. + +:::::::::::::::::::: + +:::::::::::::::::::: instructor + +Nous pouvons mettre en évidence ce dernier biais à l'aide de l'outil [concept décrit dans ce `{cfr}` vignette](https://epiverse-trace.github.io/cfr/articles/cfr.html#concept-how-reporting-delays-bias-cfr-estimates). + + + +:::::::::::::::::::: + +## CFR ajusté au retard + +[Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) a développé une méthode qui prend en compte les **délai** entre l'apparition des symptômes et le décès. + +Les épidémies en temps réel peuvent avoir un nombre de décès insuffisant pour déterminer la distribution du temps entre l'apparition des symptômes et le décès. Par conséquent, nous pouvons estimer la distribution du temps entre l'apparition des symptômes et le décès. *délai de distribution* à partir d'épidémies historiques ou réutiliser celles qui sont accessibles via des packages R tels que `{epiparameter}` ou `{epireview}` qui les collectent à partir de la littérature scientifique publiée. Pour un guide étape par étape, lisez l'épisode du tutoriel sur la façon de [accéder aux retards épidémiologiques](https://epiverse-trace.github.io/tutorials-early/delays-reuse.html). + +Utilisons `{epiparameter}`: + +```{r, message=FALSE, warning=FALSE} +# Get delay distribution +onset_to_death_ebola <- + epiparameter::epiparameter_db( + disease = "Ebola", + epi_name = "onset_to_death", + single_epiparameter = TRUE + ) + +# Plot object +plot(onset_to_death_ebola, day_range = 0:40) +``` + +Pour calculer le CFR corrigé des retards, nous pouvons utiliser l'équation suivante `cfr_static()` avec la fonction `data` et `delay_density` arguments. + +```{r} +# Calculate the delay-adjusted CFR +# for the first 30 days +cfr::cfr_static( + data = ebola_30days, + delay_density = function(x) density(onset_to_death_ebola, x) +) +``` + +```{r, echo=FALSE} +out_delay_adjusted <- + cfr::cfr_static( + data = ebola_30days, + delay_density = function(x) density(onset_to_death_ebola, x) + ) + +out_estimate <- out_delay_adjusted %>% pull(severity_estimate) +out_low <- out_delay_adjusted %>% pull(severity_low) +out_high <- out_delay_adjusted %>% pull(severity_high) +``` + +Le CFR ajusté en fonction des délais a indiqué que la gravité globale de la maladie *à la fin de l'épidémie* ou avec le *dernières données disponibles à ce moment-là* est `r out_estimate` avec un intervalle de confiance de 95 % entre `r out_low` et `r out_high` soit une valeur légèrement supérieure à la valeur naïve. + +:::::::::::::::::: callout + +### Utilisez la classe d'épiparamètres + +Lorsque vous utilisez un `` nous pouvons utiliser cette expression comme modèle : + +`function(x) density(, x)` + +Pour les fonctions de distribution dont les paramètres ne sont pas disponibles dans `{epiparameter}` nous vous proposons deux alternatives : + +- Créez un `` pour l'intégrer dans d'autres paquets R du pipeline d'analyse de l'épidémie. Lisez l'article [documentation de référence de `epiparameter::epiparameter()`](https://epiverse-trace.github.io/epiparameter/reference/epiparameter.html) ou + +- Lisez `{cfr}` vignette pour [une introduction à l'utilisation des distributions de retard](https://epiverse-trace.github.io/cfr/articles/delay_distributions.html). + +:::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: challenge + +Utilisez le même fichier que celui du défi précédent ([sarscov2\_cases\_deaths.csv](data/sarscov2_cases_deaths.csv)). + +Estimez le TFC ajusté au délai en utilisant le délai de distribution approprié. Dans ce cas : + +- Comparez les solutions du CFR naïf et du CFR ajusté au retard ! + +:::::::::::::::::::: hint + +- Trouvez la solution `` approprié ! + +:::::::::::::::::::: + +:::::::::::::::::::: solution + +Nous utilisons `{epiparameter}` pour accéder à une distribution des retards pour les données d'incidence agrégées du SRAS-CoV-2 : + +```{r, message=FALSE, warning=FALSE} +library(epiparameter) + +sarscov2_delay <- + epiparameter::epiparameter_db( + disease = "covid", + epi_name = "onset to death", + single_epiparameter = TRUE + ) +``` + +Nous lisons les données en utilisant `readr::read_csv()`. Cette fonction reconnaît que la colonne `date` est une `` vecteur de classe. + +```{r, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE} +# read data from the tutorial repository R project +sarscov2_input <- + readr::read_csv(file.path("data", "sarscov2_cases_deaths.csv")) +``` + +```{r, eval=FALSE, echo=TRUE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +sarscov2_input <- + readr::read_csv(here::here("data", "raw-data", "sarscov2_cases_deaths.csv")) +``` + +```{r} +# Inspect data +sarscov2_input +``` + +Nous pouvons utiliser `dplyr::rename()` pour adapter les données externes aux données d'entrée de l'application `cfr_static()`. + +```{r} +# Rename before Estimate naive CFR +sarscov2_input %>% + dplyr::rename( + cases = cases_jpn, + deaths = deaths_jpn + ) %>% + cfr::cfr_static( + delay_density = function(x) density(sarscov2_delay, x) + ) +``` + +Interprétez la comparaison entre les estimations naïves et les estimations corrigées des retards. + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::: spoiler + +### Quand utiliser les distributions discrètes ? + +Pour les `cfr_static()` et toutes les `cfr_*()` les choix les plus appropriés à faire sont les suivants **discrets** discrètes. En effet, nous travaillerons avec des données quotidiennes sur les cas et les décès. + +Nous pouvons supposer que l'évaluation de la fonction de distribution de probabilité (PDF) d'un *continue* est équivalente à la fonction de masse de probabilité (FMP) de la distribution continue équivalente. *discrète* discrète équivalente. + +Toutefois, cette hypothèse peut ne pas être appropriée pour les distributions présentant des pics plus importants. C'est le cas, par exemple, des maladies dont la distribution de l'apparition à la mort présente un pic important et une faible variance. Dans ce cas, la disparité moyenne entre la PDF et la PMF devrait être plus prononcée que pour les distributions dont les écarts sont plus importants. Une façon d'y remédier est de discrétiser la distribution continue en utilisant la méthode `epiparameter::discretise()` à une `` objet. + +:::::::::::::::::: + +::::::::::::::::::::::::::: spoiler + +### Comment le {cfr} fonctionne ? + +Pour ajuster le CFR, [Nishiura et al. 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) utilisent les données d'incidence des cas et des décès pour estimer le nombre de cas dont les résultats sont connus : + +$$ +u_t = \dfrac{\sum_{i = 0}^t +\sum_{j = 0}^\infty c_{i - j} f_{j}}{\sum_{i = 0} c_i}, +$$ + +où : + +- $c_{t}$ est l'incidence quotidienne des cas au moment $t$, +- $f_{t}$ est la valeur de la fonction de masse de probabilité (FMP) de l'échantillon. **distribution des retards** entre l'apparition et le décès, et +- $u_{t}$ représente le facteur de sous-estimation des résultats connus. + +$u_{t}$ est utilisé pour **mettre à l'échelle** la valeur du nombre cumulé de cas au dénominateur dans le calcul du CFR. Ce calcul est effectué en interne à l'aide de l'outil [`estimate_outcomes()`](https://epiverse-trace.github.io/cfr/reference/estimate_outcomes.html) fonction. + +L'estimateur de la CFR peut être écrit comme suit : + +$$p_{t} = \frac{b_{t}}{u_{t}}$$ + +où $p_{t}$ est la proportion réalisée de cas confirmés qui meurent de l'infection (ou le TFC non biaisé), et $b_{t}$ est l'estimation brute et biaisée du RCF (ou RCF naïf). + +D'après cette dernière équation, nous observons que le TFC non biaisé $p_{t}$ est plus important que le CFR biaisé $b_{t}$ biaisé, car en $u_{t}$ le numérateur est plus petit que le dénominateur (notez que $f_{t}$ est la distribution de probabilité de la *distribution des retards* entre l'apparition et le décès). Par conséquent, nous nous référons à $b_{t}$ comme l'estimateur biaisé du CFR. + +Lorsque nous observons l'ensemble de l'évolution d'une épidémie (de $t \rightarrow \infty$), $u_{t}$ tend vers 1, ce qui fait que $b_{t}$ tend à $p_{t}$ et devient un estimateur sans biais ([Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852)). + +::::::::::::::::::::::::::: + +## Estimation du CFR à un stade précoce + +L'estimation **naïf** est utile pour obtenir une estimation globale de la gravité de l'épidémie (jusqu'à présent). Une fois que l'épidémie est terminée ou qu'elle a progressé de telle sorte que davantage de décès sont signalés, le TFC estimé est alors le plus proche du "véritable" TFC non biaisé. + +Par ailleurs, le **corrigé des délais** peut évaluer la gravité d'une maladie infectieuse émergente. *plus tôt* que le RCF biaisé ou naïf, au cours d'une épidémie. + +Nous pouvons explorer les **précoce** détermination de la *CFR corrigé des retards* à l'aide de la méthode `cfr_rolling()` fonction. + +:::::::::::::::::::::: callout + +`cfr_rolling()` est une fonction utilitaire qui calcule automatiquement le CFR pour chaque jour de l'épidémie à l'aide des données disponibles jusqu'à ce jour, ce qui permet à l'utilisateur de gagner du temps. + +:::::::::::::::::::::: + +`cfr_rolling()` montre le CFR estimé pour chaque jour de l'épidémie, étant donné que les données futures sur les cas et les décès ne sont pas disponibles à ce moment-là. La valeur finale de `cfr_rolling()` est identique à celle de `cfr_static()` pour les mêmes données. + +```{r} +# for all the 73 days in the Ebola dataset +# Calculate the rolling daily naive CFR +rolling_cfr_naive <- cfr::cfr_rolling(data = ebola1976) +``` + +```{r} +# for all the 73 days in the Ebola dataset +# Calculate the rolling daily delay-adjusted CFR +rolling_cfr_adjusted <- cfr::cfr_rolling( + data = ebola1976, + delay_density = function(x) density(onset_to_death_ebola, x) +) +``` + +Avec `utils::tail()` nous montrons que les dernières estimations du CFR. Les intervalles de confiance à 95 % des estimations naïves et corrigées des retards se chevauchent. + +```{r, eval=FALSE, echo=TRUE} +# Print the tail of the data frame +utils::tail(rolling_cfr_naive) +utils::tail(rolling_cfr_adjusted) +``` + +Visualisons maintenant les deux résultats dans une série chronologique. Quelle serait la performance en temps réel des estimations naïves et des estimations corrigées des retards ? + +```{r, echo=TRUE, warning=FALSE, message=FALSE} +# bind by rows both output data frames +dplyr::bind_rows( + list( + naive = rolling_cfr_naive, + adjusted = rolling_cfr_adjusted + ), + .id = "method" +) %>% + # visualise both adjusted and unadjusted rolling estimates + ggplot() + + geom_ribbon( + aes( + date, + ymin = severity_low, + ymax = severity_high, + fill = method + ), + alpha = 0.2, show.legend = FALSE + ) + + geom_line( + aes(date, severity_estimate, colour = method) + ) +``` + +La ligne horizontale représente le TFC ajusté au retard estimé à la fin de l'épidémie. La ligne en pointillé signifie que l'estimation a un intervalle de confiance de 95 % (IC 95 %). + +**Avis** Notez que ce calcul ajusté en fonction du délai est particulièrement utile lorsqu'une *courbe épidémique de cas confirmés* est la seule donnée disponible (c'est-à-dire lorsque les données individuelles depuis l'apparition jusqu'au décès ne sont pas disponibles, en particulier au début de l'épidémie). Lorsqu'il y a peu ou pas de décès, une hypothèse doit être faite pour la courbe épidémique des cas confirmés. *distribution des délais* entre l'apparition et le décès, par exemple à partir de la littérature basée sur les épidémies précédentes. [Nishiura et al. 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) illustrent ce phénomène dans les figures à l'aide de données relatives à l'épidémie de SRAS survenue à Hong Kong en 2003. + +:::::::::::::::::::::::::::::::::: spoiler + +### Étude de cas : Épidémie de SRAS, Hong Kong, 2003 + +Les figures A et B montrent les nombres cumulés de cas et de décès dus au SRAS, et la figure C montre les estimations observées (biaisées) du CFR en fonction du temps, c'est-à-dire le nombre cumulé de décès par rapport au nombre de cas à l'heure $t$. En raison du délai entre l'apparition des symptômes et le décès, l'estimation biaisée du RCF au temps $t$ sous-estime le TFC réalisé à la fin d'une épidémie (302/1755 = 17,2 %). + +![Risque observé (biaisé) de létalité des cas confirmés du syndrome respiratoire aigu sévère (SRAS) à Hong Kong, 2003. ([Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852))](fig/cfr-pone.0006852.g003-fig_abc.png) + +Néanmoins, même en n'utilisant que les données observées pour la période du 19 mars au 2 avril, `cfr_static()` peut produire une prédiction appropriée (figure D), par exemple le TFC ajusté au retard au 27 mars est de 18,1 % (IC 95 % : 10,5, 28,1). Une surestimation est observée au tout début de l'épidémie, mais les limites de confiance à 95 % pour les phases ultérieures incluent le TFC réalisé (c'est-à-dire 17,2 %). + +![Détermination précoce du risque de létalité confirmé, ajusté au délai, du syndrome respiratoire aigu sévère (SRAS) à Hong Kong, 2003. ([Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852))](fig/cfr-pone.0006852.g003-fig_d.png) + +:::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::: discussion + +### Interpréter l'estimation de la CFR à un stade précoce + +Sur la base de la figure ci-dessus : + +- Quelle est la différence en jours entre la date à laquelle l'IC à 95 % de la valeur estimée du *estimé ajusté aux retards* estimé corrigé des retards par rapport à l'IC 95 % de l'IC 95 %. *CFR naïf* avec le CFR estimé à la fin de l'épidémie ? + +Discutez-en : + +- Quelles sont les implications en matière de politique de santé publique d'une *CFR ajusté au retard* corrigée des retards ? + +:::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::: hint + +Nous pouvons utiliser l'inspection visuelle ou l'analyse des trames de données de sortie. + +:::::::::::::::::::::: + +:::::::::::::::::::::: solution + +Il y a presque un mois de différence. + +Notez que l'estimation présente une incertitude considérable au début de la série chronologique. Après deux semaines, le CFR corrigé des retards se rapproche de l'estimation globale du CFR à la fin de l'épidémie. + +Ce schéma est-il similaire à celui d'autres épidémies ? Nous pouvons utiliser les ensembles de données dans les défis de cet épisode. Nous vous invitons à le découvrir ! + +:::::::::::::::::::::: + +:::::::::::::::::::::: discussion + +### Liste de contrôle + +Avec `{cfr}` nous estimons le CFR comme la proportion de décès parmi les **confirmés** confirmés. + +En n'utilisant que des **confirmé** il est clair que tous les cas qui ne cherchent pas de traitement médical ou qui ne sont pas notifiés ne sont pas pris en compte, de même que tous les cas asymptomatiques. Cela signifie que l'estimation du CFR est plus élevée que la proportion de décès parmi les personnes infectées. + +:::::::::::::::::::::: + +::::::::::::::::::::::::::: solution + +### Pourquoi les estimations naïves et ajustées aux délais diffèrent-elles ? + +`{cfr}` La méthode naïve vise à obtenir un estimateur non biaisé "bien avant" d'observer l'ensemble de l'évolution de l'épidémie. Pour ce faire, `{cfr}` utilise le facteur de sous-estimation $u_{t}$ pour estimer le CFR non biaisé $p_{t}$ à l'aide de la méthode du maximum de vraisemblance, étant donné que le *processus d'échantillonnage* défini par [Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852). + +::::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solution + +### Qu'est-ce que le processus d'échantillonnage ? + +![La population des cas confirmés et le processus d'échantillonnage pour l'estimation du TFC non biaisé au cours d'une épidémie. ([Nishiura et al. 2009](https://doi.org/10.1371/journal.pone.0006852.g001))](fig/cfr-pone.0006852.g001.png) + +De *données d'incidence agrégées* au moment $t$ nous connaissons le nombre cumulé de cas confirmés et de décès, $C_{t}$ et $D_{t}$ et souhaitons estimer le CFR non biaisé $\pi$ sans biais, au moyen du facteur de sous-estimation $u_{t}$. + +Si nous connaissions le facteur de sous-estimation $u_{t}$ nous pourrions préciser la taille de la population des cas confirmés qui ne sont plus à risque ($u_{t}C_{t}$, **ombré**), bien que nous ne sachions pas quels individus survivants appartiennent à ce groupe. Une proportion $\pi$ de ceux qui font partie du groupe de cas encore à risque (taille $(1- u_{t})C_{t}$, **non ombré**) devrait mourir. + +Parce que chaque cas qui n'est plus à risque a une probabilité indépendante de mourir, $\pi$ le nombre de décès, $D_{t}$ est un échantillon d'une distribution binomiale avec une taille d'échantillon de $u_{t}C_{t}$ et la probabilité de décès $p_{t}$ = $\pi$. + +Ceci est représenté par la fonction de vraisemblance suivante pour obtenir l'estimation du maximum de vraisemblance de la CRF non biaisée $p_{t}$ = $\pi$: + +$$ +{\sf L}(\pi | C_{t},D_{t},u_{t}) = \log{\dbinom{u_{t}C_{t}}{D_{t}}} + D_{t} \log{\pi} + +(u_{t}C_{t} - D_{t})\log{(1 - \pi)}, +$$ + +Cette estimation est réalisée par la fonction interne `?cfr:::estimate_severity()`. + +:::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solution + +### Limitations + +- Le TFC ajusté aux délais ne tient pas compte de toutes les sources d'erreur dans les données, comme le sous-diagnostic des personnes infectées. + +:::::::::::::::::::::::::: + +## Défis + +:::::::::::::::::::::::::::::::: discussion + +### Plus de mesures de sévérité + +Supposons que nous ayons besoin d'évaluer la gravité clinique de l'épidémie dans un contexte différent des données de surveillance, comme la gravité parmi les cas qui arrivent à l'hôpital ou les cas que vous avez recueillis lors d'une enquête sérologique représentative. + +En utilisant `{cfr}` nous pouvons modifier les entrées du numérateur (`cases`) et du dénominateur (`deaths`) pour estimer des mesures plus sévères comme le risque d'infection mortelle (IFR) ou le risque d'hospitalisation mortelle (HFR). Nous pouvons suivre cette analogie : + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::: solution + +### Risque de létalité lié à l'infection et à l'hospitalisation + +Si pour une *cas* risque de décès (CFR), nous exigeons : + +- *cas* les données sur l'incidence des cas et des décès, avec une +- distribution des délais entre les cas et les décès (ou une approximation proche, comme le délai entre l'apparition des symptômes et le décès). + +Dans ce cas, le *d'infection* risque de létalité (IFR) : + +- *l'infection* les données sur l'incidence des infections et des décès, avec une +- distribution des délais entre l'exposition et le décès (ou une approximation proche). + +De la même manière, la distribution des délais d'exposition au décès (ou une approximation proche). *Hospitalisation* Fatality Risk (HFR) exige : + +- *une hospitalisation* d'hospitalisation et de décès, ainsi qu'une +- distribution des délais entre l'hospitalisation et le décès. + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::: solution + +### Sources de données pour d'autres mesures de la gravité + +[Yang et al, 2020](https://www.nature.com/articles/s41467-020-19238-2/figures/1) résume les différentes définitions et sources de données : + +![Niveaux de gravité des infections par le SRAS-CoV-2 et paramètres d'intérêt. Chaque niveau est supposé être un sous-ensemble du niveau inférieur.](fig/cfr-s41467-020-19238-2-fig_a.png) + +- sCFR risque de létalité symptomatique, +- sCHR risque d'hospitalisation symptomatique, +- mCFR risque de létalité des cas médicalement assistés, +- mCHR risque d'hospitalisation d'un cas médicalement pris en charge, +- HFR risque d'hospitalisation et de mortalité. + +![Schéma des analyses de base. Les flèches rouges, bleues et vertes indiquent le flux de données provenant des cas confirmés en laboratoire dans le cadre de la surveillance passive, des cas diagnostiqués cliniquement et des cas confirmés en laboratoire dans le cadre des dépistages actifs.](fig/cfr-s41467-020-19238-2-fig_b.png){fig-alt="Source des données sur les cas de COVID-19 à Wuhan : D1) 32 583 cas de COVID-19 confirmés en laboratoire en mars 84, D2) 17 365 cas de COVID-19 diagnostiqués cliniquement entre le 9 février et le 24 avril, D3) nombre quotidien de cas confirmés en laboratoire entre le 9 mars et le 24 avril, D4) nombre total de décès dus au COVID-19 en date du 24 avril, obtenus auprès de la Commission de la santé du Hubei3, D5) 325 cas confirmés en laboratoire et D6) 1 290 décès ont été ajoutés au 16 avril grâce à une vérification complète et systématique effectuée par les autorités de Wuhan3, et D7) 16 781 cas confirmés en laboratoire identifiés par le biais d'un dépistage universel10,11. Pse : sensibilité de la RT-PCR12. Pmed.care : proportion de patients souffrant d'infections respiratoires aiguës qui demandent une assistance médicale13."} + +:::::::::::::::::::::::::::: + +::::::::::::::::: callout + +### Les données agrégées diffèrent des listes de diffusion + +*Données agrégées* Les données sur l'incidence diffèrent des **liste de référence** où chaque observation contient des données au niveau individuel. + +```{r} +outbreaks::ebola_sierraleone_2014 %>% as_tibble() +``` + +::::::::::::::::: + +:::::::::::::::::::::::::::::::::: challenge + +### Utilisez incidence2 pour réorganiser vos données + +A partir de la `{outbreaks}` chargez la liste des cas de MERS à partir de la base de données du `mers_korea_2015` l'objet. + +Réorganisez cette liste pour qu'elle s'insère dans l'espace de travail de l'objet. `{cfr}` l'entrée du paquet. + +Estimez le CFR ajusté au délai en utilisant le délai de distribution correspondant. + +::::::::::::::::: hint + +**Comment réorganiser mes données d'entrée ?** + +Le réarrangement des données d'entrée pour l'analyse des données peut prendre beaucoup de temps. Pour être prêt à analyser *données d'incidence agrégées* nous vous encourageons à utiliser `{incidence2}`! + +Tout d'abord, dans le [Commencez](https://www.reconverse.org/incidence2/articles/incidence2.html) de la rubrique `{incidence2}` explore l'utilisation de l'outil `date_index` lors de la lecture d'une liste de lignes contenant des dates dans plusieurs colonnes. + +Ensuite, référez-vous à l'outil `{cfr}` manuel de référence sur les [Préparer des formats de données épidémiologiques communs pour l'estimation du CFR](https://epiverse-trace.github.io/cfr/reference/prepare_data.html) sur la façon d'utiliser le `cfr::prepare_data()` à partir des objets incidence2. + + + +::::::::::::::::: + +::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +# Load packages +library(cfr) +library(epiparameter) +library(incidence2) +library(outbreaks) +library(tidyverse) + +# Access delay distribution +mers_delay <- + epiparameter::epiparameter_db( + disease = "mers", + epi_name = "onset to death", + single_epiparameter = TRUE + ) + +# Read linelist +mers_korea_2015$linelist %>% + as_tibble() %>% + select(starts_with("dt_")) + +# Use {incidence2} to count daily incidence +mers_incidence <- mers_korea_2015$linelist %>% + # converto to incidence2 object + incidence(date_index = c("dt_onset", "dt_death")) %>% + # complete dates from first to last + incidence2::complete_dates() + +# Inspect incidence2 output +mers_incidence + +# Prepare data from {incidence2} to {cfr} +mers_incidence %>% + prepare_data( + cases_variable = "dt_onset", + deaths_variable = "dt_death" + ) + +# Estimate delay-adjusted CFR +mers_incidence %>% + cfr::prepare_data( + cases_variable = "dt_onset", + deaths_variable = "dt_death" + ) %>% + cfr::cfr_static(delay_density = function(x) density(mers_delay, x)) +``` + +::::::::::::::::: + +:::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::: challenge + +### Hétérogénéité de la gravité + +Le RCF peut différer d'une population à l'autre (par exemple, âge, espace, traitement) ; la quantification de ces hétérogénéités peut aider à cibler les ressources de manière appropriée et à comparer différents régimes de soins ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +Utilisez le `cfr::covid_data` pour estimer un TFC ajusté aux retards, stratifié par pays. + +::::::::::::::::::::::::: hint + +Une façon d'effectuer une *analyse stratifiée* consiste à appliquer un modèle à des données imbriquées. Cette analyse stratifiée est une méthode qui consiste à appliquer un modèle à des données imbriquées. [`{tidyr}` vignette](https://tidyr.tidyverse.org/articles/nest.html#nested-data-and-models) vous montre comment appliquer la méthode `group_by()` + `nest()` aux données de nidification, puis `mutate()` + `map()` pour appliquer le modèle. + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +library(cfr) +library(epiparameter) +library(tidyverse) + +covid_data %>% glimpse() + +delay_onset_death <- + epiparameter::epiparameter_db( + disease = "covid", + epi_name = "onset to death", + single_epiparameter = TRUE + ) + +covid_data %>% + group_by(country) %>% + nest() %>% + mutate( + temp = + map( + .x = data, + .f = cfr::cfr_static, + delay_density = function(x) density(delay_onset_death, x) + ) + ) %>% + unnest(cols = temp) +``` + +C'est génial ! Vous pouvez maintenant utiliser un code similaire pour toute autre analyse stratifiée comme l'âge, les régions ou autres ! + +Mais comment pouvons-nous interpréter qu'il existe une variabilité nationale de la gravité pour un même agent pathogène diagnostiqué ? + +Des facteurs locaux tels que la capacité de test, la définition de cas et le régime d'échantillonnage peuvent influer sur la déclaration des cas et des décès, et donc sur la détermination des cas. Jetez un coup d'œil à la base de données de l'OMS sur les maladies infectieuses. `{cfr}` vignette sur [Estimation de la proportion de cas confirmés au cours d'une épidémie](https://epiverse-trace.github.io/cfr/articles/estimate_ascertainment.html)! + +::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +## Annexe + +L'annexe `{cfr}` possède une fonction appelée `cfr_time_varying()` dont la fonctionnalité diffère de celle de `cfr_rolling()`. + +::::::::::::::::: callout + +### Quand utiliser cfr\_rolling() ? + +`cfr_rolling()` montre le CFR estimé pour chaque jour d'épidémie, étant donné que les données futures sur les cas et les décès ne sont pas disponibles à ce moment-là. La valeur finale de `cfr_rolling()` est identique à celle de `cfr_static()` pour les mêmes données. + +Rappelez-vous, comme indiqué ci-dessus, `cfr_rolling()` est utile pour obtenir des estimations du CFR à un stade précoce et vérifier si l'estimation du CFR d'un foyer s'est stabilisée. C'est pourquoi, `cfr_rolling()` n'est pas sensible à la durée ou à la taille de l'épidémie. + +::::::::::::::::: + +::::::::::::::::: callout + +### Quand utiliser `cfr_time_varying()`? + +D'autre part, `cfr_time_varying()` calcule le CFR sur une fenêtre mobile et aide à comprendre les variations du CFR dues à des changements dans l'épidémie, par exemple en raison d'une nouvelle variante ou d'une immunité accrue due à la vaccination. + +Cependant, `cfr_time_varying()` est sensible à l'incertitude de l'échantillonnage. Il est donc sensible à la taille de l'épidémie. Plus le nombre de cas avec des résultats attendus un jour donné est élevé, plus nous obtiendrons des estimations raisonnables du TFC variable dans le temps. + +Par exemple, avec 100 cas, l'estimation du risque de décès aura, grosso modo, un intervalle de confiance de 95 % ± 10 % de l'estimation moyenne (IC binomial). Donc, si nous avons >100 cas avec des résultats attendus *un jour donné* nous pouvons obtenir des estimations raisonnables du RCF variable dans le temps. Mais si nous n'avons que >100 cas *sur toute la durée de l'épidémie* nous devrons probablement nous appuyer sur les `cfr_rolling()` qui utilise les données cumulées. + +Nous vous invitons à lire ce document [vignette sur la `cfr_time_varying()` fonction](https://epiverse-trace.github.io/cfr/articles/estimate_time_varying_severity.html). + +::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utiliser `{cfr}` pour estimer la gravité + +- Utilisation `cfr_static()` pour estimer le CFR global à l'aide des dernières données disponibles. + +- Utiliser `cfr_rolling()` pour montrer quel serait le CFR estimé pour chaque jour de l'épidémie. + +- Utilisez le `delay_density` pour ajuster le CFR en fonction de la distribution des retards correspondante. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/fr/episodes/superspreading-estimate.Rmd b/locale/fr/episodes/superspreading-estimate.Rmd new file mode 100644 index 00000000..0352156c --- /dev/null +++ b/locale/fr/episodes/superspreading-estimate.Rmd @@ -0,0 +1,930 @@ +--- +title: Tenir compte de la superposition des couches +teaching: 30 +exercises: 2 +--- + +```{r setup, echo=FALSE, message=FALSE, warning=FALSE} +library(webshot) +webshot::install_phantomjs(force = TRUE) +``` + +:::::::::::::::::::::::::::::::::::::: questions + +- Comment peut-on estimer la variation de la transmission au niveau individuel (c'est-à-dire le potentiel de super propagation) à partir des données de traçage des contacts ? +- Quelles sont les implications de la variation de la transmission pour la prise de décision ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Estimez la distribution de la transmission ultérieure des individus infectés (c'est-à-dire la distribution de la descendance) à partir des données de l'épidémie à l'aide de `{epicontacts}`. +- Estimez l'ampleur de la variation au niveau individuel (c'est-à-dire le paramètre de dispersion) de la distribution de la descendance à l'aide de . `{fitdistrplus}`. +- Estimez la proportion de la transmission liée à des "événements de super propagation" à l'aide de `{superspreading}`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +Les apprenants doivent se familiariser avec les concepts suivants avant de suivre ce tutoriel : + +**Statistiques**: distributions de probabilités courantes, en particulier Poisson et binôme négatif. + +**Théorie épidémique** Le nombre de reproduction, R. + +::::::::::::::::::::::::::::::::: + +## Introduction + + + +De la variole au coronavirus du syndrome respiratoire aigu sévère 2 (SRAS-CoV-2), certaines personnes infectées transmettent l'infection à un plus grand nombre de personnes que d'autres. La transmission de la maladie est le résultat d'une combinaison de facteurs biologiques et sociaux, et ces facteurs s'équilibrent dans une certaine mesure au niveau de la population lors d'une grande épidémie. C'est pourquoi les chercheurs utilisent souvent les moyennes de la population pour évaluer le potentiel de propagation de la maladie. Toutefois, au début ou à la fin d'une épidémie, les différences individuelles en matière de contagiosité peuvent être plus importantes. En particulier, elles augmentent le risque d'événements de super propagation (ESS), qui peuvent déclencher des épidémies explosives et influencer les chances de contrôler la transmission ([Lloyd-Smith et al., 2005](https://wellcomeopenresearch.org/articles/5-83)). + +![**Chaînes de transmission du SRAS-CoV-2 à Hong Kong initiées par des cas locaux ou importés.** (**a**), réseau de transmission d'un groupe de cas remontant à un ensemble de quatre bars de Hong Kong (n = 106). (**b**), réseau de transmission associé à un mariage sans paires infectrices-infectieuses claires, mais lié à une réunion sociale précédente et à une source locale (n = 22). (**c**), réseau de transmission associé à un groupe de temples de source indéterminée (n = 19). (**d**), tous les autres groupes d'infections par le SRAS-CoV-2 dont la source et la chaîne de transmission ont pu être déterminées ([Adam et al., 2020](https://www.nature.com/articles/s41591-020-1092-0)).](fig/see-intro-superspreading.png) + + + +Les [numéro de reproduction de base](../learners/reference.md#basic), $R_{0}$ mesure le nombre moyen de cas causés par un individu infectieux dans une population entièrement sensible. Les estimations de $R_{0}$ sont utiles pour comprendre la dynamique moyenne d'une épidémie au niveau de la population, mais elles peuvent masquer des variations individuelles considérables dans la contagiosité. Cela a été mis en évidence lors de l'émergence mondiale du SRAS-CoV-2 par de nombreux "événements de super propagation" au cours desquels certains individus infectieux ont généré un nombre anormalement élevé de cas secondaires ([LeClerc et al, 2020](https://wellcomeopenresearch.org/articles/5-83)). + +![**Distribution de la transmission du SRAS-CoV-2 par la descendance observée à Hong Kong.** N = 91 infectés par le SRAS-CoV-2, N = 153 infectés en phase terminale et N = 46 cas locaux sporadiques. Les barres de l'histogramme indiquent la proportion de transmission ultérieure par rapport au nombre de cas secondaires. La ligne correspond à une distribution binomiale négative ajustée ([Adam et al., 2020](https://www.nature.com/articles/s41591-020-1092-0)).](fig/see-intro-secondary-cases-fig-b.png){fig-alt="R = 0,58 et k = 0,43."} + + + +Dans ce tutoriel, nous allons quantifier la variation individuelle de la transmission, et donc estimer le potentiel d'événements de superspreading. Nous utiliserons ensuite ces estimations pour explorer les implications de la superspreading pour les interventions de recherche de contacts. + +Nous allons utiliser les données de l'étude `{outbreaks}` et gérer la liste des lignes et les données sur les contacts à l'aide de l'outil `{epicontacts}` et estimer les paramètres de distribution avec `{fitdistrplus}`. Enfin, nous allons utiliser `{superspreading}` pour explorer les implications de la variation de la transmission sur la prise de décision. + +Nous utiliserons le tuyau `%>%` pour relier certaines des fonctions de ces paquets, donc appelons aussi le paquet `{tidyverse}` . + +```r +library(outbreaks) +library(epicontacts) +library(fitdistrplus) +library(superspreading) +library(tidyverse) +``` + +```{r, message=FALSE, warning=FALSE, eval=TRUE, echo=FALSE} +library(outbreaks) +library(epicontacts) +library(superspreading) +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### Le double point-virgule + +Le double point-virgule `::` dans R vous permettent d'appeler une fonction spécifique d'un paquetage sans charger le paquetage entier dans l'environnement actuel. + +Par exemple, vous pouvez appeler une fonction spécifique d'un package sans charger le package entier dans l'environnement actuel, `dplyr::filter(data, condition)` utilise `filter()` à partir de l'outil `{dplyr}` paquet. + +Cela nous permet de nous souvenir des fonctions du paquet et d'éviter les conflits d'espace de noms. + +::::::::::::::::::: + +## Le numéro de reproduction individuel + +Le nombre de reproduction individuelle est défini comme le nombre de cas secondaires causés par un individu infecté particulier. + +Au début d'une épidémie, nous pouvons utiliser les données de contact pour reconstruire les chaînes de transmission (c'est-à-dire qui a infecté qui) et calculer le nombre de cas secondaires générés par chaque individu. Cette reconstruction des événements de transmission liés à partir des données de contact peut permettre de comprendre comment différents individus ont contribué à la transmission au cours d'une épidémie ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +Mettons cela en pratique en utilisant l'outil `mers_korea_2015` et les données de contact de la base de données `{outbreaks}` et les intégrons à l'application `{epicontacts}` pour calculer la distribution des cas secondaires lors de l'épidémie de MERS-CoV de 2015 en Corée du Sud ([Campbell, 2022](https://community.appliedepi.org/t/estimating-the-degree-of-super-spreading-from-transmission-chain-data/103/2)) : + +```{r} +## first, make an epicontacts object +epi_contacts <- + epicontacts::make_epicontacts( + linelist = outbreaks::mers_korea_2015$linelist, + contacts = outbreaks::mers_korea_2015$contacts, + directed = TRUE + ) +``` + +Avec l'argument `directed = TRUE` nous configurons un graphe orienté. Ces directions intègrent notre hypothèse de la **infecteur-infecté** du patient source probable au cas secondaire. + +```{r, eval=FALSE} +# visualise contact network +epicontacts::vis_epicontacts(epi_contacts) +``` + +```{r, echo=FALSE} +withr::with_envvar(c(OPENSSL_CONF = file.path("/dev", "null")), { + # visualise contact network + network <- + vis_epicontacts(epi_contacts) %>% + visNetwork::visPhysics(solver = "barnesHut") + fname <- "network.html" + visNetwork::visSave(network, fname) + webshot::webshot( + fname, + delay = 5, + zoom = 10 + ) +}) +``` + +::::::::::::::::::::::::::: spoiler + +### Les données de contact sont-elles bien rangées ? + +Les données de contact d'une chaîne de transmission peuvent fournir des informations sur les personnes infectées qui sont entrées en contact avec d'autres. Nous nous attendons à ce que l'infecteur (`from`) et la personne infectée (`to`), ainsi que des colonnes supplémentaires de variables liées à leur contact, telles que le lieu (`exposure`) et la date du contact. + +À la suite de [mettre de l'ordre dans les données](https://tidyr.tidyverse.org/articles/tidy-data.html#tidy-data) l'unité d'observation dans notre cadre de données de contact est le **infecteur-infecté** est la paire infecteur-infecté. Bien qu'un infecteur puisse infecter plusieurs personnes, les enquêtes de recherche de contacts peuvent enregistrer des contacts liés à plus d'un infecteur (par exemple, au sein d'un ménage). Mais nous devrions nous attendre à avoir des paires infecteur-infecté uniques, car chaque personne infectée a généralement contracté l'infection auprès d'une autre personne. + +Pour garantir l'unicité de ces paires, nous pouvons vérifier les réplicats pour les personnes infectées : + +```{r} +# no infector-infectee pairs are replicated +epi_contacts %>% + purrr::pluck("contacts") %>% + dplyr::group_by(to) %>% + dplyr::filter(dplyr::n() > 1) +``` + +::::::::::::::::::::::::::: + +Notre objectif est d'obtenir le nombre de cas secondaires causés par les individus infectés observés. Dans la base de données des contacts, lorsque chaque paire infecteur-infecté est unique, le nombre de lignes par infecteur correspond au nombre de cas secondaires générés par cet individu. + +```{r} +# count secondary cases per infector in contacts +epi_contacts %>% + purrr::pluck("contacts") %>% + dplyr::count(from, name = "secondary_cases") +``` + +Mais cette sortie ne contient que le nombre de cas secondaires pour les infectieux déclarés dans les données de contact, et non pour les cas de **tous les** individus de l'ensemble des `` l'objet. + +Au lieu de cela, à partir de `{epicontacts}` nous pouvons utiliser la fonction `epicontacts::get_degree()`. L'argument `type = "out"` permet d'obtenir la valeur de **degré de sortie** de chaque **nœud** dans le réseau de contact à partir du `` objet de la classe. Dans un réseau dirigé, le degré de sortie est le nombre d'arêtes sortantes (infectés) émanant d'un nœud (infecteur) ([Nykamp DQ, consulté le : 2025](https://mathinsight.org/definition/node_degree)). + +De même, l'argument `only_linelist = TRUE` n'inclura que les individus figurant dans le cadre de données de la liste de référence. Lors des enquêtes sur les épidémies, nous nous attendons à ce qu'un registre de **tous les** les personnes infectées observées dans les données de la liste de diffusion. Cependant, toute personne qui n'est pas liée à un infecteur ou un infecté potentiel n'apparaîtra pas dans les données de contact. Par conséquent, l'argument `only_linelist = TRUE` nous permettra de ne pas manquer ce dernier groupe d'individus lorsque nous compterons le nombre de cas secondaires causés par tous les individus infectés observés. Ils apparaîtront dans les `` sous la forme `0` cas secondaires. + +```{r, message=FALSE, warning=FALSE} +# Count secondary cases per subject in contacts and linelist +all_secondary_cases <- epicontacts::get_degree( + x = epi_contacts, + type = "out", + only_linelist = TRUE +) +``` + +::::::::::::::::::::: caution + +À `epicontacts::get_degree()` nous utilisons l'argument `only_linelist = TRUE`. +Il s'agit de compter le nombre de cas secondaires causés par toutes les personnes infectées observées, +ce qui inclut les individus figurant dans les bases de données des contacts et des listes de diffusion. + +::::::::::::::::::::: + +::::::::::::::::::::: spoiler + +### Quand utiliser "only\_linelist = FALSE" ? + +L'hypothèse selon laquelle +"la liste de diffusion inclura toutes les personnes figurant dans les contacts et la liste de diffusion". +peut ne pas fonctionner dans toutes les situations. + +Par exemple, si au cours du registre des infections observées, +les données de contact comprenaient plus de sujets que ceux disponibles dans les données de la liste de diffusion, +vous ne devez prendre en compte que les individus figurant dans les données de contact. +Dans ce cas, vous devez prendre en compte uniquement les personnes figurant dans les données de contact, +à `epicontacts::get_degree()` nous utilisons l'argument `only_linelist = FALSE`. + +Vous trouverez ici une version imprimée [exemple reproductible](https://reprex.tidyverse.org/): + +```r +# Three subjects on linelist +sample_linelist <- tibble::tibble( + id = c("id1", "id2", "id3") +) + +# Four infector-infectee pairs with Five subjects in contact data +sample_contact <- tibble::tibble( + from = c("id1","id1","id2","id4"), + to = c("id2","id3","id4","id5") +) + +# make an epicontacts object +sample_net <- epicontacts::make_epicontacts( + linelist = sample_linelist, + contacts = sample_contact, + directed = TRUE +) + +# count secondary cases per subject from linelist only +epicontacts::get_degree(x = sample_net, type = "out", only_linelist = TRUE) +#> id1 id2 id3 +#> 2 1 0 + +# count secondary cases per subject from contact only +epicontacts::get_degree(x = sample_net, type = "out", only_linelist = FALSE) +#> id1 id2 id4 id3 id5 +#> 2 1 1 0 0 +``` + +::::::::::::::::::::: + +A partir d'un histogramme des `all_secondary_cases` de l'objet, nous pouvons identifier les **variation au niveau individuel** dans le nombre de cas secondaires. Trois cas étaient liés à plus de 20 cas secondaires, tandis que les cas complémentaires comptaient moins de cinq ou aucun cas secondaire. + + + +```{r} +## plot the distribution +all_secondary_cases %>% + tibble::enframe() %>% + ggplot(aes(value)) + + geom_histogram(binwidth = 1) + + labs( + x = "Number of secondary cases", + y = "Frequency" + ) +``` + +Le nombre de cas secondaires peut être utilisé pour *empiriquement* d'estimer de manière empirique le **distribution de la descendance** qui est le nombre de descendants secondaires *secondaires* causées par chaque cas. Une distribution statistique candidate utilisée pour modéliser la distribution de la descendance est la distribution **binomiale négative** avec deux paramètres : + +- **Moyenne** qui représente la $R_{0}$ le nombre moyen de cas (secondaires) produits par un seul individu dans une population entièrement sensible, et + +- **Dispersion** exprimée par $k$ qui représente la variation au niveau individuel de la transmission par des individus isolés. + +```{r, echo=FALSE, message=FALSE, warning=FALSE} +# Load parameters +mpox <- epiparameter::epiparameter_db( + disease = "SARS", + epi_name = "offspring_distribution", + single_epiparameter = TRUE +) +mpox_params <- epiparameter::get_parameters(mpox) +# mpox_params + +# calculate density fit +fit_density <- + dplyr::tibble(quantile = 0:40) %>% + dplyr::mutate( + density = dnbinom( + x = quantile, + mu = mpox_params["mean"], + size = mpox_params["dispersion"] + ) + ) + +# plot offspring distribution with density fit +ggplot() + + geom_line( + data = fit_density, + mapping = + aes( + x = quantile, + y = density + ) + ) + + geom_vline( + aes(xintercept = mpox_params["mean"] + ), lty = 2 + ) + + annotate( + "text", label = "mean Ro", + x = mpox_params["mean"] + 5, + y = 0.5, + size = 8, + colour = "red" + ) + + labs( + x = "Individual reproduction number", + y = "Density" + ) +``` + +L'histogramme et le diagramme de densité montrent que la distribution de la descendance est fortement asymétrique, soit **surdispersée**. Dans ce cadre, les événements de surdispersion (ESS) ne sont pas arbitraires ou exceptionnels, mais simplement des réalisations de la queue droite de la distribution de la descendance, que nous pouvons quantifier et analyser ([Lloyd-Smith et al., 2005](https://www.nature.com/articles/nature04153)). + +::::::::::::::::::::::::::: callout + +### Récapitulation terminologique + +- A partir de la liste des lignes et des données de contact, nous calculons la **le nombre de cas secondaires** causés par les personnes infectées observées. +- Alors que $R_{0}$ représente la transmission moyenne au sein de la population, nous pouvons définir l'indicateur **nombre de reproduction individuelle** comme une variable aléatoire représentant la *espéré* nombre attendu de cas secondaires causés par un individu infecté. +- En raison des effets stochastiques de la transmission, le nombre de cas secondaires *infections* causées par chaque cas est décrit par un **distribution de la descendance**. +- Une *empirique* La distribution des descendants peut être modélisée par l'équation suivante **binomiale négative** avec une moyenne $R_{0}$ et un paramètre de dispersion $k$. + +::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::: spoiler + +### Poisson, surdispersion et binôme négatif + + + +Pour les occurrences d'événements discrets associés, nous pouvons utiliser **Poisson** ou des distributions binomiales négatives. + +Dans une distribution de Poisson, la moyenne est égale à la variance. Mais lorsque la variance est supérieure à la moyenne, on parle de **surdispersion**. Dans les applications biologiques, la surdispersion se produit et une binomiale négative peut donc être considérée comme une alternative à la distribution de Poisson. + +**Binôme négatif** est particulièrement utile pour les données discrètes sur un intervalle positif non borné dont la variance de l'échantillon dépasse la moyenne de l'échantillon. En d'autres termes, les observations sont surdispersées par rapport à une distribution de Poisson, pour laquelle la moyenne est égale à la variance. + +En épidémiologie, [binôme négatif](https://en.wikipedia.org/wiki/Negative_binomial_distribution) ont été utilisées pour modéliser la transmission de maladies infectieuses pour lesquelles le nombre probable d'infections ultérieures peut varier considérablement d'un individu à l'autre et d'un environnement à l'autre, en tenant compte de toutes les variations dans les antécédents infectieux des individus, y compris les propriétés des circonstances biologiques (c'est-à-dire le degré d'excrétion virale) et environnementales (par exemple, le type et le lieu de contact). + +::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::: challenge + +Calculez la distribution des cas secondaires d'Ebola à l'aide de la méthode des `ebola_sim_clean` objet de `{outbreaks}` paquet. + +- La distribution de la descendance d'Ebola est-elle asymétrique ou surdispersée ? + +:::::::::::::::::: hint + +⚠️ + **Étape facultative :** Cet ensemble de données a `r nrow(ebola_sim_clean$linelist)` cas. Exécution `epicontacts::vis_epicontacts()` peut prendre plusieurs minutes et utiliser beaucoup de mémoire pour les grandes épidémies telles que la liste des cas d'Ebola. Si vous utilisez un ordinateur plus ancien ou plus lent, vous pouvez sauter cette étape. + +:::::::::::::::::: + +:::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +## first, make an epicontacts object +ebola_contacts <- + epicontacts::make_epicontacts( + linelist = outbreaks::ebola_sim_clean$linelist, + contacts = outbreaks::ebola_sim_clean$contacts, + directed = TRUE + ) + +# count secondary cases per subject in contacts and linelist +ebola_secondary <- epicontacts::get_degree( + x = ebola_contacts, + type = "out", + only_linelist = TRUE +) + +## plot the distribution +ebola_secondary %>% + tibble::enframe() %>% + ggplot(aes(value)) + + geom_histogram(binwidth = 1) + + labs( + x = "Number of secondary cases", + y = "Frequency" + ) +``` + +D'après une inspection visuelle, la distribution des cas secondaires pour l'ensemble des données relatives à Ebola en `ebola_sim_clean` montre une distribution asymétrique avec des cas secondaires inférieurs ou égaux à 6. Nous devons compléter cette observation par une analyse statistique afin d'évaluer la surdispersion. + +:::::::::::::::::: + +:::::::::::::::::::::::::::::::::: + +## Estimez le paramètre de dispersion + +Pour estimer empiriquement le paramètre de dispersion $k$ nous pourrions ajuster une distribution binomiale négative au nombre de cas secondaires. + +Nous pouvons ajuster des distributions aux données à l'aide de la fonction `{fitdistrplus}` qui fournit des estimations du maximum de vraisemblance. + +```r +library(fitdistrplus) +``` + +```{r} +## fit distribution +offspring_fit <- all_secondary_cases %>% + fitdistrplus::fitdist(distr = "nbinom") + +offspring_fit +``` + +:::::::::::::::::::::::::::::::: callout + +### Nom des paramètres + +A partir de la `{fitdistrplus}` sortie : + +- Le `size` fait référence au paramètre de dispersion estimé $k$ estimé, et +- L'objet `mu` se réfère à la moyenne estimée, qui représente l'ensemble de la population. $R_{0}$, + +:::::::::::::::::::::::::::::::: + +```{r, echo=FALSE} +## extract the "size" parameter +mid <- offspring_fit$estimate[["size"]] + +## calculate the 95% confidence intervals using the standard error estimate and +## the 0.025 and 0.975 quantiles of the normal distribution. +lower <- mid + offspring_fit$sd[["size"]] * qnorm(0.025) +upper <- mid + offspring_fit$sd[["size"]] * qnorm(0.975) +``` + +À partir de la distribution du nombre de cas secondaires, nous avons estimé un paramètre de dispersion $k$ de +`r round(mid, 3)` avec un intervalle de confiance à 95% de `r round(lower, 3)` à `r round(upper, 3)`. Comme la valeur de $k$ est nettement inférieure à un, nous pouvons conclure qu'il existe un potentiel considérable pour les événements de superposition. + +Nous pouvons superposer les valeurs de densité estimées de la distribution binomiale négative ajustée et l'histogramme du nombre de cas secondaires : + +```{r, echo=FALSE} +# calculate density fit +fit_density <- + tibble::tibble(quantile = 0:40) %>% + dplyr::mutate( + density = dnbinom( + x = quantile, + mu = offspring_fit$estimate[["mu"]], + size = mid + ) + ) %>% + dplyr::mutate(label = "Fitted\nnegative\nbinomial\ndistribution") + +# plot offspring distribution with density fit +ggplot() + + geom_histogram( + data = all_secondary_cases %>% tibble::enframe(), + mapping = + aes( + x = value, + y = after_stat(density) + ), fill = "white", color = "black", + binwidth = 1 + ) + + geom_point( + data = fit_density, + mapping = aes( + x = quantile, + y = density, + color = label + ), + alpha = 0.5 + ) + + geom_line( + data = fit_density, + mapping = aes( + x = quantile, + y = density + ), + alpha = 0.5, color = "red" + ) + + labs( + x = "Number of secondary cases", + y = "Density", + color = "Legend" + ) + + theme_bw() +``` + +:::::::::::::::::::: callout + +### Variation de la transmission au niveau individuel + +La variation de la transmission au niveau individuel est définie par la relation entre la moyenne ($R_{0}$), la dispersion ($k$) et la variance d'une distribution binomiale négative. + +Le modèle binomial négatif a $variance = R_{0}(1+\frac{R_{0}}{k})$, de sorte que les plus petites valeurs de $k$ indiquent une plus grande variance et, par conséquent, une plus grande **variation au niveau individuel** de la transmission. + +$$\uparrow variance = R_{0}(1+\frac{R_{0}}{\downarrow k})$$ + +Lorsque $k$ s'approche de l'infini ($k \rightarrow \infty$), la variance est égale à la moyenne (parce que $\frac{R_{0}}{\infty}=0$). Cela fait du modèle de Poisson classique un cas particulier du modèle binomial négatif. + +:::::::::::::::::::: + +::::::::::::::::::::::: challenge + +À partir de l'épreuve précédente, utilisez la distribution des cas secondaires de l'épreuve de la `ebola_sim_clean` de l'objet de `{outbreaks}` paquet. + +Ajustez une distribution binomiale négative pour estimer la moyenne et le paramètre de dispersion de la distribution de la descendance. Essayez d'estimer l'incertitude du paramètre de dispersion à partir de l'erreur standard et des intervalles de confiance à 95 %. + +- Le paramètre de dispersion estimé d'Ebola fournit-il des preuves d'une variation de la transmission au niveau individuel ? + +:::::::::::::: hint + +Revoyez comment nous avons ajusté une distribution binomiale négative à l'aide de la fonction `fitdistrplus::fitdist()` fonction. + +:::::::::::::: + +:::::::::::::: solution + +```{r} +ebola_offspring <- ebola_secondary %>% + fitdistrplus::fitdist(distr = "nbinom") + +ebola_offspring +``` + +```{r} +## extract the "size" parameter +ebola_mid <- ebola_offspring$estimate[["size"]] + +## calculate the 95% confidence intervals using the +## standard error estimate and +## the 0.025 and 0.975 quantiles of the normal distribution. + +ebola_lower <- ebola_mid + ebola_offspring$sd[["size"]] * qnorm(0.025) +ebola_upper <- ebola_mid + ebola_offspring$sd[["size"]] * qnorm(0.975) + +# ebola_mid +# ebola_lower +# ebola_upper +``` + +À partir de la distribution du nombre de cas secondaires, nous avons estimé un paramètre de dispersion $k$ de +`r round(ebola_mid, 2)` avec un intervalle de confiance à 95% de `r round(ebola_lower, 2)` à `r round(ebola_upper, 2)`. + +Pour les estimations du paramètre de dispersion supérieures à un, nous obtenons une faible variance de la distribution, et donc une faible variation de la transmission au niveau individuel. + +Mais cela signifie-t-il que la distribution des cas secondaires ne présente pas d'événements de super propagation (ESS) ? Vous rencontrerez plus tard une difficulté supplémentaire : comment définir un seuil d'ESS pour Ebola ? + +:::::::::::::: + +:::::::::::::: solution + +### Sélectionnez le meilleur modèle + +Nous pouvons utiliser les estimations du maximum de vraisemblance de `{fitdistrplus}` pour comparer différents modèles et évaluer la performance de l'ajustement à l'aide d'estimateurs tels que l'AIC et le BIC. Pour en savoir plus, lisez la vignette sur [Estimer la transmission au niveau individuel](https://epiverse-trace.github.io/superspreading/articles/estimate_individual_level_transmission.html) et utilisez l'outil `{superspreading}` fonction d'aide `ic_tbl()` pour cela ! + +:::::::::::::: + +::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::: checklist + +### Le paramètre de dispersion entre les maladies + +La recherche sur les maladies sexuellement transmissibles et à transmission vectorielle a précédemment suggéré une règle "20/80", 20 % des individus contribuant à au moins 80 % du potentiel de transmission ([Woolhouse et al](https://www.pnas.org/doi/10.1073/pnas.94.1.338)). + +En soi, le paramètre de dispersion $k$ est difficile à interpréter intuitivement, et sa conversion en un résumé proportionnel peut faciliter la comparaison. Si l'on considère un éventail plus large d'agents pathogènes, on constate qu'il n'existe pas de règle absolue pour le pourcentage qui génère 80 % de la transmission, mais que la variation apparaît comme une caractéristique commune des maladies infectieuses. + +- Lorsque les 20 % de cas les plus infectieux contribuent à 80 % de la transmission (ou plus), on observe une forte variation de la transmission au niveau individuel, avec une distribution de la descendance fortement surdispersée ($k<0.1$), par exemple dans le cas du SRAS-1. + +- Lorsque les 20 % de cas les plus infectieux contribuent à environ 50 % de la transmission, la variation de la transmission au niveau individuel est faible et la distribution de la descendance est modérément dispersée ($k > 0.1$), par exemple la peste pulmonaire. + +![**Preuve de la variation du nombre d'individus reproducteurs**(Gauche, c) Proportion de transmission attendue à partir des 20 % de cas les plus infectieux, pour 10 ensembles de données d'épidémies ou de surveillance (triangles). Les lignes en pointillé indiquent les proportions attendues selon la règle des 20/80 (en haut) et l'homogénéité (en bas). (Droite, d), Événements de super propagation signalés (SSE ; losanges) par rapport au nombre reproductif estimé R (carrés) pour douze infections directement transmissibles. Les croix indiquent le 99e centile proposé comme seuil pour les ESS. (Pour plus de détails sur les figures, voir [Lloyd-Smith et al. 2005](https://www.nature.com/articles/nature04153))](fig/SEE-individual-reproductive-number-fig-c-d.png) + +```{r, message=FALSE, warning=FALSE, echo=FALSE, eval=FALSE} +library(epiparameter) +library(superspreading) +library(tidyverse) + +# list of diseases with offspring distribution +epidist_string <- epiparameter::epiparameter_db( + epi_name = "offspring distribution" +) %>% + epiparameter::parameter_tbl() %>% + dplyr::select(disease) %>% + dplyr::distinct() %>% + dplyr::as_tibble() + +# get percent of cases that cause percent of transmission +across_offspring <- epidist_string %>% + # add column list of epidist objects + mutate( + epidist_out = + map( + .x = disease, + .f = epiparameter::epiparameter_db, + epi_name = "offspring distribution", + single_epiparameter = TRUE + ) + ) %>% + # get parameters + mutate( + epidist_params = + map( + .x = epidist_out, + .f = epiparameter::get_parameters + ) + ) %>% + # unnest parameters + unnest_wider(col = epidist_params) %>% + # to each disease, add sequence from 0.01 to 1 (proportion of transmission) + expand_grid(percent_transmission = seq(from = 0.01, to = 1, by = 0.01)) %>% + # estimate proportion of cases responsible of proportion of transmission (row) + mutate( + transmission_output = + pmap( + .l = dplyr::select(., R = mean, k = dispersion, percent_transmission), + .f = superspreading::proportion_transmission, + format_prop = FALSE, + simulate = TRUE # use a numerical simulation + ) + ) %>% + # unnest proportion of cases results + unnest_wider(col = transmission_output) %>% + # move each result to one column + rowwise() %>% + mutate( + percent_cases = + sum( + c_across(cols = starts_with("prop_")), + na.rm = TRUE + ) + ) %>% + dplyr::select(-starts_with("prop_")) %>% + ungroup() + +# get a position to the ggplot text annotation +across_offspring_tip <- across_offspring %>% + group_by(disease) %>% + filter(percent_transmission < 0.98, percent_transmission > 0.85) %>% + slice_max(percent_transmission) %>% + ungroup() %>% + mutate(disease = case_when( + str_detect(disease, stringr::fixed("Hantavirus")) ~ "Hantavirus", + str_detect(disease, stringr::fixed("Ebola")) ~ "Ebola", + TRUE ~ disease + )) + +# plot x: proportion of cases, y: proportion of transmission +across_offspring %>% + ggplot() + + geom_line( + aes( + x = percent_cases, + y = percent_transmission, + color = dispersion, + group = disease + ) + ) + + geom_text( + data = across_offspring_tip, + aes( + x = percent_cases, + y = percent_transmission, + label = disease + ), + hjust = 0.0, + vjust = 1.0, + angle = 25, + size = 3 + ) + + scale_y_continuous(breaks = scales::breaks_pretty(n = 5)) + + colorspace::scale_color_continuous_diverging(trans = "log10", rev = TRUE) + + labs( + x = "Proportion of infectious cases (ranked)", + y = "Expected proportion of transmission", + color = "Dispersion\nparameter (k)" + ) + + # geom_hline(aes(yintercept = 0.8),lty = 3) + + geom_vline(aes(xintercept = 0.2), lty = 2) + + coord_fixed(ratio = 1) +``` + +:::::::::::::::::::::::::::::::::: + +## Contrôle de la superspreading avec la traçabilité des contacts + +Lors d'une épidémie, il est courant d'essayer de réduire la transmission en identifiant les personnes qui ont été en contact avec une personne infectée, puis en les mettant en quarantaine au cas où elles s'avéreraient infectées par la suite. Cette recherche de contacts peut être déployée de plusieurs manières. La recherche des contacts "en amont" cible les contacts en aval susceptibles d'avoir été infectés par une infection nouvellement identifiée (c'est-à-dire le "cas index"). La recherche "en amont" vise plutôt le cas primaire en amont qui a infecté le cas index (ou un lieu ou un événement au cours duquel le cas index a été infecté), par exemple en retraçant l'historique des contacts jusqu'au point d'exposition probable. Cela permet d'identifier d'autres personnes qui ont également été potentiellement infectées par ce cas primaire antérieur. + +En présence d'une variation de la transmission au niveau individuel, c'est-à-dire avec une distribution de la descendance surdispersée, si ce cas primaire est identifié, une plus grande partie de la chaîne de transmission peut être détectée en remontant l'historique de chacun des contacts de ce cas primaire ([Endo et al., 2020](https://wellcomeopenresearch.org/articles/5-239/v3)). + +![Représentation schématique des stratégies de recherche de contacts. Les flèches noires indiquent le sens de la transmission, les flèches bleues et orange indiquent respectivement une recherche de contact réussie ou échouée. Lorsqu'il existe des preuves d'une variation de la transmission au niveau individuel, entraînant souvent une superspreading, la recherche de contacts en amont du cas index (cercle bleu) augmente la probabilité de trouver le cas primaire (cercle vert) ou des grappes avec une plus grande fraction de cas, augmentant potentiellement le nombre de cas en quarantaine (cercles jaunes). [Claire Blackmore, 2021](https://www.paho.org/sites/default/files/backward_contact_tracing_v3_0.pdf)](fig/contact-tracing-strategies.png) + +Lorsqu'il existe des preuves de variation au niveau individuel (c'est-à-dire de surdispersion), qui se traduisent souvent par ce que l'on appelle des événements de superspreading, une grande proportion d'infections peut être liée à une petite proportion de grappes d'origine. Par conséquent, la recherche et le ciblage des grappes d'origine, combinés à la réduction des infections ultérieures, peuvent considérablement améliorer l'efficacité des méthodes de dépistage ([Endo et al., 2020](https://wellcomeopenresearch.org/articles/5-239/v3)). + +Des données empiriques axées sur l'évaluation de l'efficacité de la recherche rétrospective ont permis d'identifier 42 % de cas supplémentaires par rapport à la recherche prospective, ce qui plaide en faveur de sa mise en œuvre lorsqu'une suppression rigoureuse de la transmission est justifiée ([Raymenants et al, 2022](https://www.nature.com/articles/s41467-022-32531-6)) + +## Probabilité de cas dans un groupe donné + +En utilisant `{superspreading}` nous pouvons estimer la probabilité d'avoir une grappe d'infections secondaires causées par un cas primaire identifié par traçage rétrospectif de taille $X$ ou plus ([Endo et al., 2020](https://wellcomeopenresearch.org/articles/5-239/v3)). + +```{r} +# Set seed for random number generator +set.seed(33) + +# estimate the probability of +# having a cluster size of 5, 10, or 25 +# secondary cases from a primary case, +# given known reproduction number and +# dispersion parameter. +superspreading::proportion_cluster_size( + R = offspring_fit$estimate["mu"], + k = offspring_fit$estimate["size"], + cluster_size = c(5, 10, 25) +) +``` + +```{r, echo=FALSE, message=FALSE, warning=FALSE} +# Set seed for random number generator +set.seed(33) + +cluster_probability <- superspreading::proportion_cluster_size( + R = offspring_fit$estimate["mu"], + k = offspring_fit$estimate["size"], + cluster_size = c(5, 10, 25) +) + +cluster_probability_percent <- cluster_probability %>% + dplyr::select(prop_25) %>% + dplyr::pull(prop_25) + +# cluster_probability_percent +``` + +Même si nous disposons d'un $R<1$ une distribution de la progéniture fortement surdispersée ($k=0.02$) signifie que si nous détectons un nouveau cas, il y a un risque d'erreur dans la distribution de la descendance. `r cluster_probability_percent` probabilité qu'il provienne d'un groupe de 25 infections ou plus. Par conséquent, en suivant une stratégie rétrospective, les efforts de recherche des contacts augmenteront la probabilité de réussir à contenir et à mettre en quarantaine ce grand nombre de personnes précédemment infectées, plutôt que de se concentrer simplement sur le nouveau cas, qui est susceptible de n'avoir infecté personne (parce qu'il n'a pas été infecté). $k$ est très faible). + +Nous pouvons également utiliser ce nombre pour empêcher les rassemblements de certaines tailles afin de réduire l'épidémie en prévenant les événements potentiels de surpopulation. Les interventions peuvent viser à réduire le nombre de reproductions afin de réduire la probabilité d'avoir des groupes de cas secondaires. + +::::::::::::::::::::::::::::::::: challenge + +### Recherche rétrospective des contacts pour Ebola + +Utilisez les paramètres estimés pour Ebola pour `ebola_sim_clean` à partir de `{outbreaks}` paquet. + +Calculez la probabilité d'avoir un groupe d'infections secondaires causées par un cas primaire identifié par traçage rétrospectif de taille 5, 10, 15 ou plus. + +La mise en œuvre d'une stratégie de traçage en amont à ce stade de l'épidémie d'Ebola augmenterait-elle la probabilité de contenir et de mettre en quarantaine un plus grand nombre de cas en aval ? + +:::::::::::::::: hint + +Examinez comment nous avons estimé la probabilité d'avoir des grappes de taille fixe, compte tenu de la moyenne de la distribution de la descendance et des paramètres de dispersion, à l'aide de la méthode des `superspreading::proportion_cluster_size()` fonction. + +:::::::::::::::: + +:::::::::::::::: solution + +```{r} +# estimate the probability of +# having a cluster size of 5, 10, or 25 +# secondary cases from a primary case, +# given known reproduction number and +# dispersion parameter. +superspreading::proportion_cluster_size( + R = ebola_offspring$estimate["mu"], + k = ebola_offspring$estimate["size"], + cluster_size = c(5, 10, 25) +) +``` + +La probabilité d'avoir des grappes de cinq personnes est de 1,8 %. À ce stade, compte tenu des paramètres de distribution de la descendance, une stratégie rétrospective n'augmentera peut-être pas la probabilité de contenir et de mettre en quarantaine davantage de cas en amont. + +:::::::::::::::: + +::::::::::::::::::::::::::::::::: + +## Défis + +::::::::::::::::::::::::: challenge + +### Le virus Ebola se propage-t-il à grande échelle ? + + La notion d'"événement de surpopulation" peut revêtir des significations différentes selon les personnes. [Lloyd-Smith et al, 2005](https://www.nature.com/articles/nature04153) ont proposé un protocole général pour définir un événement de super propagation (ESS). Si le nombre d'infections secondaires causées par chaque cas, $Z$ suit une distribution binomiale négative ($R, k$) : + +- Nous définissons une ESS comme tout individu infecté qui infecte plus de $Z(n)$ autres, où $Z(n)$ est le nième percentile de l'échantillon de $Poisson(R)$ distribution. +- Un SSE du 99e centile est donc tout cas causant plus d'infections qu'il n'en surviendrait dans 99 % des histoires infectieuses d'une population homogène. + +À l'aide de la fonction de distribution correspondante, estimez le seuil d'ESS pour définir un ESS pour les estimations de la distribution de la descendance d'Ebola pour l'ensemble de la population. `ebola_sim_clean` objet de `{outbreaks}` paquet. + +::::::::::::::::: hint + +Dans une distribution de Poisson, la **lambda** ou **taux** sont égaux à la valeur estimée du paramètre **moyenne** d'une distribution binomiale négative. Vous pouvez étudier cette question dans [Le zoo de la distribution](https://ben18785.shinyapps.io/distribution-zoo/) une application brillante. + +::::::::::::::::: + +::::::::::::::::: solution + +Pour obtenir la valeur du quantile pour le 99ème centile, nous devons utiliser la fonction [fonction de densité](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc) de la distribution de Poisson `dpois()`. + +```{r} +# get mean +ebola_mu_mid <- ebola_offspring$estimate["mu"] + +# get 99th-percentile from poisson distribution +# with mean equal to mu +stats::qpois( + p = 0.99, + lambda = ebola_mu_mid +) +``` + +Comparez ces valeurs avec celles rapportées par [Lloyd-Smith et al, 2005](https://www.nature.com/articles/nature04153). Voir la figure ci-dessous : + +![Événements de surmultiplication signalés (diamants) par rapport au nombre de reproduction estimé R (carrés) pour douze infections directement transmissibles. Les lignes indiquent les percentiles 5-95 du nombre de cas secondaires suivant une distribution de Poisson avec lambda égal au nombre de reproduction ($Z∼Poisson(R)$), et les croix indiquent le 99e centile proposé comme seuil pour les ESS. Les étoiles représentent les ESS causés par plus d'un cas source. Les "autres" maladies sont les suivantes 1, streptocoque du groupe A ; 2, fièvre de Lassa ; 3, pneumonie à mycoplasme ; 4, peste pulmonaire ; 5, tuberculose. R n'est pas indiqué pour les "autres" maladies et est hors échelle pour la variole.](fig/SEE-individual-reproductive-number-fig-d.png) + +::::::::::::::::: + +:::::::::::::::::::::::: + +::::::::::::::::::::::::::::: challenge + +### Proportion attendue de transmission + +Quelle est la proportion de cas responsables de 80 % de la transmission ? + +L'utilisation `{superspreading}` et comparez les estimations pour **MERS** en utilisant les paramètres de distribution de la descendance de cet épisode du didacticiel, avec les estimations pour le **SRAS-1** et **Ebola** accessibles via le paramètre de distribution de la descendance `{epiparameter}` R. + +::::::::::::::::::::: hint + +Pour utiliser `superspreading::proportion_transmission()` nous vous recommandons de lire le [Estimer quelle proportion de cas provoque une certaine proportion de transmission](https://epiverse-trace.github.io/superspreading/reference/proportion_transmission.html) le manuel de référence. + +```{r, message=FALSE, warning=FALSE, echo=FALSE} +library(epiparameter) + +epidist_string <- epiparameter::epiparameter_db( + epi_name = "offspring distribution" +) %>% + epiparameter::parameter_tbl() %>% + dplyr::select(disease) %>% + dplyr::distinct() %>% + dplyr::pull() %>% + base::paste(collapse = ", ") +``` + +Actuellement, `{epiparameter}` a des distributions de descendants pour `r epidist_string`. Accédons à la distribution des descendants `mean` et `dispersion` pour SARS-1 : + +```{r, message=FALSE, warning=FALSE} +# Load parameters +sars <- epiparameter::epiparameter_db( + disease = "SARS", + epi_name = "offspring distribution", + single_epiparameter = TRUE +) +sars_params <- epiparameter::get_parameters(sars) +sars_params +``` + +::::::::::::::::::::: + +::::::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +#' estimate for ebola -------------- + +ebola_epiparameter <- epiparameter::epiparameter_db( + disease = "Ebola", + epi_name = "offspring distribution", + single_epiparameter = TRUE +) +ebola_params <- epiparameter::get_parameters(ebola_epiparameter) +ebola_params + +# estimate +# proportion of cases that +# generate 80% of transmission +superspreading::proportion_transmission( + R = ebola_params[["mean"]], + k = ebola_params[["dispersion"]], + percent_transmission = 0.8 +) + +#' estimate for sars -------------- + +# estimate +# proportion of cases that +# generate 80% of transmission +superspreading::proportion_transmission( + R = sars_params[["mean"]], + k = sars_params[["dispersion"]], + percent_transmission = 0.8 +) + + +#' estimate for mers -------------- + +# estimate +# proportion of cases that +# generate 80% of transmission +superspreading::proportion_transmission( + R = offspring_fit$estimate["mu"], + k = offspring_fit$estimate["size"], + percent_transmission = 0.8 +) +``` + +Le MERS présente le pourcentage le plus faible de cas (2,1 %) responsables de 80 % de la transmission, ce qui est représentatif d'une distribution très dispersée de la descendance. + +Le virus Ebola présente le pourcentage le plus élevé de cas (43 %) responsables de 80 % de la transmission. Ce pourcentage est représentatif des distributions de descendance dont les paramètres de dispersion sont élevés. + +::::::::::::::::::::: + +::::::::::::::::::::::::::::: + +::::::::::::::::: callout + +### inverse-dispersion ? + +Le paramètre de dispersion $k$ peut être exprimé différemment dans la littérature. + +- Dans la page Wikipédia consacrée à la binomiale négative, ce paramètre est défini sous sa forme réciproque (voir la rubrique [équation de la variance](https://en.wikipedia.org/wiki/Negative_binomial_distribution)). +- Dans le cas d'une [le zoo de distribution](https://ben18785.shinyapps.io/distribution-zoo/) shiny app, le paramètre de dispersion $k$ est appelé "Inverse-dispersion" mais il est égal au paramètre estimé dans cet épisode. Nous vous invitons à explorer cette piste ! + +::::::::::::::::: + +:::::::::::::::::::::::::::: callout + +### hétérogénéité ? + +La variation de la transmission au niveau individuel est également appelée hétérogénéité de la transmission ou degré d'hétérogénéité de la transmission. [Lloyd-Smith et al, 2005](https://wellcomeopenresearch.org/articles/5-83) l'infectiosité hétérogène dans les [Campbell et al, 2018](https://bmcbioinformatics.biomedcentral.com/articles/10.1186/s12859-018-2330-z) lors de l'introduction de la `{outbreaker2}` paquet. De même, un réseau de contacts peut stocker des contacts épidémiologiques hétérogènes, comme dans la documentation de l'étude `{epicontacts}` paquet ([Nagraj et al., 2018](https://www.repidemicsconsortium.org/epicontacts/articles/epicontacts.html)). + +:::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::: testimonial + +### Lisez ces articles de blog + +Les [Tracer la variole du singe](https://plus.maths.org/content/monkeypox) de l'article de la [JUNIPER](https://maths.org/juniper/) montre l'utilité des modèles de réseau pour la recherche de contacts. + +Les [Devenir viral](https://kucharski.substack.com/p/going-viral) d'Adam Kucharski présente les conditions qui déclenchent la contagion en ligne : viralité sur YouTube, épidémies et campagnes de marketing. + +::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utiliser `{epicontacts}` pour calculer le nombre de cas secondaires causés par une personne particulière à partir de la liste de diffusion et des données de contact. +- Utiliser `{fitdistrplus}` pour estimer empiriquement la distribution de la descendance à partir de la distribution du nombre de cas secondaires. +- Utilisez `{superspreading}` pour estimer la probabilité d'avoir des grappes d'une taille donnée à partir des cas primaires et informer les efforts de recherche de contacts. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/fr/episodes/superspreading-simulate.Rmd b/locale/fr/episodes/superspreading-simulate.Rmd new file mode 100644 index 00000000..562086ea --- /dev/null +++ b/locale/fr/episodes/superspreading-simulate.Rmd @@ -0,0 +1,1042 @@ +--- +title: Simuler des chaînes de transmission +teaching: 30 +exercises: 2 +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- Comment simuler des chaînes de transmission basées sur les caractéristiques de l'infection ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Estimez le potentiel de grandes épidémies suite à l'introduction d'un nouveau cas à l'aide d'un processus de ramification avec `{epichains}`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +Les apprenants doivent se familiariser avec les concepts suivants avant de suivre ce tutoriel : + +**Statistiques** Les distributions de probabilités courantes, y compris les distributions de Poisson et binomiale négative. + +**Théorie des épidémies**: Le nombre de reproductions, $R$. + +::::::::::::::::::::::::::::::::: + +## Introduction + + + +La variation individuelle de la transmission peut affecter à la fois le potentiel d'établissement d'une épidémie dans une population et la facilité de contrôle ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +- Une plus grande variation réduit la probabilité globale qu'un nouveau cas unique soit à l'origine d'une épidémie locale de grande ampleur, car la plupart des cas infectent peu d'autres personnes et les individus qui génèrent un grand nombre de cas secondaires sont relativement rares. + +- Toutefois, si un "événement de super propagation" se produit et que l'épidémie s'installe, cette variation peut rendre l'épidémie plus difficile à contrôler à l'aide d'un système d'information sur les maladies infectieuses. *des interventions de masse* (c'est-à-dire des interventions générales qui supposent implicitement que tout le monde contribue de manière égale à la transmission), car certains cas contribuent de manière disproportionnée : un seul cas non contrôlé peut générer un grand nombre de cas secondaires. + +- Inversement, la variation de la transmission peut offrir des possibilités de *des interventions ciblées* si les individus qui contribuent le plus à la transmission (en raison de facteurs biologiques ou comportementaux), ou les environnements dans lesquels se produisent les "événements de super propagation", partagent des caractéristiques sociodémographiques, environnementales ou géographiques qui peuvent être définies. + +% + # incidence2 workflow + incidence2::incidence(date_index = "dt_onset") %>% + incidence2::complete_dates() %>% + # wrangling using {dplyr} + mutate(count_cumsum = cumsum(count)) %>% + rownames_to_column(var = "day") %>% + mutate(day = as.numeric(day)) + +# offspring distribution +mers_offspring <- c(mean = 0.60, dispersion = 0.02) + +# generation time +serial_interval <- epiparameter_db( + disease = "mers", + epi_name = "serial", + single_epiparameter = TRUE +) + +# Set seed for random number generator +set.seed(33) +# Number of simulation runs +number_simulations <- 1000 +# Number of initial cases +initial_cases <- 1 + +simulated_chains_map <- + # iterate one function across multiple numbers (simulation IDs) + purrr::map( + # vector of numbers (simulation IDs) + .x = seq_len(number_simulations), + # function to iterate to each simulation ID number + .f = function(sim) { + epichains::simulate_chains( + # simulation controls + n_chains = initial_cases, + statistic = "size", + # offspring + offspring_dist = rnbinom, + mu = mers_offspring["mean"], + size = mers_offspring["dispersion"], + # generation + generation_time = function(x) generate(x = serial_interval, times = x) + ) %>% + # creates a column with the simulation ID number + dplyr::mutate(simulation_id = sim) + } + ) %>% + # combine list outputs (for each simulation ID) into a single data frame + purrr::list_rbind() + +# daily aggregate of cases +simulated_chains_day <- simulated_chains_map %>% + # use data.frame output from object + as_tibble() %>% + # transform simulation ID column to factor (categorical variable) + mutate(simulation_id = as_factor(simulation_id)) %>% + # get the round number (day) of infection times + mutate(day = ceiling(time)) %>% + # count the daily number of cases each simulation (simulation ID) + count(simulation_id, day, name = "cases") %>% + # calculate the cumulative number of cases for each simulation (simulation ID) + group_by(simulation_id) %>% + mutate(cases_cumsum = cumsum(cases)) %>% + ungroup() + +# Summarise the chain duration and size +sim_chains_max <- + simulated_chains_day %>% + group_by(simulation_id) %>% + summarise( + # duration + day_max = max(day), + # size + cases_total = max(cases_cumsum) + ) %>% + ungroup() + +# Observed cases vs Simulated transmission chains +mers_cumcases_type <- + mers_cumcases %>% + mutate(type = "Observed") +simulated_chains_day_type <- + simulated_chains_day %>% + mutate(type = "Simulated") + +ggplot() + + geom_line( + data = simulated_chains_day_type, + mapping = aes( + x = day, + y = cases_cumsum, + group = simulation_id, + color = type + ) + ) + + geom_hline(aes(yintercept = 100), lty = 2) + + geom_line( + data = mers_cumcases_type, + mapping = aes( + x = day, + y = count_cumsum, + color = type + ), + linewidth = 1.5 + ) + + labs( + x = "Day since first report", + y = "Cumulative cases", + color = "Type" + ) +``` + + + +Dans cet épisode, nous utiliserons la fonction `{epichains}` pour simuler des chaînes de transmission et estimer le potentiel d'épidémies importantes suite à l'introduction d'un nouveau cas. Nous allons l'utiliser avec les fonctions de `{epiparameter}`, `{dplyr}` et `{purrr}` de sorte qu'il faut également charger le `{tidyverse}` paquet : + +```r +library(epichains) +library(epiparameter) +library(tidyverse) +``` + +```{r, message=FALSE, warning=FALSE, echo=FALSE, eval=TRUE} +library(epiparameter) +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### Le double point-virgule + +Le double point-virgule `::` en R vous permettent d'appeler une fonction spécifique d'un paquetage sans charger le paquetage entier dans l'environnement courant. + +Par exemple, vous pouvez appeler une fonction spécifique d'un package sans charger le package entier dans l'environnement actuel, `dplyr::filter(data, condition)` utilise `filter()` à partir de l'outil `{dplyr}` paquet. + +Cela nous permet de nous souvenir des fonctions du paquet et d'éviter les conflits d'espace de noms. + +::::::::::::::::::: + +## Simulation de foyers incontrôlés + +Les épidémies de maladies infectieuses se propagent dans les populations lorsqu'une chaîne d'individus infectés transmet l'infection à d'autres. [Processus de ramification](https://epiverse-trace.github.io/epichains/articles/theoretical_background.html) peuvent être utilisés pour modéliser cette transmission. Un processus de ramification est un processus stochastique (c'est-à-dire un processus aléatoire qui peut être décrit par une distribution de probabilité connue), dans lequel chaque individu infectieux donne naissance à un nombre aléatoire d'individus dans la génération suivante d'infection, en commençant par le cas index dans la génération 1. La distribution du nombre de cas secondaires générés par chaque individu est appelée distribution de la descendance ([Azam \& Funk, 2024](https://epiverse-trace.github.io/epichains/articles/epichains.html)). + +`{epichains}` fournit des méthodes d'analyse et de simulation de la *taille* et *longueur* des processus de ramification pour une distribution donnée de la descendance. `{epichains}` met en œuvre un modèle simple et rapide pour simuler les chaînes de transmission afin d'évaluer le risque épidémique, de projeter les cas dans l'avenir et d'évaluer les interventions qui modifient la distribution de la descendance. $R$. + +::::::::::::::::::: discussion + +### taille et longueur de la chaîne + +- La **taille** de la chaîne de transmission est définie comme le nombre total d'individus infectés sur toutes les générations d'infection, et + +- la **longueur** de la chaîne de transmission est le nombre de générations entre le premier et le dernier cas du foyer avant que la chaîne ne se termine. + +La longueur de la chaîne de transmission *taille* inclut le premier cas, et le calcul de la *longueur* contient la première génération lorsque le premier cas commence la chaîne (voir figure ci-dessous). + +![**Exemple d'une chaîne de transmission commençant par un seul cas C1.** Les cas sont représentés par des cercles bleus et des flèches indiquant qui a infecté qui. La chaîne se développe à travers les générations Gen 1, Gen 2 et Gen 3, produisant les cas C2, C3, C4, C5 et C6. La chaîne se termine à la génération Gen 3 avec les cas C4, C5 et C6. La taille de la chaîne de C1 est de 6, y compris C1 (c'est-à-dire la somme de tous les cercles bleus), et sa longueur est de 3, ce qui inclut la génération 1 (nombre maximal de générations atteint par la chaîne de C1) ([Azam \& Funk, 2024](https://epiverse-trace.github.io/epichains/articles/epichains.html)).](https://raw.githubusercontent.com/epiverse-trace/epichains/main/vignettes/img/transmission_chain_example.png) + +:::::::::::::::::::: + +Pour utiliser `{epichains}` nous devons connaître (ou supposer) deux valeurs épidémiologiques clés : la distribution de la descendance et le temps de génération. + +## Obtenez la distribution de la descendance + +Nous supposons ici que la distribution de la descendance du MERS suit une distribution binomiale négative, avec une moyenne (nombre de reproduction $R$) et une dispersion $k$ estimées à partir de la liste et des données de contact de `mers_korea_2015` dans la `{outbreaks}` R dans l'épisode précédent. + +```{r} +mers_offspring <- c(mean = 0.60, dispersion = 0.02) +``` + +:::::::::::::::::::::::::::: callout + +### distribution de la descendance pour les épichains + +Nous entrons une distribution de descendance dans `{epichains}` en faisant référence à la fonction R qui génère des valeurs aléatoires à partir de la distribution souhaitée. Pour une distribution binomiale négative, nous utilisons `rnbinom` avec la fonction `mu` et `size` arguments : + +```r + offspring_dist = rnbinom, + mu = mers_offspring["mean"], + size = mers_offspring["dispersion"], +``` + +Le manuel de référence en `?rnbinom` nous indique les arguments spécifiques requis. + +:::::::::::::::::::::::::::: + +:::::::::::::::::::::::::: spoiler + +### Poisson et autres distributions + +`{epichains}` peut accepter n'importe quelle fonction R qui génère des nombres aléatoires, de sorte que les arguments spécifiés changeront en fonction de la fonction R utilisée. Pour plus de détails sur les options possibles, consultez le manuel de référence de la fonction. + +Par exemple, disons que nous voulons utiliser une distribution de Poisson pour la distribution de la descendance. Tout d'abord, lisez l'argument requis dans le champ `?rpois` dans le manuel de référence. Ensuite, spécifiez l'argument `lambda` également connu sous le nom de taux ou de moyenne dans la littérature. En `{epichains}` cela peut ressembler à ceci : + +```r + offspring_dist = rpois, + lambda = mers_offspring["mean"], +``` + +Dans cet exemple, nous pouvons spécifier `lambda = mers_offspring["mean"]` car le nombre moyen de cas secondaires générés (c'est-à-dire $R$) devrait être le même quelle que soit la distribution que nous supposons. Ce qui change, c'est la variance de la distribution, et donc le niveau de variation de la transmission au niveau individuel. Lorsque le paramètre de dispersion $k$ s'approche de l'infini ($k \rightarrow \infty$) dans une distribution binomiale négative, la variance est égale à la moyenne. Cela fait de la distribution de Poisson classique un cas particulier de la distribution binomiale négative. + +:::::::::::::::::::::::::: + +## Obtenir le temps de génération + +Les [intervalle de série](../learners/reference.md#serialinterval) est souvent utilisée pour approximer la distribution du temps de génération. Cette approximation est couramment utilisée parce qu'il est plus facile d'observer et de mesurer l'apparition des symptômes dans chaque cas que le moment précis de l'infection. + +:::::::::::::::::::::::::::::::: spoiler + +### temps de génération vs intervalle sériel + +![Schéma de la relation entre les différentes périodes de transmission entre un infecteur et un infecté dans une paire de transmission. La fenêtre d'exposition est définie comme l'intervalle de temps au cours duquel se produit l'exposition virale, et la fenêtre de transmission est définie comme l'intervalle de temps pour la transmission ultérieure par rapport à la durée de l'infection ([Chung Lau et al., 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)).](fig/serial-interval-observed.jpeg) + +Cependant, l'utilisation de l'option *intervalle sériel* comme approximation de l'intervalle *temps de génération* est principalement valable pour les maladies dans lesquelles l'infectiosité commence après l'apparition des symptômes ([Chung Lau et al., 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)). Dans les cas où l'infectiosité commence avant l'apparition des symptômes, les intervalles sériels peuvent avoir des valeurs négatives, ce qui est le cas pour les maladies à transmission pré-symptomatique ([Nishiura et al., 2020](https://www.ijidonline.com/article/S1201-9712\(20\)30119-3/fulltext#gr2)). + +:::::::::::::::::::::::::::::::: + +Utilisons le `{epiparameter}` pour accéder à l'intervalle de série disponible pour la maladie MERS et l'utiliser : + +```{r, message=FALSE, warning=FALSE} +serial_interval <- epiparameter_db( + disease = "mers", + epi_name = "serial", + single_epiparameter = TRUE +) + +plot(serial_interval, day_range = 0:25) +``` + +```{r, echo=FALSE} +serial_summary <- serial_interval$summary_stats %>% + dplyr::as_tibble() %>% + dplyr::select(mean, sd) %>% + dplyr::distinct(.keep_all = TRUE) +``` + +L'intervalle de série pour le MERS a une moyenne de `r serial_summary$mean` jours et un écart-type de `r serial_summary$sd` jours. + +:::::::::::::::::::::::::::: callout + +### temps de génération pour les épichaïnes + +En `{epichains}` nous devons spécifier le temps de génération comme une fonction qui génère des nombres aléatoires. En utilisant `{epiparameter}` présente l'avantage d'utiliser la fonction de distribution `epiparameter::generate()` pour cette entrée. Le résultat sera le suivant : + +```r +function(x) generate(x = serial_interval, times = x) +``` + +Cette interface est similaire à celle de `{cfr}` pour établir un lien avec `{epiparameter}`. Lisez le [travailler avec des distributions de retard](https://epiverse-trace.github.io/cfr/articles/delay_distributions.html) pour plus de détails. + +:::::::::::::::::::::::::::: + +## Simuler une chaîne unique + +Nous sommes maintenant prêts à utiliser la fonction `simulate_chains()` de `{epichains}` pour créer **un** chaîne de transmission : + +```{r, message=FALSE, warning=FALSE, eval=FALSE} +epichains::simulate_chains( + # simulation controls + n_chains = 5, + statistic = "size", + # offspring + offspring_dist = rnbinom, + mu = mers_offspring["mean"], + size = mers_offspring["dispersion"], + # generation + generation_time = function(x) generate(x = serial_interval, times = x) +) +``` + +`simulate_chains()` nécessite au minimum trois séries d'arguments : + +- les contrôles de simulation, +- la distribution de la progéniture, et +- la durée de la génération. + +Dans les lignes ci-dessus, nous avons décrit comment spécifier la distribution des descendants et le temps de génération. Les **contrôle la simulation** comprennent au moins deux arguments : + +- `index_case`, qui définit le nombre de cas d'index pour simuler les chaînes de transmission pour et +- `statistic` qui définit une statistique de chaîne à suivre (soit `"size"` ou `"length"`) comme critère d'arrêt pour chaque chaîne simulée. + +::::::::::::::::::::::::::: callout + +### Critères d'arrêt + +Il s'agit d'une fonction personnalisable de `{epichains}`. Par défaut, les simulations de processus de ramification se terminent lorsqu'elles se sont éteintes. Pour les chaînes de transmission de longue durée, en `simulate_chains()` vous pouvez ajouter le paramètre `stat_threshold` vous pouvez ajouter l'argument + +Par exemple, si nous définissons un critère d'arrêt pour `statistic = "size"` de `stat_threshold = 500` il n'y aura plus de descendance après une chaîne de taille 500. + +::::::::::::::::::::::::::: + +Les `simulate_chains()` crée un `` que nous pouvons ensuite analyser dans R. + +## Simuler plusieurs chaînes + +Nous pouvons utiliser `simulate_chains()` pour créer plusieurs chaînes et augmenter la probabilité de simuler des projections de foyers incontrôlés en cas de distribution trop dispersée de la descendance. + +Nous devons spécifier trois éléments supplémentaires : + +- `set.seed()`, qui est une fonction de générateur de nombres aléatoires avec une valeur de semence spécifiée, la fonction `` afin de garantir des résultats cohérents entre les différentes exécutions du code. +- `number_simulations` qui définit le nombre de simulations à effectuer. +- `initial_cases` définit le nombre de cas initiaux à introduire dans le programme `n_chains` expliqué dans les lignes ci-dessus. + +```{r} +# Set seed for random number generator +set.seed(33) +# Number of simulation runs +number_simulations <- 1000 +# Number of initial cases +initial_cases <- 1 +``` + +`number_simulations` et `initial_cases` sont commodément stockés dans des objets pour faciliter leur réutilisation en aval dans le flux de travail. + +:::::::::::::::::::::::::::::: checklist + +### Itération à l'aide de purrr + +[Itération](https://r4ds.hadley.nz/iteration.html) vise à effectuer la même action sur différents objets de manière répétée. + +Apprenez à utiliser le noyau `{purrr}` comme `map()` à partir du tutoriel YouTube sur [Comment ronronner](https://www.youtube.com/watch?v=nd-Y8b22YaQ) par Equitable Equations. + +Ou, si vous avez déjà utilisé la fonction `*apply` visitez la vignette du paquet sur la famille de fonctions [purrr base R](https://purrr.tidyverse.org/articles/base.html) qui présente les principales différences, des traductions directes et des exemples. + +:::::::::::::::::::::::::::::: + +Pour obtenir plusieurs chaînes, nous devons appliquer la méthode `simulate_chains()` à chaque chaîne définie par une séquence de nombres allant de 1 à `r number_simulations`. + +::::::::::::::::::::::::::::::: callout + +### purrr et epichains + +Tout d'abord, décrivons comment nous utilisons `purrr::map()` avec `epichains::simulate_chains()`. Les `map()` nécessite deux arguments : + +- `.x`, un vecteur de nombres, et +- `.f` une fonction permettant d'itérer sur chaque valeur du vecteur. + +```r +map( + # vector of numbers (simulation IDs) + .x = seq_len(number_simulations), + # function to iterate to each simulation ID number + .f = function(sim) { + simulate_chains(...) %>% + # creates a column with the simulation ID number + mutate(simulation_id = sim) + } +) %>% + # combine list outputs (for each simulation ID) into a single data frame + list_rbind() +``` + +Les `sim` est placé pour enregistrer le numéro d'itération (**ID de simulation**) en tant que nouvelle colonne dans la base de données `` dans le fichier de sortie. Les `purrr::list_rbind()` a pour but de combiner toutes les sorties de liste de `map()`. + +**Pourquoi un point (`.`) comme préfixe ?** Dans le [principes de conception ordonnée](https://design.tidyverse.org/dots-prefix.html) nous avons un chapitre sur le préfixe point ! + +::::::::::::::::::::::::::::::: + +Nous sommes maintenant prêts à utiliser `map()` pour simuler de manière répétée de `simulate_chains()` et de stocker dans un vecteur de 1 à `r number_simulations`: + +```{r} +simulated_chains_map <- + # iterate one function across multiple numbers (simulation IDs) + purrr::map( + # vector of numbers (simulation IDs) + .x = seq_len(number_simulations), + # function to iterate to each simulation ID number + .f = function(sim) { + epichains::simulate_chains( + # simulation controls + n_chains = initial_cases, + statistic = "size", + # offspring + offspring_dist = rnbinom, + mu = mers_offspring["mean"], + size = mers_offspring["dispersion"], + # generation + generation_time = function(x) generate(x = serial_interval, times = x) + ) %>% + # creates a column with the simulation ID number + dplyr::mutate(simulation_id = sim) + } + ) %>% + # combine list outputs (for each simulation ID) into a single data frame + purrr::list_rbind() +``` + +```{r, echo=FALSE, eval=FALSE} +# view infectee number per simulation +simulated_chains_map %>% + dplyr::as_tibble() %>% + dplyr::count(simulation_id, sort = TRUE) +``` + +::::::::::::::::::::::::::::::::: discussion + +### Lire la sortie des épichains + +```{r, echo=FALSE} +#### get simulated chain with more infections -------------------------------- + +chains_subgroup <- simulated_chains_map %>% + as_tibble() %>% + group_by(simulation_id) %>% + distinct(infector) %>% + count(simulation_id) %>% + filter(n < 5, n >= 3) %>% + pull(simulation_id) + +chain_to_observe <- simulated_chains_map %>% + as_tibble() %>% + count(simulation_id, sort = TRUE) %>% + filter( + magrittr::is_in( + simulation_id, chains_subgroup + ) + ) %>% + filter(n < 10) %>% + filter(n == max(n)) %>% + slice_min(simulation_id) %>% + pull(simulation_id) +``` + +Pour explorer le format de sortie de l'outil `` objet de classe de nom `simulated_chains_map` examinons l'objet simulé `simulation_id` nombre `r chain_to_observe`. + +::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::: solution + +### L'objet épichaïnes + +Utilisons `dplyr::filter()` pour cela : + +```r +chain_to_observe <- 806 +``` + +```{r} +#### get epichain summary ---------------------------------------------------- + +simulated_chains_map %>% + dplyr::filter(simulation_id == chain_to_observe) +``` + +Les éléments clés de ce résultat se trouvent dans le pied de page, le texte qui apparaît en bas de page : + +```output +Number of infectors (known): 3 +Number of generations: 3 +``` + +La simulation `simulation_id` nombre `r chain_to_observe` comporte trois infecteurs connus et trois générations. Ces chiffres sont plus visibles lorsque vous lisez le `` sous la forme d'un cadre de données. + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: solution + +### Le cadre de données epichains + +```{r} +#### infector-infectee data frame -------------------------------------------- + +simulated_chains_map %>% + dplyr::filter(simulation_id == chain_to_observe) %>% + dplyr::as_tibble() +``` + +Chaîne `r chain_to_observe` nous indique une **histoire** Dans la première génération de transmission à `time = 0` un cas index a infecté le premier cas avec `sim_id = 1`. Ensuite, lors de la deuxième génération de transmission (entre `time` 10 à 16), `sim_id = 1` a infecté cinq cas. Plus tard, dans la troisième génération de transmission (entre `time` 26 à 30), `sim_id = 2` a infecté trois nouveaux cas". + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: solution + +### Une base de données d'infectés + +Le cadre de données de sortie rassemble **les infectés** comme unité d'observation : + +- Chaque personne infectée a une `sim_id`. +- Chaque *infecté* qui se comporte comme un *infecteur* est enregistré dans la base de données `infector` à l'aide de `sim_id` de cet infecté. +- Chaque personne infectée l'a été dans une `generation` et (continu) `time`. +- Le numéro de simulation est enregistré sous la rubrique `simulation_id` colonne. + +**Remarque :** Le `Number of infectors (known)` comprend le `NA` observation dans le cadre de la `infector` colonne. Il s'agit du vecteur spécifié comme cas index (dans la colonne `n_chains` ), qui a déclenché la chaîne de transmission à l'infecté de `sim_id = 1` à `generation = 1` et `time = 0`. + +::::::::::::::::::::::::: + +## Visualiser plusieurs chaînes + +Pour visualiser les chaînes simulées, nous avons besoin d'un traitement préalable : + +1. Utilisons `{dplyr}` pour obtenir des nombres de temps ronds qui ressemblent à des journées de surveillance. +2. Comptez les cas quotidiens dans chaque simulation (par `simulation_id`). +3. Calculez le nombre cumulé de cas dans une simulation. + +```{r} +# daily aggregate of cases +simulated_chains_day <- simulated_chains_map %>% + # use data.frame output from object + dplyr::as_tibble() %>% + # transform simulation ID column to factor (categorical variable) + dplyr::mutate(simulation_id = as_factor(simulation_id)) %>% + # get the round number (day) of infection times + dplyr::mutate(day = ceiling(time)) %>% + # count the daily number of cases in each simulation (simulation ID) + dplyr::count(simulation_id, day, name = "cases") %>% + # calculate the cumulative number of cases for each simulation (simulation ID) + dplyr::group_by(simulation_id) %>% + dplyr::mutate(cases_cumsum = cumsum(cases)) %>% + dplyr::ungroup() +``` + +Avant le tracé, créons un tableau récapitulatif avec la durée totale et la taille de chaque chaîne. Nous pouvons utiliser la fonction `{dplyr}` "combo" de `group_by()`, `summarise()` et `ungroup()`: + +```{r} +# Summarise the chain duration and size +sim_chains_max <- + simulated_chains_day %>% + dplyr::group_by(simulation_id) %>% + dplyr::summarise( + # duration + day_max = max(day), + # size + cases_total = max(cases_cumsum) + ) %>% + dplyr::ungroup() + +sim_chains_max +``` + +Nous sommes maintenant prêts à utiliser le `{ggplot2}` paquet : + +```{r} +# Visualize transmission chains by cumulative cases +ggplot() + + # create grouped chain trajectories + geom_line( + data = simulated_chains_day, + mapping = aes( + x = day, + y = cases_cumsum, + group = simulation_id + ), + color = "black", + alpha = 0.25, + show.legend = FALSE + ) + + # create points to visualize the chain endpoint + geom_point( + data = sim_chains_max, + mapping = aes( + x = day_max, + y = cases_total, + group = simulation_id, + color = simulation_id + ), + show.legend = FALSE + ) + + # define a 100-case threshold + geom_hline(aes(yintercept = 100), lty = 2) + + labs( + x = "Day", + y = "Cumulative cases" + ) +``` + +```{r, echo=FALSE, message=FALSE, warning=FALSE} +# proportion that reached the 100-case threshold +threshhold_summary <- sim_chains_max %>% + dplyr::arrange(dplyr::desc(day_max)) %>% + dplyr::filter(cases_total > 100) %>% + dplyr::count(name = "chains_theshold") %>% + dplyr::mutate(chains_number = number_simulations) %>% + dplyr::mutate(chains_percentage = chains_theshold / chains_number * 100) + +chains_extinct <- sim_chains_max %>% + dplyr::arrange(dplyr::desc(day_max)) %>% + dplyr::filter(day_max > 0) %>% + dplyr::summarise( + extinct_duration_median = stats::median(day_max), + extinct_size_median = stats::median(cases_total) + ) + +chains_null <- sim_chains_max %>% + dplyr::arrange(desc(cases_total)) %>% + dplyr::filter(day_max < 1) %>% + base::nrow() +``` + +Bien que la plupart des introductions de `r initial_cases` ne génèrent pas de cas secondaires (N = `r chains_null`) ou que la plupart des foyers s'éteignent rapidement (durée médiane de `r chains_extinct$extinct_duration_median` et taille médiane de `r chains_extinct$extinct_size_median`), seuls les `r threshhold_summary$chains_theshold` trajectoires épidémiques parmi les `r threshhold_summary$chains_number` simulations (`r threshhold_summary$chains_percentage`%) peuvent atteindre plus de 100 cas infectés. Ce résultat est d'autant plus remarquable que le nombre de reproduction $R$ est inférieur à 1 (moyenne de la distribution des descendants de `r mers_offspring[["mean"]]`), mais, compte tenu d'un paramètre de dispersion de la distribution des descendants de `r mers_offspring[["dispersion"]]` il montre le potentiel de flambées explosives de la maladie MERS. + +Nous pouvons compter combien de chaînes ont atteint le seuil de 100 cas en utilisant la fonction `{dplyr}` fonctions : + +```{r} +# number of chains that reached the 100-case threshold +sim_chains_max %>% + dplyr::arrange(desc(day_max)) %>% + dplyr::filter(cases_total > 100) +``` + +::::::::::::::::::::::::::::::::::: spoiler + +### Cas observés vs chaînes simulées + +Recouvrons le nombre cumulé de cas observés à l'aide de l'objet linelist de l'application `mers_korea_2015` du jeu de données `{outbreaks}` R. Pour préparer l'ensemble de données afin de pouvoir tracer le nombre total de cas quotidiens au fil du temps, nous utilisons l'objet `{incidence2}` pour convertir la liste de lignes en un fichier `` compléter les dates manquantes de la série temporelle à l'aide de l'objet `complete_dates()` + +```{r, warning=FALSE, message=FALSE} +library(outbreaks) + +mers_cumcases <- mers_korea_2015$linelist %>% + # incidence2 workflow + incidence2::incidence(date_index = "dt_onset") %>% + incidence2::complete_dates() %>% + # wrangling using {dplyr} + dplyr::mutate(count_cumsum = cumsum(count)) %>% + tibble::rownames_to_column(var = "day") %>% + dplyr::mutate(day = as.numeric(day)) +``` + +Utiliser `plot()` pour réaliser un diagramme d'incidence : + +```{r} +# plot the incidence2 object +plot(mers_cumcases) +``` + +::::::::::::::::::::::::::::::::::: + +Si l'on compare le nombre de cas cumulés observés lors de l'épidémie de syndrome respiratoire du Moyen-Orient (MERS) en Corée du Sud en 2015 avec les chaînes simulées précédemment, on constate que les cas observés ont suivi une trajectoire cohérente avec la dynamique de l'épidémie explosive simulée (ce qui est logique, étant donné que la simulation utilise des paramètres basés sur cette épidémie spécifique). + +```{r, echo=FALSE} +# Observed cases vs Simulated transmission chains +mers_cumcases_type <- + mers_cumcases %>% + mutate(type = "Observed") +simulated_chains_day_type <- + simulated_chains_day %>% + mutate(type = "Simulated") + +ggplot() + + geom_line( + data = simulated_chains_day_type, + mapping = aes( + x = day, + y = cases_cumsum, + group = simulation_id, + color = type + ) + ) + + geom_hline(aes(yintercept = 100), lty = 2) + + geom_line( + data = mers_cumcases_type, + mapping = aes( + x = day, + y = count_cumsum, + color = type + ), + linewidth = 1.5 + ) + + labs( + x = "Day since first report", + y = "Cumulative cases", + color = "Type" + ) +``` + +Lorsque nous augmentons le paramètre de dispersion de $k = 0.01$ à $k = \infty$ - et donc de réduire la variation de la transmission au niveau individuel - et que nous supposons un nombre de reproduction fixe $R = 1.5$ la proportion de foyers simulés atteignant le seuil de 100 cas augmente. Cela s'explique par le fait que les foyers simulés présentent désormais une dynamique plus cohérente, dans le sens des aiguilles d'une montre, plutôt que le niveau élevé de variabilité observé précédemment. + +![**Croissance des épidémies simulées avec R = 1,5 et un cas initial, sous réserve de non-extinction.** Les encadrés indiquent la médiane et l'intervalle interquartile (IQR) de la première génération de la maladie avec 100 cas ; les moustaches indiquent les valeurs les plus extrêmes dans un rayon de 1,5 × IQR des encadrés, et les croix indiquent les valeurs aberrantes. Les pourcentages indiquent la proportion de 10 000 foyers simulés qui ont atteint le seuil de 100 cas ([Lloyd-Smith et al., 2005](https://www.nature.com/articles/nature04153)).](fig/see-nature04153_Fig2-c.jpg) + +:::::::::::::::::::::: testimonial + +### Projections préliminaires de la propagation + +Dans la phase initiale de l'épidémie, vous pouvez utiliser `{epichains}` pour appliquer un modèle de processus de ramification afin de prévoir le nombre de cas futurs. Même si le modèle tient compte du caractère aléatoire de la transmission et de la variation du nombre de cas secondaires, il peut exister d'autres caractéristiques locales que nous n'avons pas prises en compte. L'analyse des premières prévisions faites pour le COVID dans différents pays à l'aide de cette structure de modèle a révélé que les prévisions étaient souvent trop confiantes ([Pearson et al., 2020](https://www.eurosurveillance.org/content/10.2807/1560-7917.ES.2020.25.18.2000543#validationofthemodel-1)). Cela est probablement dû au fait que le modèle en temps réel n'incluait pas tous les changements dans la distribution de la progéniture qui se produisaient au niveau local à la suite des changements de comportement et des mesures de contrôle. Pour en savoir plus sur l'importance du contexte local dans les modèles COVID-19, consultez le document suivant [Eggo et al. (2020)](https://www.nature.com/articles/s43588-020-00014-7). + +Nous vous invitons à lire la vignette sur [Prévision de l'incidence des maladies infectieuses : l'exemple de COVID-19](https://epiverse-trace.github.io/epichains/articles/projecting_incidence.html)! pour en savoir plus sur l'élaboration de prévisions à l'aide de `{epichains}`. + +:::::::::::::::::::::: + +## Défis + +:::::::::::::::::::::::::: challenge + +### Potentiel d'épidémie de variole du singe + +Évaluez le potentiel d'un nouveau cas de variole du singe (Mpox) à générer une épidémie explosive de grande ampleur. + +- Simulez 1000 chaînes de transmission avec 1 cas initial chacune. +- Utilisez le logiciel approprié pour accéder aux données sur les délais des épidémies précédentes. +- Combien de trajectoires simulées atteignent plus de 100 cas infectés ? + +:::::::::::::: hint + +Avec `{epiparameter}` vous pouvez accéder et utiliser les distributions de descendants et de retards des épidémies d'Ebola précédentes. + +```{r, warning=FALSE, message=FALSE} +library(epiparameter) +library(tidyverse) + +epiparameter::epiparameter_db(epi_name = "offspring") %>% + epiparameter::parameter_tbl() %>% + dplyr::count(disease, epi_name) + +epiparameter::epiparameter_db(epi_name = "serial interval") %>% + epiparameter::parameter_tbl() %>% + dplyr::count(disease, epi_name) +``` + +:::::::::::::: + +:::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +# load packages ----------------------------------------------------------- + +library(epiparameter) +library(tidyverse) + +# delays ------------------------------------------------------------------ + +mpox_offspring_epiparam <- epiparameter::epiparameter_db( + disease = "mpox", + epi_name = "offspring", + single_epiparameter = TRUE +) + +mpox_offspring <- epiparameter::get_parameters(mpox_offspring_epiparam) + +mpox_serialint <- epiparameter::epiparameter_db( + disease = "mpox", + epi_name = "serial interval", + single_epiparameter = TRUE +) + +# iterate ----------------------------------------------------------------- + +# Set seed for random number generator +set.seed(33) +# Number of simulation runs +number_simulations <- 1000 +# Number of initial cases +initial_cases <- 1 + +simulated_chains_mpox <- + # iterate one function across multiple numbers (simulation IDs) + purrr::map( + # vector of numbers (simulation IDs) + .x = seq_len(number_simulations), + # function to iterate to each simulation ID number + .f = function(sim) { + epichains::simulate_chains( + # simulation controls + n_chains = initial_cases, + statistic = "size", + # offspring + offspring_dist = rnbinom, + mu = mpox_offspring["mean"], + size = mpox_offspring["dispersion"], + # generation + generation_time = function(x) generate(x = mpox_serialint, times = x) + ) %>% + # creates a column with the simulation ID number + dplyr::mutate(simulation_id = sim) + } + ) %>% + # combine list outputs (for each simulation ID) into a single data frame + purrr::list_rbind() + +# visualize --------------------------------------------------------------- + +# daily aggregate of cases +simulated_chains_mpox_day <- simulated_chains_mpox %>% + # use data.frame output from object + dplyr::as_tibble() %>% + # transform simulation ID column to factor (categorical variable) + dplyr::mutate(simulation_id = as_factor(simulation_id)) %>% + # get the round number (day) of infection times + dplyr::mutate(day = ceiling(time)) %>% + # count the daily number of cases in each simulation (simulation ID) + dplyr::count(simulation_id, day, name = "cases") %>% + # calculate the cumulative number of cases for each simulation (simulation ID) + dplyr::group_by(simulation_id) %>% + dplyr::mutate(cases_cumsum = cumsum(cases)) %>% + dplyr::ungroup() + +# Visualize transmission chains by cumulative cases +ggplot() + + # create grouped chain trajectories + geom_line( + data = simulated_chains_mpox_day, + mapping = aes( + x = day, + y = cases_cumsum, + group = simulation_id + ), + color = "black", + alpha = 0.25, + show.legend = FALSE + ) + + # define a 100-case threshold + geom_hline(aes(yintercept = 100), lty = 2) + + labs( + x = "Day", + y = "Cumulative cases" + ) +``` + +Dans l'hypothèse d'une épidémie de variole du singe avec $R$ = 0,32 et $k$ = 0,58, il n'y a pas de trajectoire parmi 1000 simulations qui atteignent plus de 100 cas d'infection. Par rapport au MERS ($R$ = 0,6 et $k$ = 0.02). + +:::::::::::::: + +::::::::::::::::::: hint + +### Épidémie Évaluation du risque tenant compte de la superspreading + +Avec `{superspreading}` vous pouvez obtenir des solutions numériques à des processus qui `{epichains}` résoudre à l'aide de processus de branchement. Nous vous invitons à lire le `{superspreading}` vignette sur [Le risque épidémique](https://epiverse-trace.github.io/superspreading/articles/epidemic_risk.html) et répondez aux questions suivantes : + +- Quelle est la probabilité qu'un agent pathogène nouvellement introduit provoque une épidémie de grande ampleur ? +- Quelle est la probabilité qu'une infection ne s'établisse pas, par hasard, après une ou plusieurs introductions initiales ? +- Quelle est la probabilité que l'épidémie soit endiguée ? + +Vérifiez que ces estimations varient de manière non linéaire en fonction du nombre moyen de reproduction. $R$ et de la dispersion $k$ d'une maladie donnée. + + + + + +```{r, message=FALSE, warning=FALSE, echo=FALSE, eval=FALSE} +# estimate probability to contain +superspreading::probability_contain( + R = mers_offspring["mean"], + k = mers_offspring["dispersion"], + num_init_infect = 1, + case_threshold = 100 +) + +# Estimate the probability of a large outbreak +# with 5 independent imported cases +superspreading::probability_epidemic( + R = mers_offspring["mean"], + k = mers_offspring["dispersion"], + num_init_infect = 5 +) +``` + +```{r, message=FALSE, warning=FALSE, echo=FALSE, eval=FALSE} +# estimate probability to contain +superspreading::probability_contain( + R = mpox_offspring["mean"], + k = mpox_offspring["dispersion"], + num_init_infect = 1, + case_threshold = 100 +) + +# Estimate the probability of a large outbreak +# with 5 independent imported cases +superspreading::probability_epidemic( + R = mpox_offspring["mean"], + k = mpox_offspring["dispersion"], + num_init_infect = 5 +) +``` + +:::::::::::::::::: + +::::::::::::::::::::::::: + +:::::::::::::::::::::::::: challenge + +### À partir d'une distribution de cas secondaires + +[Christian Althaus, 2015](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099\(15\)70135-0/fulltext) données réutilisées publiées par [Faye et al, 2015 (Figure 2)](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099\(14\)71075-8/fulltext#gr2) sur l'arbre de transmission de la maladie à virus Ebola à Conakry, en Guinée, en 2014. + +En utilisant les données de l'étude **indice** estimez la distribution des descendants à partir de la distribution des cas secondaires. Estimez ensuite le potentiel d'apparition d'un foyer important à partir de ces données. + +::::::::::: hint + +Code avec les données de l'arbre de transmission écrites par [Christian Althaus, 2015](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099\(15\)70135-0/fulltext): + +```{r, message=FALSE, warning=FALSE} +# Number of individuals in the trees +n <- 152 +# Number of secondary cases for all individuals +c1 <- c(1, 2, 2, 5, 14, 1, 4, 4, 1, 3, 3, 8, 2, 1, 1, + 4, 9, 9, 1, 1, 17, 2, 1, 1, 1, 4, 3, 3, 4, 2, + 5, 1, 2, 2, 1, 9, 1, 3, 1, 2, 1, 1, 2) +c0 <- c(c1, rep(0, n - length(c1))) + +c0 %>% + enframe() %>% + ggplot(aes(value)) + + geom_histogram() +``` + +::::::::::: + +::::::::::: solution + +```r +# load packages --------------------------- +library(epichains) +library(epiparameter) +library(fitdistrplus) +library(tidyverse) +``` + +```{r, message=FALSE, warning=FALSE} +# fit a negative binomial distribution ------------------------------------ + +# Fitting a negative binomial distribution to the number of secondary cases +fit.cases <- fitdistrplus::fitdist(c0, "nbinom") +fit.cases + +# serial interval parameters ---------------------------------------------- + +ebola_serialinter <- epiparameter::epiparameter_db( + disease = "ebola", + epi_name = "serial interval", + single_epiparameter = TRUE +) + +# simulate outbreak trajectories ------------------------------------------ + +# Set seed for random number generator +set.seed(645) +# Number of simulation runs +number_simulations <- 1e2 +# Number of initial cases +initial_cases <- 1 + +sim_multiple_chains <- + purrr::map( + .x = seq_len(number_simulations), + .f = function(sim) { + epichains::simulate_chains( + n_chains = initial_cases, + # stopping + statistic = "size", + # offspring + offspring_dist = rnbinom, + mu = fit.cases$estimate["mu"], + size = fit.cases$estimate["size"], + # generation + generation_time = function(x) generate(x = ebola_serialinter, times = x) + ) %>% + dplyr::mutate(simulation_n = sim) + } + ) %>% + # combine list outputs (for each simulation ID) into a single data frame + purrr::list_rbind() + +# visualize ---------------------------------------- + +sim_chains_aggregate <- + sim_multiple_chains %>% + dplyr::as_tibble() %>% + dplyr::mutate(simulation_n = as_factor(simulation_n)) %>% + dplyr::mutate(day = ceiling(time)) %>% + dplyr::count(simulation_n, day, name = "cases") %>% + dplyr::group_by(simulation_n) %>% + dplyr::mutate(cases_cumsum = cumsum(cases)) %>% + dplyr::ungroup() + +ggplot() + + geom_line( + data = sim_chains_aggregate, + mapping = aes( + x = day, + y = cases_cumsum, + group = simulation_n + ), + show.legend = FALSE + ) + + # define a 100-case threshold + geom_hline(aes(yintercept = 100), lty = 2) +``` + +Il est remarquable que même avec un R0 inférieur à 1 (R = 0,95), nous puissions avoir des épidémies potentiellement explosives. La variation observée de la contagiosité individuelle dans le cas d'Ebola signifie que, bien que la probabilité d'extinction soit élevée, les nouveaux cas index ont également le potentiel d'une repousse explosive de l'épidémie. + +::::::::::: + +::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utiliser `{epichains}` pour simuler le potentiel d'épidémies importantes de maladies dont la distribution des descendants est trop dispersée. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/fr/learners/setup.md b/locale/fr/learners/setup.md new file mode 100644 index 00000000..bea60e03 --- /dev/null +++ b/locale/fr/learners/setup.md @@ -0,0 +1,235 @@ +--- +title: Mise en place +--- + +## Motivation + +**Éclosions** de maladies infectieuses peuvent apparaître à cause de différents agents pathogènes et dans différents contextes, mais elles conduisent généralement à des questions de santé publique similaires, allant de la compréhension des schémas de transmission et de gravité à l'examen de l'effet des mesures de contrôle ([Cori et al. 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371#d1e605)). Nous pouvons relier chacune de ces questions de santé publique à une série de tâches d'analyse des données relatives aux épidémies. Plus ces tâches sont efficaces et fiables, plus nous pouvons répondre rapidement et avec précision aux questions sous-jacentes. + +Epiverse-TRACE vise à fournir un écosystème logiciel pour [**l'analyse des épidémies**](reference.md#outbreakanalytics) grâce à des logiciels intégrés, généralisables et évolutifs pilotés par la communauté. Nous soutenons le développement de nouveaux progiciels R, nous aidons à relier les outils existants pour les rendre plus conviviaux et nous contribuons à une communauté de pratique composée d'épidémiologistes de terrain, de scientifiques des données, de chercheurs en laboratoire, d'analystes d'agences de santé, d'ingénieurs en logiciel et bien d'autres. + +### Tutoriels Epiverse-TRACE + +Nos tutoriels sont construits autour d'un pipeline d'analyse d'épidémies divisé en trois étapes : **Tâches préliminaires**, **Tâches intermédiaires** et **Tâches tardives**. Les résultats des tâches accomplies au cours des étapes précédentes alimentent généralement les tâches requises pour les étapes ultérieures. + +![Aperçu des thèmes abordés dans le cadre du tutorat](https://epiverse-trace.github.io/task_pipeline-minimal.svg) + +Chaque tâche a son site web de tutorat et chaque site web de tutorat consiste en un ensemble d'épisodes couvrant différents sujets. + +| [Tutoriels pour les premières tâches ➠](https://epiverse-trace.github.io/tutorials-early/) | [Didacticiels pour les tâches intermédiaires ➠](https://epiverse-trace.github.io/tutorials-middle) | [Travaux dirigés tardifs ➠](https://epiverse-trace.github.io/tutorials-late/) | +| ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| Lire et nettoyer les données de l'affaire, et établir une liste de contrôle | Analyse et prévision en temps réel | Modélisation de scénarios | +| Lire, nettoyer et valider les données des cas, convertir les données de la liste des lignes en incidence pour la visualisation. | Accéder aux distributions des retards et estimer les paramètres de transmission, prévoir les cas, estimer la gravité et la superposition. | Simulez la propagation de la maladie et étudiez les interventions. | + +Chaque épisode contient : + +- **Vue d'ensemble** Cet épisode décrit les questions auxquelles il sera répondu et les objectifs de l'épisode. +- **Conditions préalables** La description des épisodes/paquets qui doivent idéalement être couverts avant l'épisode en cours. +- **Exemple de code R** Le site web de la Commission européenne contient des exemples de code R afin que vous puissiez travailler sur les épisodes sur votre propre ordinateur. +- **Défis** Les défis : des défis à relever pour tester votre compréhension. +- **Explicatifs** Les Explicateurs sont des boîtes qui vous permettent de mieux comprendre les concepts mathématiques et de modélisation. + +Consultez également le site [glossaire](./reference.md) pour connaître les termes qui ne vous sont pas familiers. + +### Paquets Epiverse-TRACE R + +Notre stratégie consiste à incorporer progressivement des **R spécial** dans un pipeline d'analyse traditionnel. Ces progiciels devraient combler les lacunes dans les tâches spécifiques à l'épidémiologie en réponse aux épidémies. + +![Dans le cadre de l'analyse de l'épidémie de grippe aviaire, le **R** l'unité fondamentale du code partageable est le **paquet**. Un paquetage regroupe du code, des données, de la documentation et des tests et est facile à partager avec d'autres ([Wickham et Bryan, 2023](https://r-pkgs.org/introduction.html))](episodes/fig/pkgs-hexlogos-2.png) + +:::::::::::::::::::::::::::: prereq + +Ce contenu suppose une connaissance intermédiaire de R. Ces tutoriels sont pour vous si : + +- Vous savez lire des données dans R, les transformer et les remodeler, et créer une grande variété de graphiques. +- Vous connaissez les fonctions de `{dplyr}`, `{tidyr}` et `{ggplot2}` +- Vous pouvez utiliser le tube magrittr `%>%` et/ou le tuyau natif `|>`. + +Nous attendons des apprenants qu'ils soient familiarisés avec les concepts de base de la statistique, des mathématiques et de la théorie des épidémies, mais PAS avec une connaissance intermédiaire ou experte de la modélisation. + +:::::::::::::::::::::::::::: + +## Configuration du logiciel + +Suivez ces deux étapes : + +### 1\. Installez ou mettez à jour R et RStudio + +R et RStudio sont deux logiciels distincts : + +- **R** est un langage de programmation et un logiciel utilisé pour exécuter du code écrit en R. +- **RStudio** est un environnement de développement intégré (IDE) qui facilite l'utilisation de R. Nous vous recommandons d'utiliser RStudio pour interagir avec R. + +Pour installer R et RStudio, suivez les instructions suivantes . + +::::::::::::::::::::::::::::: callout + +### Déjà installé ? + +Ne perdez pas de temps : C'est le moment idéal pour vous assurer que votre installation R est à jour. + +Ce tutoriel nécessite **R version 4.0.0 ou ultérieure**. + +::::::::::::::::::::::::::::: + +Pour vérifier si votre version de R est à jour : + +- Dans RStudio, votre version de R sera imprimée en [la fenêtre de la console](https://docs.posit.co/ide/user/ide/guide/code/console.html). Ou exécutez `sessionInfo()` là. + +- **Pour mettre à jour R** téléchargez et installez la dernière version à partir du site [site web du projet R](https://cran.rstudio.com/) pour votre système d'exploitation. + + - Après l'installation d'une nouvelle version, vous devrez réinstaller tous vos paquets avec la nouvelle version. + + - Pour Windows, l'option `{installr}` peut mettre à jour votre version de R et migrer votre bibliothèque de paquets. + +- **Pour mettre à jour RStudio** ouvrez RStudio et cliquez sur + `Help > Check for Updates`. Si une nouvelle version est disponible, suivez les instructions suivantes + instructions à l'écran. + +::::::::::::::::::::::::::::: callout + +### Vérifiez régulièrement les mises à jour + +Bien que cela puisse paraître effrayant, c'est **bien plus courant** de rencontrer des problèmes dus à l'utilisation de versions obsolètes de R ou de paquets R. Il est donc recommandé de se tenir au courant des dernières versions de R, de RStudio et de tous les paquets que vous utilisez régulièrement. + +::::::::::::::::::::::::::::: + +### 2\. Installez les paquets R requis + +Ouvrez RStudio et **copiez et collez** le morceau de code suivant dans la fenêtre [fenêtre de la console](https://docs.posit.co/ide/user/ide/guide/code/console.html) puis appuyez sur la touche Entrer (Windows et Linux) ou Retour (MacOS) pour exécuter la commande : + +```r +# for episodes on access delays and quantify transmission + +if(!require("pak")) install.packages("pak") + +new_packages <- c( + "EpiNow2", + "epiparameter", + "incidence2", + "tidyverse" +) + +pak::pkg_install(new_packages) +``` + +```r +# for episodes on forecast and severity + +if(!require("pak")) install.packages("pak") + +new_packages <- c( + "EpiNow2", + "cfr", + "epiparameter", + "incidence2", + "outbreaks", + "tidyverse" +) + +pak::pkg_install(new_packages) +``` + +```r +# for episodes on superspreading and transmission chains + +if(!require("pak")) install.packages("pak") + +superspreading_packages <- c( + "epicontacts", + "fitdistrplus", + "superspreading", + "epichains", + "epiparameter", + "incidence2", + "outbreaks", + "tidyverse" +) + +pak::pkg_install(superspreading_packages) +``` + +Ces étapes d'installation peuvent vous demander `? Do you want to continue (Y/n)` écrire `Y` et d'appuyer sur Entrez. + +::::::::::::::::::::::::::::: spoiler + +### obtenez-vous une erreur avec EpiNow2 ? + +Les utilisateurs de Windows auront besoin d'une installation fonctionnelle de `Rtools` afin de construire le paquet à partir des sources. `Rtools` n'est pas un paquetage R, mais un logiciel que vous devez télécharger et installer. Nous vous suggérons de suivre les instructions suivantes : + +1. **Vérifier `Rtools` l'installation**. Vous pouvez le faire en utilisant la recherche Windows sur l'ensemble de votre système. En option, vous pouvez utiliser `{devtools}` l'exécution : + +```r +if(!require("devtools")) install.packages("devtools") +devtools::find_rtools() +``` + +Si le résultat est `FALSE` vous devez passer à l'étape 2. + +2. **Installer `Rtools`**. Téléchargez le `Rtools` l'installateur à partir de . Installez avec les sélections par défaut. + +3. **Vérifiez `Rtools` l'installation**. Encore une fois, nous pouvons utiliser `{devtools}`: + +```r +if(!require("devtools")) install.packages("devtools") +devtools::find_rtools() +``` + +::::::::::::::::::::::::::::: + +Vous devriez mettre à jour **tous les paquets** nécessaires au tutoriel, même si vous les avez installés relativement récemment. Les nouvelles versions apportent des améliorations et d'importantes corrections de bogues. + +Lorsque l'installation est terminée, vous pouvez essayer de charger les paquets en collant le code suivant dans la console : + +```r +# for episodes on access delays and quantify transmission + +library(EpiNow2) +library(epiparameter) +library(incidence2) +library(tidyverse) +``` + +```r +# for episodes on forecast and severity + +library(EpiNow2) +library(cfr) +library(epiparameter) +library(incidence2) +library(outbreaks) +library(tidyverse) +``` + +```r +# for episodes on superspreading and transmission chains + +library(epicontacts) +library(fitdistrplus) +library(superspreading) +library(epichains) +library(epiparameter) +library(incidence2) +library(outbreaks) +library(tidyverse) +``` + +Si vous ne voyez PAS d'erreur comme `there is no package called '...'` vous êtes prêt à partir ! Si c'est le cas, [contactez-nous](#your-questions)! + +## Jeux de données + +### Télécharger les données + +Nous téléchargerons les données directement à partir de R pendant le tutoriel. Cependant, si vous vous attendez à des problèmes de réseau, il peut être préférable de télécharger les données à l'avance et de les stocker sur votre machine. + +Les fichiers de données pour le tutoriel peuvent être téléchargés manuellement ici : + +- + +- + +## Vos questions + +Si vous avez besoin d'aide pour installer le logiciel ou si vous avez d'autres questions concernant ce tutoriel, veuillez envoyer un courriel à l'adresse suivante [andree.valle-campos@lshtm.ac.uk](mailto:andree.valle-campos@lshtm.ac.uk) + +