diff --git a/episodes/severity-static.Rmd b/episodes/severity-static.Rmd index 8617f0a9..058be7f3 100644 --- a/episodes/severity-static.Rmd +++ b/episodes/severity-static.Rmd @@ -10,7 +10,8 @@ editor_options: - Why do we estimate the clinical severity of an epidemic? -- How can the Case Fatality Risk (CFR) be estimated early in an ongoing epidemic? +- How can the Case Fatality Risk (CFR) be estimated early in an ongoing +epidemic? :::::::::::::::::::::::::::::::::::::::::::::::: @@ -34,8 +35,27 @@ This episode requires you to be familiar with: **Epidemic theory**: [Delay distributions](../learners/reference.md#delaydist). +**R packages installed**: `{cfr}`, `{epiparameter}`, `{outbreaks}`, `{tidyverse}`. + ::::::::::::::::::::::::::::::::: +:::::::::: spoiler + +Install packages if their are not already installed + +```{r, eval = FALSE} +# if {pak} is not installed, run: install.packages("pak") +pak::pak("cfr") +pak::pak("epiparameter") +pak::pak("tidyverse") +pak::pak("outbreaks") +``` + +If you have any error message, +go to the [main setup page](../learners/setup.md#software-setup). + +:::::::::: + ## Introduction Common questions at the early stage of an epidemic include: @@ -48,15 +68,12 @@ We can assess the pandemic potential of an epidemic with two critical measuremen ([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.'} +![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.'} One epidemiological approach to estimating the clinical severity is quantifying the Case Fatality Risk (CFR). CFR is the conditional probability of death given confirmed diagnosis, calculated as the ratio of the cumulative number of deaths from an infectious disease to the number of confirmed diagnosed cases. However, calculating this directly during the course of an epidemic tends to result in a naive or biased CFR given the time [delay](../learners/reference.md#delaydist) from onset to death, varying substantially as the epidemic progresses and stabilising at the later stages of the outbreak ([Ghani et al., 2005](https://academic.oup.com/aje/article/162/5/479/82647?login=false#620743)). -![Observed biased confirmed case fatality risk (CFR) estimates as a function of time (thick line) calculated as the cumulative number -of deaths over confirmed cases at time t. The estimate at the end of an outbreak (~May 30) is the realised CFR by the end of the epidemic. - The horizontal continuous line and dotted lines show the expected value and the 95% confidence intervals ($95\%$ CI) of the predicted delay-adjusted - CFR estimate only by using the observed data until 27 Mar 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){alt='The periods are relevant: Period 1 -- 15 days where CFR is zero to indicate this is due to no reported deaths; Period from Mar 15 -- Apr 26 where CFR appears to be rising; Period Apr 30 -- May 30 where the CFR estimate stabilises.'} +![Observed biased confirmed case fatality risk (CFR) estimates as a function of time (thick line) calculated as the cumulative number of deaths over confirmed cases at time t. The estimate at the end of an outbreak (~May 30) is the realised CFR by the end of the epidemic. The horizontal continuous line and dotted lines show the expected value and the 95% confidence intervals ($95\%$ CI) of the predicted delay-adjusted CFR estimate only by using the observed data until 27 Mar 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){alt='The periods are relevant: Period 1 -- 15 days where CFR is zero to indicate this is due to no reported deaths; Period from Mar 15 -- Apr 26 where CFR appears to be rising; Period Apr 30 -- May 30 where the CFR estimate stabilises.'} ::::::::::::::::::::::: instructor @@ -68,11 +85,12 @@ More generally, estimating severity can be helpful even outside of a pandemic pl Knowing whether an outbreak has or had a different severity from the historical record can motivate causal investigations, which could be intrinsic to the infectious agent (e.g., a new, more severe strain) or due to underlying factors in the population (e.g. reduced immunity or morbidity factors) ([Lipsitch et al., 2015](https://journals.plos.org/plosntds/article?id=10.1371/journal.pntd.0003846)). -In this tutorial we are going to learn how to use the `{cfr}` package to calculate and adjust a CFR estimation using [delay distributions](../learners/reference.md#delaydist) from `{epiparameter}` or elsewhere, based on the methods developed by [Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852), also, how we can reuse `{cfr}` functions for more severity measurements. +In this tutorial we are going to learn how to use the `{cfr}` package to calculate and adjust a CFR estimation using [delay distributions](../learners/reference.md#delaydist) from `{epiparameter}` or elsewhere, based on the methods developed by [Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852). We will also explore how we can reuse `{cfr}` functions for more severity measurements. -We'll use the pipe `%>%` operator to connect functions, so let's also call to the `{tidyverse}` package: +We'll use the pipe `%>%` operator from the `{magrittr}` package to connect functions from {cfr}, including others from the package `{dplyr}`. Hence, we will load the `{tidyverse}` package which contains both `{magrittr}` and `{dplyr}`. -```{r,message=FALSE,warning=FALSE} +```{r message=FALSE, warning=FALSE} +# load packages library(cfr) library(epiparameter) library(tidyverse) @@ -85,7 +103,7 @@ library(outbreaks) The double-colon `::` in R lets you call a specific function from a package without loading the entire package into the current environment. -For example, `dplyr::filter(data, condition)` uses `filter()` from the `{dplyr}` package. +For example, `dplyr::filter(data, condition)` uses the `filter()` function from the `{dplyr}` package. This helps us remember package functions and avoid namespace conflicts. @@ -93,11 +111,7 @@ This helps us remember package functions and avoid namespace conflicts. :::::::::::::::::::: discussion -Based on your experience: - -- Share any previous outbreak in which you participated in its response. - -Answer to these questions: +Have you been a member of an epidemic response team? If yes: - How did you assess the clinical severity of the outbreak? - What were the primary sources of bias? @@ -113,13 +127,13 @@ What data sources can we use to estimate the clinical severity of a disease outb ![Spectrum of COVID-19 cases. The CFR aims to estimate the proportion of deaths among confirmed cases in an epidemic. ([Verity et al., 2020](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(20)30243-7/fulltext#gr1))](fig/cfr-spectrum-cases-covid19.jpg) -- At the top of the pyramid, those who met the WHO case criteria for **severe** or critical cases would likely have been identified in the hospital setting, presenting with atypical viral pneumonia. These cases would have been identified in mainland China and among those categorised internationally as local transmission. +- At the top of the pyramid, those who met the WHO case criteria for **severe** or **critical** cases would likely have been identified in the hospital setting, presenting with atypical viral pneumonia. These cases would have been identified in mainland China and among those categorised internationally as local transmission. - Many more cases are likely to be **symptomatic** (i.e., with fever, cough, or myalgia) but might not require hospitalisation. These cases would have been identified through links to international travel to high-risk areas and through contact-tracing of contacts of confirmed cases. They might be identifiable through population surveillance of, for example, influenza-like illness. - The bottom part of the pyramid represents **mild** (and possibly **asymptomatic**) cases. These cases might be identifiable through contact tracing and subsequently via serological testing. ## Naive CFR -We measure disease severity in terms of case fatality risk (CFR). The CFR is interpreted as the conditional probability of death given confirmed diagnosis, calculated as the ratio of the cumulative number of deaths $D_{t}$ to the cumulative number of confirmed cases $C_{t}$ at a certain time $t$. We can refer to the _naive CFR_ (also crude or biased CFR, $b_{t}$): +We measure disease severity in terms of case fatality risk (CFR). The CFR is interpreted as the conditional probability of death given confirmed diagnosis, calculated as the ratio of the cumulative number of deaths $D_{t}$ to the cumulative number of confirmed cases $C_{t}$ at a certain time $t$. We can refer it to the _naive CFR_ (also crude or biased CFR, $b_{t}$): $$ b_{t} = \frac{D_{t}}{C_{t}} $$ @@ -131,7 +145,7 @@ To calculate the naive CFR, the `{cfr}` package requires an input data frame wit - `cases` - `deaths` -Let's explore the `ebola1976` dataset, included in {cfr}, which comes from the first Ebola outbreak in what was then called Zaire (now the Democratic Republic of the Congo) in 1976, as analysed by Camacho et al. (2014). +Let's explore the `ebola1976` dataset, included in {cfr}, which comes from the first Ebola outbreak in Zaire (now the Democratic Republic of the Congo) in 1976, as analysed by Camacho et al. (2014). ```{r} # Load the Ebola 1976 data provided with the {cfr} package @@ -174,12 +188,12 @@ This data input should be **aggregated** by day, which means one observation *pe Also, `{cfr}` currently works for *daily* data only, but not for other temporal units of data aggregation, e.g., weeks. - + :::::::::::::::::: -When we apply `cfr_static()` to `data` directly, we are calculating the naive CFR: +When we apply the `cfr_static()` function to the input `data` directly, we are calculating the naive CFR: ```{r} # Calculate the naive CFR for the first 30 days @@ -224,14 +238,13 @@ sarscov2_input <- sarscov2_input ``` -We can use `dplyr::rename()` to adapt the external data to fit the data input for `cfr_static()`. +We can use `cleanepi::standardize_column_names()` to adapt the external data to fit the data input for `cfr::cfr_static()`. ```{r} # Rename before Estimate naive CFR sarscov2_input %>% - dplyr::rename( - cases = cases_jpn, - deaths = deaths_jpn + cleanepi::standardize_column_names( + rename = c(cases = "cases_jpn", deaths = "deaths_jpn") ) %>% cfr::cfr_static() ``` @@ -350,7 +363,7 @@ When using an `` class object we can use this expression as a temp For distribution functions with parameters not available in `{epiparameter}`, we suggest you two alternatives: -- Create an `` class object, to plug into other R packages of the outbreak analytics pipeline. Read the [reference documentation of `epiparameter::epiparameter()`](https://epiverse-trace.github.io/epiparameter/reference/epiparameter.html), or +- Create an `` class object, to plug into other R packages of the outbreak analytics pipeline. Read the [reference documentation of `epiparameter::epiparameter()`](https://epiverse-trace.github.io/epiparameter/reference/epiparameter.html) - Read `{cfr}` vignette for [a primer on working with delay distributions](https://epiverse-trace.github.io/cfr/articles/delay_distributions.html). @@ -405,14 +418,13 @@ sarscov2_input <- sarscov2_input ``` -We can use `dplyr::rename()` to adapt the external data to fit the data input for `cfr_static()`. +We can use the `cleanepi::standardize_column_names()` to adapt the external data to fit the data input for `cfr_static()`. ```{r} # Rename before Estimate naive CFR sarscov2_input %>% - dplyr::rename( - cases = cases_jpn, - deaths = deaths_jpn + cleanepi::standardize_column_names( + rename = c(cases = "cases_jpn", deaths = "deaths_jpn") ) %>% cfr::cfr_static( delay_density = function(x) density(sarscov2_delay, x) @@ -501,7 +513,7 @@ rolling_cfr_adjusted <- cfr::cfr_rolling( ) ``` -With `utils::tail()`, we show that the latest CFR estimates. The naive and delay-adjusted estimates have overlapping ranges of 95% confidence intervals. +With `utils::tail()`, we view the latest CFR estimates. The naive and delay-adjusted estimates have overlapping ranges of 95% confidence intervals. ```{r,eval=FALSE,echo=TRUE} # Print the tail of the data frame @@ -536,7 +548,7 @@ dplyr::bind_rows( ) ``` -The horizontal line represents the delay-adjusted CFR estimated at the outbreak's end. The dotted line means the estimate has a 95% confidence interval (95% CI). +The red and blue lines represent the delay-adjusted and naive CFR, respectively, throughout the outbreak. The bands around them represent the 95% confidence intervals (95% CI). **Notice** that this delay-adjusted calculation is particularly useful when an _epidemic curve of confirmed cases_ is the only data available (i.e. when individual data from onset to death are unavailable, especially during the early stage of the epidemic). When there are few deaths or none at all, an assumption has to be made for the *delay distribution* from onset to death, e.g. from literature based on previous outbreaks. [Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) depict this in the figures with data from the SARS outbreak in Hong Kong, 2003. @@ -570,7 +582,7 @@ Discuss: :::::::::::::::::::::: hint -We can use either visual inspection or analysis of the output data frames. +We can either use a visual inspection or analyse the output data frames. :::::::::::::::::::::: @@ -731,12 +743,11 @@ library(outbreaks) library(tidyverse) # Access delay distribution -mers_delay <- - epiparameter::epiparameter_db( - disease = "mers", - epi_name = "onset to death", - single_epiparameter = TRUE - ) +mers_delay <- epiparameter::epiparameter_db( + disease = "mers", + epi_name = "onset to death", + single_epiparameter = TRUE +) # Read linelist mers_korea_2015$linelist %>% @@ -755,7 +766,7 @@ mers_incidence # Prepare data from {incidence2} to {cfr} mers_incidence %>% - prepare_data( + cfr::prepare_data( cases_variable = "dt_onset", deaths_variable = "dt_death" ) 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..1eadbe40 --- /dev/null +++ b/locale/fr/episodes/quantify-transmissibility.Rmd @@ -0,0 +1,594 @@ +--- +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 paquet `EpiNow2`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Conditions préalables + +Les étudiants 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 reproduction effectif. + +**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 : le nombre de reproduction effectif, $R_t$ + +Le [nombre 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 susceptible. + +Mais dans une épidémie en cours, la population ne reste pas entièrement susceptible, 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 du **nombre de reproduction effectif**, $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'une épidémie 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 l'épidémie se propage ou décline (temps de doublement/dédoublement) 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 les dates d'infections et les dates de cas déclarés. Lors d'une é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 la [vignette.](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections.html). + +Dans ce tutoriel, nous allons apprendre à utiliser le paquet `{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 deux-points `::` dans R vous permet d'appeler une fonction spécifique d'un paquet sans charger l'ensemble du paquet 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 du paquet `{dplyr}`. + +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 étudiants 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 paquet 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 déclarées. 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 a priori (distributions a priori) et les données (via une fonction de vraisemblance) pour obtenir la probabilité a posteriori : + +$\text{Probabilité a posteriori} \propto \text{vraisemblance} \times \text{probabilité a priori}$ + +:::::::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::: instructor + +Faites référence à la distribution de probabilité a priori et à la [probabilité a posteriori](https://en.wikipedia.org/wiki/Posterior_probability) a posteriori. + +Dans la ["`Expected change in reports`", l'appel](#expected-change-in-daily-cases) par "la probabilité a posteriori que $R_t < 1$"nous nous référons spécifiquement à la [aire sous la courbe de distribution de la probabilité a posteriori](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 paquet 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 cas déclarés (confirmés) à 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 sur différentes périodes de temps (*intervalles*, c'est-à-dire des jours, des semaines ou des mois) ou par groupe. Nous pouvons également obtenir les 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 du paquet `{dplyr}`. + +```{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, `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 paquet 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 distribution **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. Dans cet example, nous allons utiliser une distribution *log 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 a priori *log-normal* 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é d' *échantillons* et de *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 à 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 paquet 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 arguments de `epinow()` dans 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 +) +``` + +Visualisez 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..1726d3fa --- /dev/null +++ b/locale/fr/episodes/severity-static.Rmd @@ -0,0 +1,877 @@ +--- +title: "Estimation de la gravité d'une é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é (RL) au début d'une épidémie en cours ? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectifs + +- Estimer le risque de létalité (RL) à partir de données épidémiologiques agrégées en utilisant la librairie `{cfr}`. + +- Estimer le RL ajusté au délai épidémiologique à l'aide des librairies `{epiparameter}` et `{cfr}`. + +- Estimer la sévérité ajustée au délai épidémiologique pour une série +chronologique en expansion en utilisant le package `{cfr}`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +Les concepts abordés dans cet épisode supposent que vous êtes familiers avec : + +**Science des données**: Programmation de base avec R. + +**Théorie des épidémies**: [Distributions des délais](../learners/reference.md#delaydist). + +**R packages installés**: `{cfr}`, `{epiparameter}`, `{outbreaks}`, `{tidyverse}`. + +::::::::::::::::::::::::::::::::: + +:::::::::::::: spoiler + +Installer les packages si elles ne le sont pas déjà: + +```{r, eval = FALSE} +# si {pak} n'est pas disponible, exécutez : install.packages("pak") +pak::pak("cfr") +pak::pak("epiparameter") +pak::pak("tidyverse") +pak::pak("outbreaks") +``` + +Si vous recevez un message d'erreur, rendez-vous sur la [page principale de configuration](../learners/setup.md#configuration-des-logiciels). + +:::::::::::::: + +## Introduction + +Les questions les plus fréquentes au début d'une épidémie sont: + +- 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)). + +![Scénarios de planification pandémique du HHS basés sur le cadre d'évaluation de la gravité de la pandémie. Ce cadre utilise une mesure combinant la gravité clinique et la transmissibilité pour caractériser les scénarios de pandémie de grippe. **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))](../../../episodes/fig/cfr-hhs-scenarios-psaf.png){alt='L'axe horizontal représente la mesure de la gravité clinique, échelonnée de 1 à 7, où 1 correspond à faible, 4 à modérée et 7 à très grave. L'axe vertical représente la mesure de la transmissibilité, échelonnée de 1 à 5, où 1 correspond à faible, 3 à modérée et 5 à forte transmissibilité. Sur le graphique, les scénarios de planification d'une pandémie sont présentés en quatre quadrants (A, B, C et D). De gauche à droite, les scénarios sont: “variation saisonnière”, “pandémie modérée”, “pandémie grave” et “pandémie très grave”. À mesure que la gravité clinique augmente sur l'axe horizontal, ou que la transmissibilité augmente sur l'axe vertical, la gravité du scénario de planification de la pandémie augmente également.'} + +Une approche épidémiologique pour estimer la gravité clinique consiste à quantifier le risque de létalité (RL). 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 calcule de ce paramètre de cette façon au cours d'une épidémie tend à aboutir à un RL naïf ou biaisé, compte tenu du [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é (RL) observé biaisé confirmé en fonction du temps (ligne épaisse), calculé comme le rapport entre le nombre cumulé de décès et de cas confirmés à un instant $t$. La valeur atteinte à la fin d'une épidémie (~30 mai) est le risque de létalité observé à la fin de l'épidémie. La ligne horizontale continue et les lignes pointillées indiquent la valeur du RL prédit et leurs intervalles de confiance à 95% (IC $95%$) des valeurs prédites 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))](../../../episodes/fig/cfr-pone.0006852.g003-fig_c.png){fig-alt="Les périodes sont pertinentes : Période 1 -- 15 jours où le RL est nul, ce qui indique qu'aucun décès n'a été signalé ; Période du 15 mars au 26 avril où le RL semble augmenter ; Période du 30 avril au 30 mai où l'estimation du RL se stabilise."} + +::::::::::::::::::::::: instructeur + +Les périodes sont pertinentes : Période 1 -- 15 jours où le RL est nul, ce qui indique qu'aucun décès n'a été signalé ; Période du 15 mars au 26 avril où le RL semble augmenter ; Période du 30 avril au 30 mai où l'estimation du RL se stabilise. + +::::::::::::::::::::::: + +Généralement, l'estimation de la gravité clinique d'une maladie 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 pour identifier les causes. Celles-ci peuvent être intrinsèques à l'agent infectieux (par exemple, une nouvelle souche plus grave) ou liées à 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 librairie `{cfr}` pour calculer et ajuster le risque de gravité clinique en utilisant [la distribution des délais](../learners/reference.md#delaydist) obtenue de la librairie `{epiparameter}` ou de d'autres sources, 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). Nous allons aussi explorer la libraire `{cfr}` pour determiner comment l'utiliser pour calculer d'autres mesures de sévérité clinique. + +Nous utiliserons l'opérateur pipe (`%>%`) de la librairie `{magrittr}` pour relier facilement certaines fonctions de la librairie `{cfr}`, y compris les fonctions de la librairie de formatage de données `{dplyr}`. Nous chargerons donc la librairie `{tidyverse}`, qui comprend à la fois les librairies `{magrittr}` et `{dplyr}`. + +```{r message=FALSE, warning=FALSE} +# charger les packages +library(cfr) +library(epiparameter) +library(tidyverse) +library(outbreaks) +``` + +::::::::::::::::::: checklist + +### L'opérateur double deux-points (`::`) + +L'opérateur `::` de R permet d'accéder aux fonctions ou aux objets d'un package spécifique sans attacher l'intégralité du package (sans faire appel à la function `libray()`). Il offre plusieurs avantages, notamment : + +* Indiquer explicitement le package d'origine d'une fonction, réduisant ainsi les ambiguïtés et les conflits potentiels lorsque plusieurs packages possèdent des fonctions portant le même nom. +* Permettre d'appeler une fonction depuis un package sans charger l'intégralité du package avec un appel à la fonction `library()`. + +Par exemple, la commande `dplyr::filter(data, condition)` signifie que nous appelons la fonction `filter()` depuis la librairie `{dplyr}`. + +::::::::::::::::::: + +:::::::::::::::::::: discussion + +Etiez-vous membre d'une équipe chargée de de concevoir des stratégies de réponse à une épidémie? Si oui: + +- Comment évaluez-vous la gravité clinique de l'épidémie ? +- Quelles étaient les principales sources de biais ? +- Qu'aviez-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 sont les sources de données qu'on peut utiliser pour estimer la gravité clinique d'une épidémie? +[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))](../../../episodes/fig/cfr-spectrum-cases-covid19.jpg) + +- Au sommet de la pyramide, les cas définis comme **grave** ou **critiques** selon les critères établis par l'OMS. Ces cas auraient probablement été identifiés en milieu hospitalier, présentant une pneumonie virale atypique. Ils auraient été identifiés en Chine continentale et parmi ceux classés au niveau international comme émanants d'une transmission locale. +- Beaucoup d'autres sont probablement **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 à leurs liens avec des voyageurs internationaux dans des zones à haut risque et grâce à la recherche des personnes en contact avec les 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 cas **bénins** (et éventuellement **asymptomatiques**). Ces cas pourraient être identifiés par la recherche de cas contacts et, puis par des tests sérologiques. + +## Estimation du risque de létalité (RL) naïf + +Nous mesurons la gravité d'une maladie en termes de risque de létalité (RL). Le RL 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$. Nous pouvons le référer au *RL naïf* (également RL brut ou biaisé, $b_{t}$) : + +$$ b_{t} = \frac{D_{t}}{C_{t}} $$ + +Cette formule est considérée comme *naïve* parce qu'elle tend à produire un RL 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 que vers la fin de l'épidémie. + +Pour calculer le RL naïf à l'aide de la librairie `{cfr}`, on a besoin d'un tableau de données comportant au minimum trois colonnes nommées : + +- `date` +- `cases` +- `deaths` + +Explorons le tableau de données `ebola1976` inclus dans le package `{cfr}`, et qui contient les données provenant de la première épidémie d'Ebola au Zaïre (actuelle la République Démocratique du Congo) en 1976, comme l'ont analysé Camacho et al. (2014). + +```{r} +# charger le tableau de donnees ebola1976 du package {cfr} +data("ebola1976") + +# Visualiser l'incidence du nombre de cas et de deces repertorie +ebola1976 %>% + incidence2::incidence( + date_index = "date", + counts = c("cases", "deaths") + ) %>% + plot() +``` + +Nous supposerons que nous sommes dans le contexte d'une **épidémie d'Ebola en cours** où nous disposons que des données collectées durant les **30 premiers jours** de l'épidémie. + +```{r} +# supposons que nous disposons des donnees des 30 premiers jours de l'epidemie +ebola_30days <- ebola1976 %>% + dplyr::slice_head(n = 30) %>% + dplyr::as_tibble() + +ebola_30days +``` + +:::::::::::::::::: callout + +### Nous avons besoin de données d'incidence agrégées + +Les données d'entrée des fonctions de la `{cfr}` sont des données d'incidence, qui sont ont été **agrégées** à partir des données de cas individuels. + + + +```{r, eval=FALSE, echo=FALSE} +EpiNow2::example_confirmed %>% + dplyr::as_tibble() +``` + +Ces données doivent être **agrégées** par “unité de temps”, c'est-à-dire une observation par unité de temps, contenant le nombre de cas et de décès signalés en un temps donné. Les observations avec des valeurs nulles ou manquantes doivent également être incluses, comme pour les données de séries temporelles. + +Cependant, il faut noter que la version actuelle de `{cfr}` requière des données agrégées *journaliers*. Les autres unités temporelles d'agrégation de données telles que les semaines, mois, etc ne sont pour le moment pas pris en charge. + + + + + +:::::::::::::::::: + +La fonction `cfr::cfr_static()` permet de calculer le RL naïf. + +```{r} +# Calculer le RL naïf durant les 30 premiers jours +cfr::cfr_static(data = ebola_30days) +``` + +:::::::::::::::::::::::::::::::::::::::: challenge + +Téléchargez le fichier [sarscov2_cases_deaths.csv](../../../episodes/data/sarscov2_cases_deaths.csv) et importez-le dans R. Puis estimez le RL naïf. + +:::::::::::::::::::: + +:::::::::::::::::::: hint + +Vérifier le format des données d'entrée en répondant aux questions suivantes: + +- Contient-il des données d'incidences quotidiennes ? +- Les noms des colonnes sont-ils conformes aux exigences de la fonction `cfr_static()` ? +- Comment renommer les noms de colonnes d'un tableau de données ? + +:::::::::::::::::::: + +:::::::::::::::::::: solution + +Importez les données téléchargées à l'aide de la fonction `readr::read_csv()`. Cette fonction reconnaît que la colonne `date` est de type ``. + +```{r, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE} +# importer les données dans R +sarscov2_input <- readr::read_csv( + file = file.path("data", "sarscov2_cases_deaths.csv") +) +``` + +```{r, eval=FALSE, echo=TRUE, warning=FALSE, message=FALSE} +# importer les données dans R +# supposons que le chemin d'accès au fichier est data/raw-data/ebola_cases.csv +sarscov2_input <- readr::read_csv( + file = here::here("data", "raw-data", "sarscov2_cases_deaths.csv") +) +``` + +```{r} +# voir un aperçu des données +sarscov2_input +``` + +Nous pouvons utiliser la fonction `cleanepi::standardize_column_names()` pour renommer les noms des colonnes de sorte qu'elles soient conforment aux exigences de la fonction `cfr::cfr_static()`. + +```{r} +# renommer les noms des colonnes +sarscov2_input <- sarscov2_input %>% + cleanepi::standardize_column_names( + rename = c(cases = "cases_jpn", deaths = "deaths_jpn") + ) + +# estimer le RL naïf +cfr::cfr_static(sarscov2_input) +``` + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: + +## Biais affectant l'estimation du CFR + +::::::::::::::::::::::::::::: discussion + +### Deux biais qui affectent l'estimation du RL + +[Lipsitch et al, 2015](https://journals.plos.org/plosntds/article?id=10.1371/journal.pntd.0003846) ont décrit deux biais potentiels qui peuvent affecter l'estimation du RL (et comment y remédier) : + +::::::::::::::::::::::::::::: + +::::::::::::: solution + +### 1. Études 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, admises à l'hôpital ou décèdent. + +Par conséquent, le RL sera généralement plus élevé chez les *cas confirmé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 + +Lors d'une épidémie *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 contient des individus 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é. Ainsi, la division du nombre cumulé de décès déclarés par le nombre cumulé de cas déclarés en un moment donné d'une épidémie sous-évaluera le véritable RL. + +Les principaux facteurs déterminants de l'ampleur du biais sont, le *taux de croissance de l'épidémie* et la *distribution des délais* entre la déclaration des cas et la déclaration des décès ; plus les délais sont longs, plus le taux de croissance est rapide, et plus le biais est important. + +Dans les sections suivantes de cet épisode du tutoriel, nous allons nous concentrer sur les solutions concernant spécifiquement ce biais en utilisant la librairie `{cfr}`. + +:::::::::::: + +:::::::::::::::::::: solution + +### Étude de cas : Grippe A (H1N1), Mexique, 2009 + +Il est crucial d'améliorer l'estimation du RL ajusté au délais au début d'une épidémie pour déterminer sa virulence, mais aussi le niveau et les choix des interventions 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 effectué une estimation précoce biaisée du RL. 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 durant les dix jours qui ont suivi la déclaration d'urgence de santé publique par l'OMS. Même dans des circonstances similaires, au début d'une 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) ont réinterprété les données en évaluant les biais et ont obtenu 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 + +Vous trouverez plus d'informations concernant l'effet des délais dans l'estimation du RL dans cette section de la [vignette de la librairie `{cfr}` ](https://epiverse-trace.github.io/cfr/articles/cfr.html#concept-how-reporting-delays-bias-cfr-estimates). + + + +:::::::::::::::::::: + +## RL ajusté au délai + +[Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) ont développé une méthode de calcul du RL qui prend en compte les **délais** entre l'apparition des symptômes et le décès. + +Durant certaines phases d'une épidémie en cours, il peut arriver que le nombre de décès soit insuffisant pour déterminer la distribution du temps entre l'apparition des symptômes et le décès. Par conséquent, nous pouvons obtenir une estimation de la *distribution de ce délai* à partir d'épidémies antérieures ou en réutilisant celles qui sont accessibles via des librairies R tels que `{epiparameter}` ou `{epireview}` qui les collectent à partir de la littérature scientifique publiée. Lisez l'épisode [accéder aux délais épidémiologiques](https://epiverse-trace.github.io/tutorials-early/delays-reuse.html) de ce tutoriel pour de plus amples informations. + +Obtenons la distribution du délai entre la date d'apparition des symptômes et la +date de décès via la librairie `{epiparameter}`. + +```{r, message=FALSE, warning=FALSE} +# obtenir la distribution du délai +onset_to_death_ebola <- epiparameter::epiparameter_db( + disease = "Ebola", + epi_name = "onset_to_death", + single_epiparameter = TRUE +) + +# visualiser la distribution du délai +plot(onset_to_death_ebola, day_range = 0:40) +``` + +Pour prendre en compte la distribution du délai lors du calcul le RL ajusté au délai, nous devons fournir à l'arguemt `delay_density` de la fonction `cfr::cfr_static()` la valeur correspondante. + +```{r} +# calculer le RL ajusté au délai pour les 30 premiers jours +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 %>% dplyr::pull(severity_estimate) +out_low <- out_delay_adjusted %>% dplyr::pull(severity_low) +out_high <- out_delay_adjusted %>% dplyr::pull(severity_high) +``` + +Le RL ajusté au délai indique que la gravité globale de la maladie *à la fin de l'épidémie* ou selon les *récentes 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`, légèrement supérieure à la valeur naïve. + +:::::::::::::::::: callout + +### Utilisation des objets de la classe epiparameter + +Lorsque vous utilisez un object de la classe ``, vous pouvez 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éer un objet de la classe `` pour l'intégrer dans d'autres packages R d'un pipeline d'analyse épidémiologique. Lisez l'article [document de référence de `epiparameter::epiparameter()`](https://epiverse-trace.github.io/epiparameter/reference/epiparameter.html) pour plus de clarifications. + +- Liser la vignette de `{cfr}` portant sur [l'utilisation des distributions des délais](https://epiverse-trace.github.io/cfr/articles/delay_distributions.html). + +:::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: challenge + +Utilisez le même fichier ([sarscov2_cases_deaths.csv](data/sarscov2_cases_deaths.csv)) que celui du défi précédent pour: + +- Estimer le RL ajusté au délai en utilisant la distribution de délai adéquate. +- Comparer les résultats du RL naïf et du RL ajusté au délai. + +:::::::::::::::::::: hint + +- Trouver l'objet de la classe `` approprié pour ces données. + +:::::::::::::::::::: + +:::::::::::::::::::: solution + +Nous utiliserons la librairie `{epiparameter}` pour accéder à une distribution des délais pour les données d'incidence du SARS-CoV-2. + +```{r, message=FALSE, warning=FALSE} +library(epiparameter) + +sarscov2_delay <- epiparameter::epiparameter_db( + disease = "covid", + epi_name = "onset to death", + single_epiparameter = TRUE +) +``` + +Les données seront importées dans R à l'aide de la fonction `readr::read_csv()`. Cette fonction reconnaît que la colonne `date` est de type ``. + +```{r, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE} +# importer les donnees +sarscov2_input <- readr::read_csv( + file = file.path("data", "sarscov2_cases_deaths.csv") +) +``` + +```{r, eval=FALSE, echo=TRUE} +# importer les donnees +# supposons que le chemin d'accès au fichier est: data/raw-data/ebola_cases.csv +sarscov2_input <- readr::read_csv( + file = here::here("data", "raw-data", "sarscov2_cases_deaths.csv") +) +``` + +```{r} +# voir un apperçu des donnees +sarscov2_input +``` + +Nous pouvons utiliser la fonction `cleanepi::standardize_column_names()` pour renommer les noms des colonnes de sorte qu'elles soient conforment à la fonction `cfr::cfr_static()`. + +```{r} +# renommer les noms des colonnes avant d'estimer le RL ajusté au délai +sarscov2_input %>% + cleanepi::standardize_column_names( + rename = c(cases = "cases_jpn", deaths = "deaths_jpn") + ) %>% + cfr::cfr_static( + delay_density = function(x) density(sarscov2_delay, x) + ) +``` + +Comparer et interpréter les estimations du RL naïfs et ajusté au délais. + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::: spoiler + +### Quand doit-on utiliser les distributions discrètes ? + +Pour la fonction `cfr_static()` et les autres de la famille `cfr_*()`, les distributions les plus appropriées sont les **distributions discrets**. Ceci en raison du fait que nous travaillerons avec des données d'incidence quotidiennes sur le nombre de cas et de décès. + +Nous pouvons supposer que l'évaluation de la fonction de distribution de probabilité (FDP) d'une distribution *continue* est équivalente à la fonction de masse de probabilité (FMP) de la distribution *discrète* correspondante. + +Toutefois, cette hypothèse pourrait être inappropriée en présence de distributions présentant des pics énormes. C'est le cas, par exemple, des maladies dont la distribution du délai entre la date d'apparition des symptômes et la date du décès présente un pic très élevé et une faible variance. Dans ce cas, la disparité moyenne entre la FDP et la FMP devrait être plus prononcée que pour les distributions avec de larges variances. Une façon d'y remédier est de discrétiser la distribution continue en appliquant la fonction `epiparameter::discretise()` à un objet de la classe ``. + +:::::::::::::::::: + +::::::::::::::::::::::::::: spoiler + +### Comment fonctionne la librairie {cfr} ? + +Pour ajuster le RL, [Nishiura et al. 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) ont utilisé les incidences des cas et des décès pour estimer le nombre de cas dont les pronostiques vitaux 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 à l'instant $t$, +- $f_{t}$ est la valeur de la fonction de masse de probabilité (FMP) de la **distribution des délais** entre l'apparition des symptômes et le décès, et +- $u_{t}$ représente le facteur de sous-estimation des statuts vitals connus. + +$u_{t}$ est utilisé pour **ajuster l'échelle** du nombre cumulé de cas au niveau du dénominateur dans le calcul du RL. Ce calcul est effectué en interne à l'aide de la fonction [`estimate_outcomes()`](https://epiverse-trace.github.io/cfr/reference/estimate_outcomes.html). + +L'estimateur du RL peut être écrit comme suit : + +$$p_{t} = \frac{b_{t}}{u_{t}}$$ + +où $p_{t}$ est la proportion réelle de cas confirmés qui meurent de l'infection (ou le RL non biaisé), et $b_{t}$ est l'estimation brute et biaisée du RL (ou RL naïf). + +D'après cette dernière équation, nous observons que le RL non biaisé $p_{t}$ est plus élevé que le RL biaisé $b_{t}$, car le numérateur dans $u_{t}$ est plus petit que le dénominateur (notez que $f_{t}$ est la distribution de probabilité de la *distribution des délais* entre l'apparition des symptômes et le décès). Par conséquent, $b_{t}$ est considérer comme l'estimateur biaisé du RL. + +Lorsque nous observons toute 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 RL au début d'une épidémie + +L'estimation du RL **naïf** est utile pour obtenir une estimation globale de la gravité d'une épidémie (jusqu'au moment $t$). À la fin de l'épidémie ou lorsqu'on atteint un niveau où on a de plus en plus de décès sont signalés, le RL estimé sera alors plus proche du "véritable" RL non biaisé. + +Par ailleurs, la valeur RL **ajusté au délai** estimée au début d'une épidémie refléte mieux la gravité d'une maladie infectieuse émergente que le RL biaisé ou naïf obtenu au cours de l'épidémie. + +Nous pouvons calculer le *RL ajusté au délai* au début d'une épidémie à l'aide de la fonction `cfr::cfr_rolling()`. + +:::::::::::::::::::::: callout + +`cfr::cfr_rolling()` est une fonction utilitaire qui calcule automatiquement le RL à chaque jour de l'épidémie à l'aide des données disponibles au jour de l'estimation, permettant ainsi à l'utilisateur de gagner du temps. + +:::::::::::::::::::::: + +`cfr::cfr_rolling()` montre le RL estimé à chaque jour de l'épidémie, étant donné que les données futures sur les nombres de cas et de décès ne sont pas disponibles à ce moment-là. Pour un même jeu de données, la valeur finale de `cfr::cfr_rolling()` est identique à celle de `cfr::cfr_static()`. + +```{r} +# Calculer le RL naïf quotidien à chacun des 73 jours dans un jeu de donnees +# d'Ebola +rolling_cfr_naive <- cfr::cfr_rolling(data = ebola1976) +``` + +```{r} +# Calculer le RL quotidien ajusté au délai à chacun des 73 jours dans un jeu de +# donnees d'Ebola +rolling_cfr_adjusted <- cfr::cfr_rolling( + data = ebola1976, + delay_density = function(x) density(onset_to_death_ebola, x) +) +``` + +Avec la fonction `utils::tail()` nous pouvons monter les dernières estimations du RL. On voit que les intervalles de confiance à 95% des valeurs naïves et corrigées se chevauchent. + +```{r, eval=FALSE, echo=TRUE} +# voir un aperçu des dernieres valeurs du RL +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 des estimations naïves et ajustées au délai en temps réel ? + +```{r, echo=TRUE, warning=FALSE, message=FALSE} +# concatener les deux resultats +dplyr::bind_rows( + list( + naive = rolling_cfr_naive, + adjusted = rolling_cfr_adjusted + ), + .id = "method" +) %>% + # visualiser les valeurs journalieres du RL naif et corrige + 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) + ) +``` + +Les lignes rouges et bleues représentent respectivement le RL journalier ajusté au délai et naïf tout au long de l'épidémie. Les bandes autour d'elles représentent les intervalles de confiance à 95% (IC 95%). + +**Notez** que le calcul du RL ajusté au 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 concernant le temps entre l'apparition des symptômes jusqu'au décès ne sont pas disponibles, comme c'est le cas au début de l'épidémie). Lorsqu'il y a peu ou pas de décès, une hypothèse sur la *distribution des délais* entre l'apparition des symptômes et le décès doit être formulée, 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 SARS survenue à Hong Kong en 2003. + +:::::::::::::::::::::::::::::::::: spoiler + +### Étude de cas : Épidémie de SARS, Hong Kong, 2003 + +Les figures A et B montrent les nombres cumulés de cas et de décès dus au SARS, et la figure C montre les estimations observées (biaisées) du RL en fonction du temps, c'est-à-dire le nombre cumulé de décès par rapport au nombre de cas à l'instant $t$. En raison du délai entre l'apparition des symptômes et le décès, l'estimation biaisée du RL au temps $t$ est inférieure au RL obtenu à la fin de l'épidémie (302/1755 = 17,2 %). + +![Risque observé (biaisé) de létalité des cas confirmés du syndrome respiratoire aigu sévère (SARS) à Hong Kong, 2003. ([Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852))](../../../episodes/fig/cfr-pone.0006852.g003-fig_abc.png) + +Néanmoins, même en n'utilisant que les données observées sur la période du 19 mars au 2 avril, `cfr::cfr_static()` peut produire une prédiction appropriée (figure D), par exemple le RL ajusté au délai au 27 mars est de 18,1% (IC 95% : 10,5 - 28,1). Une surestimation est notée au tout début de l'épidémie, mais les limites de l'intervalle de confiance à 95% pour les phases ultérieures incluent le RL réel (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 (SARS) à Hong Kong, 2003. ([Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852))](../../../episodes/fig/cfr-pone.0006852.g003-fig_d.png) + +:::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::: discussion + +### Interpréter l'estimation du RL au début de l'épidémie + +Sur la base de la figure ci-dessus : + +- Quelle est la différence, en jours, entre la date à laquelle l'IC à 95% du *RL ajusté aux délais* et du *RL naïf* se croisent avec le RL estimé à la fin de l'épidémie ? + +Discutez-en : + +- En quoi le fait de disposer d'un RL *ajusté aux délai* peut-il influer sur les stratégies de santé publique ? + +:::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::: hint + +Nous pouvons soit inspecter visuellement ou analyser les tableaux des 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 RL corrigé au délai se rapproche de l'estimation globale du RL à la fin de l'épidémie. + +Ce schéma est-il similaire à celui d'autres épidémies ? Nous vous invitons à utiliser les ensembles de données dans les défis de cet épisode pour le découvrir. + +:::::::::::::::::::::: + +:::::::::::::::::::::: discussion + +### Checklist + +Avec `{cfr}` nous estimons le RL comme la proportion de décès parmi les cas **confirmés**. + +En n'utilisant que les cas **confirmés** 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 le RL estimé est plus élevé que la proportion de décès parmi l'ensemble des personnes infectées. + +:::::::::::::::::::::: + +::::::::::::::::::::::::::: solution + +### Pourquoi les estimations naïves et ajustées aux délais diffèrent-elles ? + +La méthode de la librairie `{cfr}` vise à obtenir un estimateur non biaisé "bien avant" d'observer toute l'évolution de l'épidémie. Pour ce faire, `{cfr}` utilise le facteur de sous-estimation $u_{t}$ pour estimer le RL non biaisé $p_{t}$ à l'aide de la méthode du maximum de vraisemblance, étant donné le *processus d'échantillonnage* défini par [Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852). + +::::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solution + +### Quel est le processus d'échantillonnage ? + +![La population des cas confirmés et le processus d'échantillonnage pour l'estimation du RL non biaisé au cours d'une épidémie selon [Nishiura et al. 2009](https://doi.org/10.1371/journal.pone.0006852.g001)](../../../episodes/fig/cfr-pone.0006852.g001.png) + +Nous connaissons le nombre cumulé de cas confirmés et de décès $C_{t}$ et $D_{t}$ à l'instant $t$ à partir des *données d'incidence agrégées* et souhaitons estimer le RL non biaisé $\pi$ 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 avait 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 permettant d'obtenir l'estimation du maximum de vraisemblance du RL non biaisé $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)}, +$$ + +Ce calcule est réalisé par la fonction interne `?cfr:::estimate_severity()`. + +:::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solution + +### Limitations + +- Le RL ajusté aux délais ne prend pas en charge toutes les sources d'erreur dans les données, telle que la non-détection de toutes les personnes infectées. + +:::::::::::::::::::::::::: + +## Challenges + +:::::::::::::::::::::::::::::::: discussion + +### Autres mesures de sévérité + +Supposons que nous ayons besoin d'évaluer la gravité clinique de l'épidémie dans un contexte autre aue la surveillance épidémiologique, 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 valeurs du numérateur (`cases`) et du dénominateur (`deaths`) pour estimer des mesures plus sévères comme le risque d'infection mortelle (RIM) ou le risque d'hospitalisation mortelle (RHM). Nous pouvons suivre analogie ci-après : + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::: solution + +### Risque de létalité lié à l'infection et à l'hospitalisation + +Si pour le risque de décès (RL) d'un *cas*, nous exigeons : + +- 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 *risque d'infection mortelle (RIM)* nécessite : + +- 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, le *risque d'hospitalisation mortelle* requière : + +- les données d'incidence des cas 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 SARS-CoV-2 et les paramètres d'intérêt. Chaque niveau est supposé être un sous-ensemble du niveau inférieur.](../../../episodes/fig/cfr-s41467-020-19238-2-fig_a.png) + +- sCFR risque de létalité des cas symptomatiques (sRL), +- sCHR risque d'hospitalisation des cas symptomatiques (sRH), +- mCFR risque de létalité des cas médicalement pris en charge (mRL), +- mCHR risque d'hospitalisation d'un cas médicalement pris en charge (mRH), +- HFR risque d'hospitalisation mortelle (RHM). + +![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.](../../../episodes/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 données de cas individuels (linelist) + +Les données d'incidence **agrégées** diffèrent des **linelist** où chaque observation contient des données concernant un cas individuel. + +```{r} +outbreaks::ebola_sierraleone_2014 %>% as_tibble() +``` + +::::::::::::::::: + +:::::::::::::::::::::::::::::::::: challenge + +### Utilisez {incidence2} pour réorganiser vos données + +Utilisez la librairie `{outbreaks}` pour chargez le linelist des cas de MERS issues de l'objet `mers_korea_2015` . + +Réorganisez cet objet linelist de sorte qu'il soit utilisable par les fonctions de la librairie `{cfr}`. + +Estimez le RL ajusté au délai en utilisant la distribution de délai correspondante. + +::::::::::::::::: hint + +**Comment réorganiser les données d'entrée ?** + +Le réorganisation des données d'entrée durant le processus d'analyse des données peut prendre beaucoup de temps. Pour obtenir des *données d'incidence agrégées* prêtes à être analysées nous vous encourageons à utiliser le package `{incidence2}`. + +Tout d'abord, consultez la vignette [Get started](https://www.reconverse.org/incidence2/articles/incidence2.html) de la librairie `{incidence2}` pour savoir comment utiliser l'argument `date_index` lors de la lecture d'un linelist contenant plusieurs colonnes de type . + +Ensuite, référez-vous [au manuel de référence](https://epiverse-trace.github.io/cfr/reference/prepare_data.html) sur la façon d'utiliser la fonction `cfr::prepare_data()` sur les objets de classe . + + + +::::::::::::::::: + +::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +# charger les packages +library(cfr) +library(epiparameter) +library(incidence2) +library(outbreaks) +library(tidyverse) + +# Acceder a la distribution des delais +mers_delay <- epiparameter::epiparameter_db( + disease = "mers", + epi_name = "onset to death", + single_epiparameter = TRUE +) + +# lire le linelist +mers_korea_2015$linelist %>% + as_tibble() %>% + select(starts_with("dt_")) + +# utiliser {incidence2} pour determiner les incidences journalieres +mers_incidence <- mers_korea_2015$linelist %>% + # convertir en objet incidence2 + incidence2::incidence(date_index = c("dt_onset", "dt_death")) %>% + # completer les dates du début a la fin + incidence2::complete_dates() + +# voir un aperçu des donnees d'incidence +mers_incidence + +# Preparer les donnees d'incidence pour utilisation dans {cfr} +mers_incidence %>% + cfr::prepare_data( + cases_variable = "dt_onset", + deaths_variable = "dt_death" + ) + +# Estimer le RL ajuste au delai +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 RL peut varier d'une population à l'autre (par exemple en fonction de l'âge, l'espace géographique, du traitement, etc) ; la quantification de ces hétérogénéités peut aider à mobiliser 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 tableau de données `cfr::covid_data` pour estimer un RL ajusté aux délais, stratifié par pays. + +::::::::::::::::::::::::: hint + +Une façon d'effectuer une *analyse stratifiée* consiste à appliquer un modèle à des données imbriquées. Cette [vignette de la librairie `{tidyr}` vignette](https://tidyr.tidyverse.org/articles/nest.html#nested-data-and-models) vous montre comment appliquer la méthode `dplyr::group_by()` + `tidyr::nest()` aux données de imbriquées, puis `dplyr::mutate()` + `purrr::map()` pour appliquer le modèle. + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +library(cfr) +library(epiparameter) +library(tidyverse) + +covid_data %>% dplyr::glimpse() + +delay_onset_death <- epiparameter::epiparameter_db( + disease = "covid", + epi_name = "onset to death", + single_epiparameter = TRUE +) + +covid_data %>% + dplyr::group_by(country) %>% + tidyr::nest() %>% + dplyr::mutate( + temp = purrr::map( + .x = data, + .f = cfr::cfr_static, + delay_density = function(x) density(delay_onset_death, x) + ) + ) %>% + tidyr::unnest(cols = temp) +``` + +C'est génial ! Vous pouvez maintenant utiliser un code similaire pour stratifier vos analyses en fonction de l'âge, des régions ou autres facteurs utiles. + +Mais comment interpréter le fait qu'on ait une variabilité nationale de la gravité clinique 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 de la grvité clinique. Jetez un coup d'œil à la vignette de `{cfr}` 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 + +La librairie `{cfr}` possède une fonction appelée `cfr_time_varying()` dont la fonctionnalité diffère de celle de `cfr_rolling()`. + +::::::::::::::::: callout + +### Quand doit-on utiliser cfr_rolling() ? + +`cfr::cfr_rolling()` calcule le RL estimé à chaque jour de l'épidémie, vue 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 RL à un stade précoce de l'épidémie et vérifier si l'estimation du RL d'une épidémie 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 doit-on utiliser `cfr_time_varying()` ? + +D'autre part, `cfr::cfr_time_varying()`, utilisée pour calculer le RL mobile (RL par intervalle de temps régulier), aide à comprendre les variations du RL dues à des changements durant l'épidémie, comme par exemple en raison d'un nouveau variant du pathogène ou d'une immunité accrue due à la vaccination. + +Cependant, `cfr_time_varying()` est sensible à l'incertitude de l'échantillonnage. Son résultat est donc sensible à la taille de l'épidémie. Plus le nombre de cas dont on connaitra le pronostique au moment de l'estimation est élevé, plus nous obtiendrons des estimations raisonnables du RL variable par intervalle de temps consécutif. + +Par exemple, avec 100 cas, le taux de létalité estimé aura, grosso modo, un intervalle de confiance de 95% ± 10% de la valeur moyenne (IC binomial). Donc, si le nombre de cas dont on connaitra le pronostique à *un jour donné* est supérieur 100, nous pouvons obtenir des estimations raisonnables du RL mobile. Mais si nous disposons que de >100 cas *sur toute la durée de l'épidémie* nous devrons probablement nous appuyer sur la fonction `cfr_rolling()` qui utilise les données cumulées. + +Nous vous invitons à lire la [vignette sur la fonction `cfr_time_varying()`](https://epiverse-trace.github.io/cfr/articles/estimate_time_varying_severity.html). + +::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utilisez la librairie `{cfr}` pour estimer la gravité clinique + +- Utilisez la fonction `cfr::cfr_static()` pour estimer le RL global à l'aide des plus récentes données disponibles. + +- Utilisez la fonction `cfr::cfr_rolling()` pour obtenir les estimations du RL durant chaque jour de l'épidémie. + +- Utiliser l'argument `delay_density` pour ajuster les valeurs du RL au délai épidémiologique en fonction de la distribution des délais correspondants. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + 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) + +