diff --git a/locale/es/episodes/create-forecast.Rmd b/locale/es/episodes/create-forecast.Rmd new file mode 100644 index 00000000..e5e57e19 --- /dev/null +++ b/locale/es/episodes/create-forecast.Rmd @@ -0,0 +1,565 @@ +--- +title: Crear una previsión a corto plazo +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 + +- ¿Cómo puedo crear previsiones a corto plazo a partir de datos de casos? +- ¿Cómo tengo en cuenta los informes incompletos en las previsiones? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Aprender a hacer previsiones de casos utilizando el paquete R `EpiNow2` +- Aprende a incluir un proceso de observación en la estimación + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Requisitos previos + +- Tutorial completo [Cuantificar la transmisión](../episodes/quantify-transmissibility.md) + +Los alumnos deben familiarizarse con las siguientes dependencias conceptuales antes de trabajar en este tutorial: + +**Estadísticas** Distribuciones de probabilidad, principio del análisis bayesiano. + +**Teoría epidémica** Número de reproducción efectiva. + +::::::::::::::::::::::::::::::::: + +## Introducción + +Dados los datos de casos de una epidemia, podemos crear estimaciones del número actual y futuro de casos teniendo en cuenta tanto los retrasos +en la notificación y la infranotificación. Para hacer afirmaciones sobre el futuro de la epidemia, tenemos que hacer una suposición sobre cómo +las observaciones hasta el presente están relacionadas con lo que esperamos que ocurra en el futuro. La forma más sencilla de hacerlo es suponer que "no hay cambios", es decir, que el número de reproducciones sigue siendo el mismo en el futuro que el último observado. En este tutorial crearemos [previsiones](../learners/reference.md#forecast) suponiendo que el número de reproducción seguirá siendo el mismo que el estimado en la última fecha para la que se disponía de datos. + +En este tutorial vamos a aprender a utilizar la función `{EpiNow2}` para prever los casos teniendo en cuenta las observaciones incompletas y prever las observaciones secundarias, como las defunciones. + +Utilizaremos la tubería `%>%` para conectar funciones, así que vamos a llamar también a la función `{tidyverse}` paquete: + +```r +library(EpiNow2) +library(tidyverse) +``` + +```{r, echo=FALSE, eval=TRUE, message=FALSE, warning=FALSE} +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### El doble punto + +El doble punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza `filter()` del `{dplyr}` paquete. + +Esto nos ayuda a recordar las funciones del paquete y a evitar conflictos de espacio de nombres. + +::::::::::::::::::: + +## Crear una previsión a corto plazo + +La función `epinow()` descrita en el [cuantificación de la transmisión](../episodes/quantify-transmissibility.md) es una envoltura de las funciones: + +- `estimate_infections()` utilizadas para estimar los casos por fecha de infección. +- `forecast_infections()` Se utiliza para simular infecciones utilizando un ajuste existente (estimación) a los casos observados. + +Utilicemos el mismo código utilizado en [cuantificar la transmisi](../episodes/quantify-transmissibility.md) para obtener los datos de entrada, los retardos y las priors: + +```{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) + +# 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 dalay +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 = base::list(mean = 2, sd = 2)) +``` + +Ahora podemos extraer la previsión a corto plazo utilizando: + +```{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 + +### ¡No esperes a que se complete! + +Esta última parte puede tardar 10 minutos en ejecutarse. Sigue leyendo este episodio del tutorial mientras esto se ejecuta en segundo plano. Para más información sobre el tiempo de computación, lee la sección "Inferencia Bayesiana con Stan" dentro del tutorial [cuantificar la transmisi](../episodes/quantify-transmissibility.md) de la transmisión. + +::::::::::::::::::::::::::::::::: + +Podemos visualizar las estimaciones del número de reproducciones efectivas y del número estimado de casos utilizando `plot()`. Las estimaciones se dividen en tres categorías: + +- **Estimación** (verde): utiliza todos los datos, + +- **Estimación basada en datos parciales** (naranja): contiene un mayor grado de incertidumbre porque dichas estimaciones se basan en menos datos, + +- **Previsión** (morado): previsiones hacia el futuro. + +```{r} +plot(estimates) +``` + +### Previsión con observaciones incompletas + +En la [cuantificación de la transmisión](../episodes/quantify-transmissibility.md) tuvimos en cuenta los retrasos en la notificación. `EpiNow2` también podemos tener en cuenta las observaciones incompletas, ya que, en realidad, el 100% de los casos no se notifican. +Pasaremos otro argumento a `epinow()` función llamada `obs` para definir un modelo de observación. El formato de `obs` se define mediante la función `obs_opt()` (véase `?EpiNow2::obs_opts` para más detalles). + +Supongamos que creemos que los datos del brote COVID-19 del `cases` objeto no incluyen todos los casos notificados. Creemos que sólo observamos el 40% de los casos. Para especificar esto en el modelo de observación, debemos pasar un factor de escala con una media y una desviación típica. Si suponemos que el 40% de los casos están en los datos de casos (con una desviación típica del 1%), entonces especificamos el factor `scale` de entrada a `obs_opts()` como sigue: + +```{r} +obs_scale <- base::list(mean = 0.4, sd = 0.01) +``` + +Para ejecutar el marco de inferencia con este proceso de observación, añadimos `obs = obs_opts(scale = obs_scale)` a los argumentos de entrada de `epinow()`: + +```{r, message=FALSE, warning=FALSE, eval=TRUE} +# Define observation model +obs_scale <- base::list(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) +``` + +Las estimaciones de las medidas de transmisión, como el número de reproducción efectivo y la tasa de crecimiento, son similares (o tienen el mismo valor) que cuando no tuvimos en cuenta las observaciones incompletas (ver [cuantificar el episodio de trans](../episodes/quantify-transmissibility.md) en la sección "Encontrar estimaciones"). Sin embargo, el número de nuevos casos confirmados por fecha de infección ha cambiado sustancialmente de magnitud para reflejar la suposición de que sólo el 40% de los casos están en el conjunto de datos. + +También podemos cambiar la distribución por defecto de Binomial Negativa a Poisson, eliminar el efecto de semana por defecto y más. Consulta `?EpiNow2::obs_opts` para más detalles. + +::::::::::::::::::::::::::: debate + +### ¿Cuáles son las implicaciones de este cambio? + +- Comparar diferentes porcentajes de observaciones % +- ¿En qué se diferencian en el número de infecciones estimadas? +- ¿Qué implicaciones tiene este cambio para la salud pública? + +::::::::::::::::::::::::::: + +## Previsión de observaciones secundarias + +`EpiNow2` también tiene la capacidad de estimar y pronosticar observaciones secundarias, por ejemplo, muertes y hospitalizaciones, a partir de una observación primaria, por ejemplo, casos. Aquí ilustraremos cómo prever el número de muertes derivadas de los casos observados de COVID-19 en las primeras fases del brote del Reino Unido. + +En primer lugar, debemos formatear nuestros datos para que tengan las siguientes columnas: + +- `date`: la fecha (como objeto de fecha ver `?is.Date()`), +- `primary`: número de observaciones primarias en esa fecha, en este ejemplo **casos**, +- `secondary`: número de observaciones secundarias fecha, en este ejemplo **defunciones**. + +```{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) %>% + # rownames_to_column() %>% + 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 +``` + +Utilizando los datos sobre casos y muertes entre el día 31 y el día 60, estimaremos la relación entre las observaciones primarias y secundarias utilizando `estimate_secondary()` y, a continuación, pronosticaremos las muertes futuras mediante `forecast_secondary()`. Para más detalles sobre el modelo, consulta el [documentación del](https://epiforecasts.io/EpiNow2/dev/articles/estimate_secondary.html). + +Debemos especificar el tipo de observación mediante `type` en `secondary_opts()`, las opciones incluyen: + +- "incidencia": las observaciones secundarias surgen de las observaciones primarias previas, es decir, de las muertes que surgen de los casos registrados. +- "Prevalencia": las observaciones secundarias surgen de una combinación de observaciones primarias actuales y observaciones secundarias anteriores, es decir, el uso de camas hospitalarias que surge de los ingresos hospitalarios actuales y del uso de camas hospitalarias anteriores. + +En este ejemplo especificamos `secondary_opts(type = "incidence")`. Consulta `?EpiNow2::secondary_opts` para más detalles. + +La última entrada clave es la distribución del retraso entre las observaciones primaria y secundaria. Aquí se trata del retraso entre la notificación del caso y la muerte, suponemos que sigue una distribución gamma con una media de 14 días y una desviación típica de 5 días (Alternativamente, podemos utilizar `{epiparameter}` para [acceder a los retrasos epidemiológicos](https://epiverse-trace.github.io/tutorials-early/delays-reuse.html)). Utilizando `Gamma()` especificamos una distribución gamma fija. + +Hay más entradas de función para `estimate_secondary()` que se pueden especificar, incluida la adición de un proceso de observación, véase `?EpiNow2::estimate_secondary` para más detalles sobre estas opciones. + +Encontrar el ajuste del modelo entre casos y muertes: + +```{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 + +### Ten cuidado con la escala de tiempo + +En las primeras fases de un brote puede haber cambios sustanciales en las pruebas y la notificación. Si hay cambios en las pruebas de un mes a otro, habrá un sesgo en el ajuste del modelo. Por tanto, debes tener cuidado con la escala temporal de los datos utilizados en el ajuste y la previsión del modelo. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +Trazamos el ajuste del modelo (cintas sombreadas) con las observaciones secundarias (diagrama de barras) y las observaciones primarias (línea de puntos) de la siguiente manera: + +```{r} +plot(estimate_cases_to_deaths, primary = TRUE) +``` + +Para utilizar este ajuste del modelo para pronosticar las muertes, pasamos un marco de datos consistente en la observación primaria (casos) para las fechas no utilizadas en el ajuste del modelo. + +*Nota : en este episodio estamos utilizando datos en los que conocemos las muertes y los casos, por lo que creamos un marco de datos extrayendo los casos. Pero, en la práctica, se trataría de otro conjunto de datos formado sólo por los casos.* + +```{r} +# Forecast from day 61 to day 90 +cases_to_forecast <- reported_cases_deaths %>% + dplyr::slice(61:90) %>% + dplyr::mutate(value = primary) +``` + +Para pronosticar, utilizamos el ajuste del modelo `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) +``` + +:::::::::::::::: spoiler + +### haz una trama de previsión + +```{r} +deaths_forecast %>% + purrr::pluck("predictions") %>% + ggplot(aes(x = date, y = secondary)) + + geom_col( + fill = "grey", col = "white", + show.legend = FALSE, na.rm = TRUE + ) + + geom_ribbon(aes(ymin = lower_90, ymax = upper_90), + alpha = 0.2, linewidth = 1) + + geom_ribbon(aes(ymin = lower_50, ymax = upper_50), + alpha = 0.4, linewidth = 1) + + geom_ribbon(aes(ymin = lower_20, ymax = upper_20), + alpha = 0.6, linewidth = 1) + + theme_bw() + + labs(y = "Reports per day", x = "Date") + + scale_x_date(date_breaks = "week", date_labels = "%b %d") + + scale_y_continuous(labels = scales::comma) + + theme(axis.text.x = ggplot2::element_text(angle = 90)) +``` + +:::::::::::::::: + +El gráfico muestra la previsión de observaciones secundarias (defunciones) en las fechas para las que hemos registrado casos. +También es posible prever las defunciones mediante la previsión de casos, para lo que debes especificar `primary` como `estimates` salida de `estimate_infections()`. + +:::::::::::::::::::::::::: callout + +### Intervalos creíbles + +En todos `{EpiNow2}` figuras de resultados, las regiones sombreadas reflejan los intervalos de credibilidad del 90%, 50% y 20% en orden de más claro a más oscuro. + +:::::::::::::::::::::::::: + +## Reto: Análisis del brote de ébola + +::::::::::::::::::::::::::::::::::::: challenge + +Descarga el archivo [casos\_ébola.csv](data/ebola_cases.csv) y léelo en R. Los datos simulados consisten en la fecha de aparición de los síntomas y el número de casos confirmados de las primeras fases del brote de ébola en Sierra Leona en 2014. + +Utiliza los 3 primeros meses (120 días) de datos: + +1. Estima si los casos aumentan o disminuyen en el día 120 del brote +2. Contar con una capacidad de observación del 80% de los casos. +3. Crea una previsión de dos semanas del número de casos. + +Puedes utilizar los siguientes valores de parámetro para la distribución o distribuciones del retraso y la distribución del tiempo de generación. + +- Periodo de incubación: Log normal$(2.487,0.330)$ ([Eichner et al. 2011](https://doi.org/10.1016/j.phrp.2011.04.001) a través de `{epiparameter}`) +- Tiempo de generación: Gamma$(15.3, 10.1)$ ([Equipo de respuesta al ébola de la OMS 2014](https://www.nejm.org/doi/full/10.1056/NEJMoa1411100)) + +Puedes incluir cierta incertidumbre en torno a la media y la desviación típica de estas distribuciones. + +::::::::::::::::: pista + +Utilizamos el número de reproducción efectivo y la tasa de crecimiento para estimar si los casos aumentan o disminuyen. + +Podemos utilizar el `horizon` argumento dentro del `epinow()` para ampliar el periodo de tiempo de la previsión. El valor por defecto es de siete días. + +Asegúrate de que los datos tienen el formato correcto : + +- `date`: la fecha (como objeto de fecha ver `?is.Date()`), +- `confirm` número de casos confirmados en esa fecha. + +:::::::::::::::::::::: + +::::::::::::::::: solución + +### SOLUCIÓN + +Para estimar el número efectivo de reproducción y la tasa de crecimiento, utilizaremos la función `epinow()`. + +Como los datos consisten en la fecha de aparición de los síntomas, sólo necesitamos especificar una distribución de retardo para el periodo de incubación y el tiempo de generación. + +Especificamos las distribuciones con cierta incertidumbre en torno a la media y la desviación típica de la distribución log normal para el periodo de incubación y la distribución Gamma para el tiempo de generación. + +```{r, eval=TRUE, echo=TRUE, warning=FALSE, message=FALSE} +epiparameter::epidist_db(disease = "ebola", epi_dist = "incubation") %>% + epiparameter::parameter_tbl() + +ebola_eichner <- epiparameter::epidist_db( + disease = "ebola", + epi_dist = "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 +) +``` + +Leemos los datos de entrada utilizando `readr::read_csv()`. Esta función reconoce que la columna `date` es una `` vector de clase. + +```{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") +) +``` + +Preprocesa y adapta los datos brutos para `{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) +``` + +Definimos un modelo de observación para escalar el número estimado y previsto de nuevas infecciones: + +```{r} +# Define observation model +# mean of 80% and standard deviation of 1% +ebola_obs_scale <- base::list(mean = 0.8, sd = 0.01) +``` + +Como queremos crear también una previsión a dos semanas, especificamos `horizon = 14` para prever 14 días en lugar de los 7 días por defecto. + +```{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) + horizon = 14 +) + +summary(ebola_estimates) +``` + +El número de reproducción efectivo $R_t$ estimado (en la última fecha de los datos) es `r summary(ebola_estimates)[measure=="Effective reproduction no."]$estimate`. La tasa de crecimiento exponencial del número de casos es `r summary(ebola_estimates)[measure=="Rate of growth"]$estimate`. + +Visualiza las estimaciones: + +```{r, eval=FALSE, echo=TRUE} +plot(ebola_estimates) +``` + +::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: callout + +### Previsión con estimaciones de $R_t$ + +Por defecto, las previsiones a corto plazo se crean utilizando la última estimación del número de reproducción $R_t$. Como esta estimación se basa en datos parciales, tiene una incertidumbre considerable. + +El número de reproducciones que se proyecta en el futuro puede cambiarse por una estimación menos reciente basada en más datos utilizando `rt_opts()`: + +```{r, eval=FALSE} +EpiNow2::rt_opts(future = "estimate") +``` + +El resultado serán previsiones menos inciertas (ya que se basan en $R_t$ con un intervalo de incertidumbre más estrecho), pero las previsiones se basarán en estimaciones menos recientes de $R_t$ y supondrán que no ha habido cambios desde entonces. + +Además, existe la opción de [proyectar](../learners/reference.md#projection) el valor de $R_t$ en el futuro utilizando un modelo genérico fijando `future = "project"`. Como esta opción utiliza un modelo para prever el valor de $R_t$ el resultado serán previsiones más inciertas que `estimate` por ejemplo [ver aquí](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections_options.html#projecting-the-reproduction-number-with-the-gaussian-process). + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Resumen + +`EpiNow2` puede utilizarse para crear previsiones a corto plazo y estimar la relación entre distintos resultados. Hay una serie de opciones de modelo que pueden implementarse para diferentes análisis, incluida la adición de un proceso de observación para tener en cuenta los informes incompletos. Consulta la [viñeta](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections_options.html) para más detalles sobre las distintas opciones de modelo en `EpiNow2` que no se tratan en estos tutoriales. + +::::::::::::::::::::::::::::::::::::: keypoints + +- Podemos crear previsiones a corto plazo haciendo suposiciones sobre el comportamiento futuro del número de reproducción +- La notificación incompleta de casos puede tenerse en cuenta en las estimaciones + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/es/episodes/delay-functions.Rmd b/locale/es/episodes/delay-functions.Rmd new file mode 100644 index 00000000..10f07db3 --- /dev/null +++ b/locale/es/episodes/delay-functions.Rmd @@ -0,0 +1,773 @@ +--- +title: 'Utilizar distribuciones de retraso en el análisis' +teaching: 20 +exercises: 10 +editor_options: + chunk_output_type: inline +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- ¿Cómo reutilizar los retrasos almacenados en el paquete `{epiparameter}` con mi flujo de análisis existente? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Utilizar funciones de distribución para distribuciones continuas y discretas almacenadas como objetos ``. +- Convertir una distribución continua en discreta con `{epiparameter}`. +- Conectar las salidas de `{epiparameter}` con entradas de `{EpiNow2}`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Requisitos previos + +- Completar el tutorial [Cuantificar la transmisión](https://epiverse-trace.github.io/tutorials-middle/quantify-transmissibility.html) + +Este episodio requiere que estés familiarizado con: + +**Ciencia de datos** : Programación básica con R. + +**Estadística** : Distribuciones de probabilidad. + +**Teoría epidémica** Parámetros epidemiológicos, periodos de tiempo, número reproductivo efectivo. + +::::::::::::::::::::::::::::::::: + +## Introducción + +`{epiparameter}` nos ayuda a *elegir* un conjunto específico de parámetros epidemiológicos de la bibliografía, en lugar de copiarlos/pegarlos *a mano*: + +```{r, message=FALSE} +covid_serialint <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Nishiura", + single_epidist = TRUE + ) +``` + +¡Ahora tenemos un parámetro epidemiológico que podemos utilizar en nuestro análisis! En el bloque de abajo hemos sustituido uno de los parámetros de **estadísticas de resumen** por `EpiNow2::LogNormal()` + +```r +generation_time <- + EpiNow2::LogNormal( + mean = covid_serialint$summary_stats$mean, # replaced! + sd = covid_serialint$summary_stats$sd, # replaced! + max = 20 + ) +``` + +En este episodio, utilizaremos las **funciones de distribución** que `{epiparameter}` proporciona para obtener un valor máximo (`max`) para este y cualquier otro paquete aguas abajo en tu flujo de análisis. + +Carguemos los paquetes `{epiparameter}` y `{EpiNow2}`. En `{EpiNow2}` estableceremos 4 núcleos para utilizarlos en cálculos paralelos. Utilizaremos el operador *pipe* `%>%`, algunos verbos de `{dplyr}` y `{ggplot2}`, así que llamemos también al paquete `{tidyverse}`: + +```{r, warning=FALSE, message=FALSE} +library(epiparameter) +library(EpiNow2) +library(tidyverse) + +withr::local_options(list(mc.cores = 4)) +``` + +::::::::::::::::::: checklist + +### El doble punto + +El doble punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza `filter()` del paquete `{dplyr}`. + +Esto nos ayuda a recordar las funciones del paquete y a evitar conflictos con los nombres de las funciones. + +::::::::::::::::::: + +## Funciones de distribución + +En R, todas las distribuciones estadísticas tienen funciones para acceder a lo siguiente: + +- `density()`: Función de **densidad** de probabilidad (PDF, por sus siglas en inglés), +- `cdf()`: Función de distribución acumulada (CDF, por sus siglas en inglés), +- `quantile()`: **Cuantil** y +- `generate()`: Generar valores **aleatorios** de la distribución dada. + +:::::::::::: lista de comprobación + +### Funciones para la distribución Normal + +Si lo necesitas, ¡lee en detalle acerca de las [funciones de probabilidad de R para la distribución normal](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc), cada una de sus definiciones e identifica en qué parte de una distribución se encuentran! + +[Las cuatro funciones de probabilidad de la distribución normal ([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 consultas `?stats::Distributions`, cada tipo de distribución tiene un conjunto único de funciones. Sin embargo, ¡`{epiparameter}` te ofrece las mismas cuatro funciones para acceder a cada uno de los valores anteriores para cualquier objeto `` que quieras! + +```{r, eval=FALSE} +# Grafica esto para tener una imagen de referencia +plot(covid_serialint, day_range = 0:20) +``` + +```{r} +# El valor de densidad cuando el cuantil tiene un valor de 10 (días) +density(covid_serialint, at = 10) + +# La probabilidad acumulada cuando el cuantil tiene un valor de 10 (días) +cdf(covid_serialint, q = 10) + +# El valor del cuantil (día) cuando la probabilidad acumulada es 60% +quantile(covid_serialint, p = 0.6) + +# Generar 10 valores aleatorios (días) dada una familia de distribuciones y +# sus parámetros +generate(covid_serialint, times = 10) +``` + +::::::::: instructor + +El acceso a la documentación de referencia (archivos de ayuda) de estas funciones es accesible con la notación de tres dobles puntos: `epiparameter:::` + +- `?epiparameter:::density.epidist()` +- `?epiparameter:::cdf.epidist()` +- `?epiparameter:::quantile.epidist()` +- `?epiparameter:::generate.epidist()` + +:::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Ventana para el rastreo de contactos y el intervalo en serie + +El **intervalo serial** es importante en la optimización del rastreo de contactos, ya que proporciona una ventana temporal para la contención de la propagación de una enfermedad ([Fine, 2003](https://academic.oup.com/aje/article/158/11/1039/162725)). A partir del intervalo serial, podemos evaluar la necesidad de ampliar el número de días previos a tener en cuenta para iniciar el rastreo de contactos e incluir más contactos retrospectivos ([Davis et al., 2020](https://assets.publishing.service.gov.uk/media/61e9ab3f8fa8f50597fb3078/S0523_Oxford_-_Backwards_contact_tracing.pdf)). + +Con el intervalo de serie COVID-19 (`covid_serialint`) calcula: + +- ¿Cuántos más casos atrasados se podrían captar si el método de rastreo de contactos considerara los contactos de hasta 6 días antes del inicio en comparación con los de 2 días antes del inicio? + +::::::::::::::::: hint + +En la Figura 5 de las [funciones de probabilidad de R para la distribución normal](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc), la sección sombreada representa una probabilidad acumulada de `0.997` para el valor del cuantil en `x = 2`. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=FALSE} +plot(covid_serialint) +``` + +```{r, eval=TRUE} +cdf(covid_serialint, q = 2) +cdf(covid_serialint, q = 6) +``` + +Dado el intervalo de serie COVID-19: + +- Un método de rastreo de contactos que considere los contactos hasta 2 días antes del inicio captará alrededor del 11,1% de los casos retrospectivos. + +- Si este periodo se amplía a 6 días antes del inicio, se podría incluir el 76,2% de los contactos retrospectivos. + +:::::::::::::::::::::::::: + +::::::::::::::::: solution + +### ¿Y si + +intercambiamos la pregunta entre días y probabilidad acumulada a: + +- Al considerar los casos secundarios, ¿cuántos días después del inicio de los síntomas de los casos primarios podemos esperar que se produzca un 55% de inicio de los síntomas? + +```{r, eval=FALSE} +quantile(covid_serialint, p = 0.55) +``` + +Una interpretación podría ser + +- El 55% del inicio de los síntomas de los casos secundarios ocurrirá después de 4,2 días del inicio de los síntomas de los casos primarios. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Discretizar una distribución continua + +¡Nos acercamos al final! `EpiNow2::LogNormal()` todavía necesita un valor máximo (`max`). + +Una forma de hacerlo es obtener el valor del cuantil del percentil 99 de la distribución o la probabilidad acumulada de `0.99` . Para ello, necesitamos acceder al conjunto de funciones de distribución de nuestro objeto ``. + +Podemos utilizar el conjunto de funciones de distribución de una distribución *continua* (como arriba). Sin embargo, estos valores serán *continuos*. Podemos **discretizar** la distribución continua almacenada en nuestro objeto `` para obtener valores discretos a partir de una distribución continua. + +Cuando usamos `epiparameter::discretise()` sobre la distribución continua, obtenemos una distribución **discreta** (o discretizada): + +```{r} +covid_serialint_discrete <- + epiparameter::discretise(covid_serialint) + +covid_serialint_discrete +``` + +Identificamos este cambio en la línea de salida `Distribution:` del objeto ``. Comprueba de nuevo esta línea: + +``` +Distribution: discrete lnorm +``` + +Mientras que para una distribución **continua** trazamos la *Función de densidad de probabilidad (PDF)* para una distribución **discreta**, trazamos la *función de masa de probabilidad (PMF)*: + +```{r, eval=FALSE} +# continua +plot(covid_serialint) + +# discreta +plot(covid_serialint_discrete) +``` + +Para obtener finalmente un valor máximo (`max`), accedamos al valor del cuantil del percentil 99 o cuando la probabilidad acumulada es `0.99` usando `prob_dist$q` de forma similar a como accedemos a los valores de **estadísticas de resumen** (`summary_stats`). + +```{r} +covid_serialint_discrete_max <- + quantile(covid_serialint_discrete, p = 0.99) +``` + +::::::::::::::::::::::::::::::::: challenge + +### Duración del periodo de cuarentena e incubación + +El **periodo de incubación** es un retraso útil para evaluar la duración de la vigilancia activa o la cuarentena ([Lauer et al., 2020](https://www.acpjournals.org/doi/10.7326/M20-0504)). Del mismo modo, los retrasos desde la aparición de los síntomas hasta la recuperación (o la muerte) determinarán la duración necesaria de la asistencia sanitaria y el aislamiento del caso ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +Calcula: + +- ¿En qué plazo exacto de tiempo el 99% de las personas que presentan síntomas de COVID-19 después de la infección los presentan? + +::::::::::::::::: hint + +¿Qué distribución del retraso mide el tiempo entre la infección y la aparición de los síntomas? + +¡Las funciones de probabilidad **discretas** para `` son las mismas que utilizamos para las *continuas*! + +```{r, eval=FALSE} +# Grafica esto para tener una imagen de referencia +plot(covid_serialint_discrete, day_range = 0:20) + +# El valor de la densidad cuando el cuantil tiene un valor de 10 (días) +density(covid_serialint_discrete, at = 10) + +# La probabilidad acumulada cuando el cuantil tiene un valor de 10 (días) +cdf(covid_serialint_discrete, q = 10) + +# El valor del cuantil (días) cuando la probabilidad acumulada es 60% +quantile(covid_serialint_discrete, p = 0.6) + +# Generar valores aleatorios +generate(covid_serialint_discrete, times = 10) +``` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE} +covid_incubation <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "incubation", + single_epidist = TRUE + ) + +covid_incubation_discrete <- epiparameter::discretise(covid_incubation) + +quantile(covid_incubation_discrete, p = 0.99) +``` + +El 99% de los que desarrollan síntomas de COVID-19 lo harán en los 16 días posteriores a la infección. + +Ahora, *¿es esperable este resultado en términos epidemiológicos?* + +:::::::::::::::::::::::::: + +::::::::::::::::: solution + +### ¿Cómo crear un gráfico de distribución? + +A partir de un valor máximo con `quantile()` podemos crear una secuencia de valores de cuantiles como un vector numérico y calcular `density()` para cada uno: + +```{r, eval=TRUE} +# Crear la visualización para una distribución discreta +# a partir de un valor máximo de la distribución +quantile(covid_serialint_discrete, p = 0.99) %>% + # Generar un vector de cuantiles + # como una secuencia para cada número natural + seq(1L, to = ., by = 1L) %>% + # Convertir el vector numérico en un data.frame (tibble) + as_tibble_col(column_name = "quantile_values") %>% + mutate( + # Calcular los valores de densidad + # para cada cuantul en la función de densidad + density_values = + density( + x = covid_serialint_discrete, + at = quantile_values + ) + ) %>% + # Graficar + ggplot( + aes( + x = quantile_values, + y = density_values + ) + ) + + geom_col() +``` + +**Recuerda:** En las infecciones con transmisión presintomática, los intervalos seriales pueden tener valores negativos ([Nishiura et al., 2020](https://www.ijidonline.com/article/S1201-9712\(20\)30119-3/fulltext)). ¡Cuando utilizamos el *intervalo serial* para aproximar el *tiempo de generación* necesitamos hacer esta distribución sólo con valores positivos! + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Plug-in `{epiparameter}` a `{EpiNow2}` + +¡Ahora podemos introducirlo todo en la función `EpiNow2::LogNormal()`! + +- Las **estadísticas de resumen**: media (`mean`) y desviación estándar (`sd`) de la distribución, +- un valor máximo (`max`), +- el nombre de la distribución (`distribution`). + +Cuando utilices `EpiNow2::LogNormal()` para definir una distribución **log normal** como la del intervalo serial del COVID-19 (`covid_serialint`) podemos especificar la media (`mean`) y la desviación estándar (`sd`) como parámetros. Alternativamente, para obtener los parámetros "naturales" de una distribución log normal podemos convertir sus estadísticos de resumen en parámetros de distribución denominados `meanlog` y `sdlog`. Con `{epiparameter}` podemos obtener directamente los *parámetros de la distribución* utilizando `epiparameter::get_parameters()`: + +```{r} +covid_serialint_parameters <- + epiparameter::get_parameters(covid_serialint) +``` + +Entonces, tenemos: + +```{r} +serial_interval_covid <- + EpiNow2::LogNormal( + meanlog = covid_serialint_parameters["meanlog"], + sdlog = covid_serialint_parameters["sdlog"], + max = covid_serialint_discrete_max + ) + +serial_interval_covid +``` + +Suponiendo un escenario con COVID-19, utilicemos los primeros 60 días del conjunto de datos `example_confirmed` del paquete `{EpiNow2}` como casos reportados(`reported_cases`) y el recientemente creado intervalo serial COVID (`serial_interval_covid`) como entradas para estimar el número reproductivo variable en el tiempo utilizando `EpiNow2::epinow()`. + +```{r, message=FALSE} +epinow_estimates_cg <- epinow( + # casos + data = example_confirmed[1:60], + # retrasos + generation_time = generation_time_opts(serial_interval_covid) +) + +base::plot(epinow_estimates_cg) +``` + +`plot()` incluye los casos estimados por fecha de infección, que se reconstruyen a partir de los casos notificados y los retrasos. + +:::::::::: callout + +### Advertencia + +Utilizar el intervalo serial en lugar del tiempo de generación es una alternativa que puede propagar sesgos en tus estimaciones, más aún en enfermedades con transmisión presintomática reportada. ([Chung Lau et al., 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)) + +:::::::::::::::::: + +## Ajuste por retrasos en la notificación + +Estimar $R_t$ requiere datos sobre el número diario de nuevas infecciones. Debido a los retrasos en el desarrollo de cargas víricas detectables, la aparición de síntomas, la búsqueda de atención sanitaria y la notificación, estas cifras no están fácilmente disponibles. Todas las observaciones reflejan eventos de transmisión de algún momento del pasado. En otras palabras, si $d$ es el tiempo transcurrido desde la infección hasta la observación, las observaciones en el momento $t$ informan a $R_{t−d}$ no $R_t$. [(Gostic et al., 2020)](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409#sec007) + +![**Calendario de notificación de la cadena de enfermedades, Países Bajos.** Lab, laboratorio; PHA, autoridad sanitaria pública. En [Marinović y otros, 2015](https://wwwnc.cdc.gov/eid/article/21/2/13-0504_article)](fig/disease-reporting.jpg) + +La **distribución del retraso** podría inferirse conjuntamente con los tiempos de infección subyacentes o estimarse como la suma del [periodo de incubación](../learners/reference.md#incubation) y la distribución de los retrasos desde el inicio de los síntomas hasta la observación a partir de los datos ([retraso en la notificación](../learners/reference.md#reportingdelay)). En `{EpiNow2}` podemos especificar estas dos distribuciones de retraso complementarias con el argumento `delays`. + +![**$R_{t}$ es una medida de la transmisión en el momento $t$.** Observaciones después del tiempo $t$ deben ajustarse. UCI, unidad de cuidados intensivos. En [Gostic et al., 2020](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409#sec007)](fig/rt-adjusting-delays.png) + +::::::::::::::::::::::::::::::::: challenge + +### Utiliza un periodo de incubación de COVID-19 para estimar Rt + +Estima el número reproductivo variable en el tiempo para los primeros 60 días del conjunto de datos `example_confirmed ` de `{EpiNow2}`. Accede a un periodo de incubación para COVID-19 a partir de `{epiparameter}` para utilizarlo como retraso de notificación. + +::::::::::::::::: sugerencia + +Utiliza el último cálculo de `epinow()` usando el argumento `delays` y la función auxiliar `delay_opts()`. + +El argumento `delays` y la función auxiliar `delay_opts()` son análogos al argumento `generation_time` y la función auxiliar `generation_time_opts()`. + +```r +epinow_estimates <- epinow( + # casos + reported_cases = example_confirmed[1:60], + # retrasos + generation_time = generation_time_opts(covid_serial_interval), + delays = delay_opts(covid_incubation_time) +) +``` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE, message=FALSE} + +# Tiempo de generación --------------------------------------------------------- + +# Intervalo serial covid +covid_serialint <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Nishiura", + single_epidist = TRUE + ) + +# adaptar epidist para 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 + ) + +# Periodo de incubación ------------------------------------------------------- + +# Periodo de incubación +covid_incubation <- epiparameter::epidist_db( + disease = "covid", + epi_dist = "incubation", + author = "Natalie", + single_epidist = TRUE +) + +# Adaptar epiparameter para 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 ------------------------------------------------------------------ + +# usar epinow +epinow_estimates_cgi <- epinow( + # casos + data = example_confirmed[1:60], + # retrasos + generation_time = generation_time_opts(covid_serial_interval), + delays = delay_opts(covid_incubation_time) +) + +base::plot(epinow_estimates_cgi) +``` + +Intenta complementar el argumento `delays` con un retraso de notificación como el objeto `reporting_delay_fixed` del episodio anterior. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::: discussion + +### ¿Cuánto ha cambiado? + +Tras añadir el periodo de incubación, debata acerca de: + +- ¿Cambia la tendencia del ajuste del modelo en la sección estimación ("Estimate")? +- ¿Ha cambiado la incertidumbre? +- ¿Cómo explicaría o interpretaría estos cambios? + +Compara todas las figuras generadas con `{EpiNow2}` anteriormente. + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +## Desafíos + +:::::::::::::::::::::::::::::: callout + +### Un consejo para completar código + +Si escribimos el `[ ]` luego del objeto `covid_serialint_parameters[ ]`, dentro de `[ ]` podemos utilizar el la tecla Tab en el teclado +para usar la [función de completado de código](https://support.posit.co/hc/en-us/articles/205273297-Code-Completion-in-the-RStudio-IDE) + +Usar esto permite acceder rápidamente a `covid_serialint_parameters["meanlog"]` y `covid_serialint_parameters["sdlog"]`. + +¡Te invitamos a probarlo en otros bloques de código y en la consola de R! + +:::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Número de reproducción efectiva del ébola ajustado por retrasos en la notificación + +Descarga y lee el [conjunto de datos de ébola](data/ebola_cases.csv): + +- Estime el número reproductivo efectivo utilizando `{EpiNow2}` +- Ajuste la estimación según los retrasos de notificación disponibles en `{epiparameter}` +- ¿Por qué eligió ese parámetro? + +::::::::::::::::: pista + +Para calcular el $R_t$ utilizando `{EpiNow2}` necesitamos + +- Los datos de incidencia agregada con los casos confirmados por día, y +- La distribución del tiempo de generación. +- Opcionalmente, informar las distribuciones de retrasos cuando estén disponibles (por ejemplo, el periodo de incubación). + +Para obtener las distribuciones de retrasos utilizando `{epiparameter}` podemos utilizar funciones como: + +- `epiparameter::epidist_db()` +- `epiparameter::parameter_tbl()` +- `discretise()` +- `quantile()` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE, echo=FALSE, message=FALSE} +# Leer datos del repositorio del proyecto en R +ebola_confirmed <- + read_csv(file.path("data", "ebola_cases.csv")) +``` + +```{r, eval=FALSE, echo=TRUE} +# Leer datos +# e.j.: Si la ruta al archivo es data/raw-data/ebola_cases.csv entonces: +ebola_confirmed <- + read_csv(here::here("data", "raw-data", "ebola_cases.csv")) + +# Listar las distribuciones +epiparameter::epidist_db(disease = "ebola") %>% + epiparameter::parameter_tbl() +``` + +```{r, message=FALSE, eval=TRUE} + +# Tiempo de generación --------------------------------------------------------- + +# Filtrar una distribución para el tiempo de generación +ebola_serial <- epiparameter::epidist_db( + disease = "ebola", + epi_dist = "serial", + single_epidist = TRUE +) + +# adaptar epiparameter para 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) + ) + +# Tiempo de incubación ------------------------------------------------------- + +# Filtrar una distribución para el retraso del periodo de incubación +ebola_incubation <- epiparameter::epidist_db( + disease = "ebola", + epi_dist = "incubation", + single_epidist = TRUE +) + +# adaptar epiparameter para 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 ------------------------------------------------------------------ + +# Usar epinow +epinow_estimates_egi <- epinow( + # casos + data = ebola_confirmed, + # retrasos + generation_time = generation_time_opts(serial_interval_ebola), + delays = delay_opts(incubation_period_ebola) +) + +plot(epinow_estimates_egi) +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### ¿Qué hacer con las distribuciones de Weibull? + +Utiliza el conjunto de datos `influenza_england_1978_school` del paquete `{outbreaks}` para calcular el número reproductivo efectivo mediante `{EpiNow2}`, ajustando por los retrasos de notificación disponibles en `{epiparameter}`. + +::::::::::::::::: sugerencia + +`EpiNow2::NonParametric()` acepta Funciones de Masa de Probabilidad (PMF) de cualquier familia de distribuciones. Lee la guía de referencia sobre [Distribuciones de probabilidad](https://epiforecasts.io/EpiNow2/reference/Distributions.html). + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, message=FALSE, eval=TRUE} +# ¿Qué parámetros hay disponibles para Influenza? +epiparameter::epidist_db(disease = "influenza") %>% + epiparameter::parameter_tbl() %>% + count(epi_distribution) + +# Tiempo de generación ------------------------------------------------------- + +# Leer tiempo de generación +influenza_generation <- + epiparameter::epidist_db( + disease = "influenza", + epi_dist = "generation" + ) + +influenza_generation + +# EpiNow2 permite usar distribuciones Gamma o LogNormal +# Se puede introducir una PMF + +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 = 1:influenza_generation_max + ) + +influenza_generation_pmf + +# EpiNow2::NonParametric() también puede recibir valores de PMF +generation_time_influenza <- + EpiNow2::NonParametric( + pmf = influenza_generation_pmf + ) + +# Periodo de incubación ------------------------------------------------------- + +# Leer el periodo de incubación +influenza_incubation <- + epiparameter::epidist_db( + disease = "influenza", + epi_dist = "incubation", + single_epidist = TRUE + ) + +# Discretizar el periodo de incubación +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 = 1:influenza_incubation_max + ) + +influenza_incubation_pmf + +# EpiNow2::NonParametric() también puede recibit valores de PMF +incubation_time_influenza <- + EpiNow2::NonParametric( + pmf = influenza_incubation_pmf + ) + +# epinow ------------------------------------------------------------------ + +# Leer datos +influenza_cleaned <- + outbreaks::influenza_england_1978_school %>% + select(date, confirm = in_bed) + +# Usar epinow +epinow_estimates_igi <- epinow( + # casos + data = influenza_cleaned, + # retrasos + generation_time = generation_time_opts(generation_time_influenza), + delays = delay_opts(incubation_time_influenza) +) + +plot(epinow_estimates_igi) +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Próximos pasos + +::::::::::::::::: testimonial + +### ¿Cómo obtener parámetros de distribución a partir de distribuciones estadísticas? + +¿Cómo obtener la media y la desviación típica de un tiempo de generación con *sólo* parámetros de distribución pero sin estadísticas de resumen como `mean` o `sd` para `EpiNow2::Gamma()` o `EpiNow2::LogNormal()`? + +¡Mira en `{epiparameter}` la viñeta [extracción y conversión de parámetros](https://epiverse-trace.github.io/epiparameter/articles/extract_convert.html) y sus [casos de uso](https://epiverse-trace.github.io/epiparameter/articles/extract_convert.html#use-cases) ! + +::::::::::::::::::::::::::::: + +::::::::::::::::: testimonial + +### ¿Cómo estimar las distribuciones de retraso de la Enfermedad X? + +Consulta este excelente tutorial sobre la estimación del intervalo serial y el período de incubación de la Enfermedad X, teniendo en cuenta *la censura* por medio de inferencia bayesiana con paquetes como `{rstan}` y `{coarseDataTools}`. + +- Tutorial en Inglés: +- Tutorial en Español: + +**Luego,** después de obtener tus valores estimados, ¡puedes crear manualmente tus propios objetos con clase ` ` por medio de `epiparameter::epidist()`! Echa un vistazo a su [guía de referencia sobre "Crear un objeto `` "](https://epiverse-trace.github.io/epiparameter/reference/epidist.html#ref-examples) ¡! + +Por último, echa un vistazo al último [paquete de R `{epidist}`](https://epidist.epinowcast.org/) que proporciona métodos para abordar los principales retos de la estimación de distribuciones, como el truncamiento, la censura por intervalos y los sesgos dinámicos. + +::::::::::::::::::::::::::::: + + + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utilizar funciones de distribución con `` para obtener estadísticas de resumen y parámetros informativos de las intervenciones de salud pública, como la Ventana de rastreo de contactos y la Duración de la cuarentena. +- Utilizar `discretise()` para convertir distribuciones de retraso continuas en discretas. +- Utilizar `{epiparameter}` para obtener los retrasos de información necesarios en las estimaciones de transmisibilidad. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/es/episodes/delays-access.Rmd b/locale/es/episodes/delays-access.Rmd new file mode 100644 index 00000000..7da516c7 --- /dev/null +++ b/locale/es/episodes/delays-access.Rmd @@ -0,0 +1,632 @@ +--- +title: 'Acceder a las distribuciones de retrasos epidemiológicos' +teaching: 20 +exercises: 10 +editor_options: + chunk_output_type: inline +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- ¿Cómo acceder a las distribuciones de retraso de la enfermedad desde una base de datos preestablecida para su uso en el análisis? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Obtener retrasos de una base de datos de búsqueda bibliográfica con `{epiparameter}`. +- Obtén parámetros de distribución y estadísticas resumidas de distribuciones de retrasos. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Requisitos previos + +Este episodio requiere que estés familiarizado con + +**Ciencia de datos** Programación básica con R + +**Teoría epidémica** : Pparámetros epidemiológicos, periodos de tiempo de la enfermedad, como el periodo de incubación, el tiempo de generación y el intervalo serial. + +::::::::::::::::::::::::::::::::: + +## Introducción + +Las enfermedades infecciosas siguen un ciclo de infección, que generalmente incluye las siguientes fases: periodo presintomático, periodo sintomático y periodo de recuperación, tal y como se describe en su [historia natural](../learners/reference.md#naturalhistory). Estos periodos de tiempo pueden utilizarse para comprender la dinámica de transmisión e informar sobre las intervenciones de prevención y control de enfermedades. + +![Definición de los periodos de tiempo clave. En [Xiang et al, 2021](https://www.sciencedirect.com/science/article/pii/S2468042721000038)](fig/time-periods.jpg) + +::::::::::::::::: callout + +### Definiciones + +Mira el [glosario](../learners/reference.md) ¡para ver las definiciones de todos los periodos de tiempo de la figura anterior! + +::::::::::::::::::::::::: + +Sin embargo, al inicio de una epidemia, los esfuerzos de modelamiento pueden verse retrasados por la falta de un recurso centralizado que resuma los parámetros de entrada para la enfermedad de interés ([Nash et al., 2023](https://mrc-ide.github.io/epireview/)). Proyectos como `{epiparameter}` y `{epireview}` están construyendo catálogos en línea siguiendo protocolos de síntesis de literatura que pueden ayudar a parametrizar modelos accediendo fácilmente a una extensa biblioteca de parámetros epidemiológicos previamente estimados de brotes pasados. + + + +Para ejemplificar cómo utilizar el `{epiparameter}` R en tu canal de análisis, nuestro objetivo en este episodio será acceder a un conjunto específico de parámetros epidemiológicos de la literatura, en lugar de copiarlos y pegarlos manualmente, para integrarlos en un flujo de trabajo de análisis con `{EpiNow2}` + + + +Empecemos cargando el paquete `{epiparameter}`. Utilizaremos la tubería `%>%` para conectar algunas de sus funciones, algunas funciones de`{tibble}` y `{dplyr}`, así que llamaremos también al paquete`{tidyverse}`: + +```{r, warning=FALSE, message=FALSE} +library(epiparameter) +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### El doble punto + +El doble punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza `filter()` del paquete`{dplyr}`. + +Esto nos ayuda a recordar las funciones del paquete y a evitar conflictos de espacio de nombres. + +::::::::::::::::::: + +## El problema + +Si queremos estimar la transmisibilidad de una infección, es común utilizar un paquete como `{EpiEstim}` o `{EpiNow2}`. Sin embargo, ambos requieren cierta información epidemiológica como entrada. Por ejemplo, en `{EpiNow2}` utilizamos `EpiNow2::Gamma()` para especificar un [tiempo de generación](../learners/reference.md#generationtime) como una distribución de probabilidad añadiendo su media `mean` desviación estándar (`sd`) y el valor máximo (`max`). + +Para especificar un tiempo de generación `generation_time` que sigue a un *Gamma* con media $\mu = 4$ y desviación estándar $\sigma = 2$ y un valor máximo de 20, escribimos + +```r +generation_time <- + EpiNow2::Gamma( + mean = 4, + sd = 2, + max = 20 + ) +``` + +Es una práctica común para analistas, buscar manualmente en la literatura disponible y copiar y pegar el **resumen estadístico** o los **parámetros de distribución** de las publicaciones científicas. Un reto frecuente al que nos enfrentamos a menudo es que la información sobre las distintas distribuciones estadísticas no es coherente en toda la literatura. El objetivo de `{epiparameter}` es facilitar el acceso a estimaciones confiables de los parámetros de distribución para una serie de enfermedades infecciosas, de modo que puedan implementarse fácilmente en las líneas de análisis de brotes. + +En este episodio *acceder a* a las estadísticas resumidas del tiempo de generación de COVID-19 desde la biblioteca de parámetros epidemiológicos proporcionada por `{epiparameter}`. Estos parámetros pueden utilizarse para estimar la transmisibilidad de esta enfermedad utilizando `{EpiNow2}` en episodios posteriores. + +Empecemos por ver cuántas entradas hay disponibles en el **base de datos de distribuciones epidemiológicas** en `{epiparameter}` utilizando `epidist_db()` para la distribución epidemiológica `epi_dist` llamada tiempo de generación con la cadena `"generation"`: + +```{r} +epiparameter::epidist_db( + epi_dist = "generation" +) +``` + +Actualmente, en la biblioteca de parámetros epidemiológicos, tenemos una entrada de tiempo generación `"generation"` para Influenza. En su lugar, podemos consultar intervalos seriales `"serial"` para `COVID`\-19. ¡Veamos qué debemos tener en cuenta para ello! + +## Tiempo de generación vs intervalo serial + +El tiempo de generación, junto con el número reproductivo ($R$), proporcionan información valiosa sobre la fuerza de transmisión e informan la implementación de medidas de control. Dado un $R>1$, cuanto más corto sea el tiempo de generación, más rápidamente aumentará la incidencia de casos de enfermedad. + +![Vídeo del Centro MRC para el Análisis Global de las Enfermedades Infecciosas, Ep 76. Ciencia en Contexto - Grupo de Revisión de Parámetros Epi con la Dra. Anne Cori (27-07-2023) en ](fig/reproduction-generation-time.png) + +Al calcular el número de reproducción efectivo ($R_{t}$), el *tiempo de generación* suele aproximarse mediante el [intervalo serial](../learners/reference.md#serialinterval) serial. +Esta aproximación frecuente se debe a que es más fácil observar y medir el inicio de los síntomas que el inicio de la infección. + +![ Un Esquema de la relación de los distintos periodos de tiempo de transmisión entre un infector y un infectado en un par de transmisión. La ventana de exposición se define como el intervalo de tiempo que tiene la exposición viral, y la ventana de transmisión se define como el intervalo de tiempo para la transmisión posterior con respecto al tiempo de infección ([Chung Lau et al., 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)).](fig/serial-interval-observed.jpeg) + +Sin embargo, usar el*intervalo serial* como una aproximación del *tiempo de generación* es válido principalmente para las enfermedades en las que la infecciosidad comienza después de la aparición de los síntomas ([Chung Lau et al., 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)). En los casos en que la infecciosidad comienza antes de la aparición de los síntomas, los intervalos seriales pueden tener valores negativos, como ocurre en las enfermedades con transmisión presintomática ([Nishiura et al., 2020](https://www.ijidonline.com/article/S1201-9712\(20\)30119-3/fulltext#gr2)). + +::::::::::::::::: callout + +### De los periodos de tiempo a las distribuciones de probabilidad. + +Cuando calculamos el *intervalo serial* vemos que no todos los pares de casos tienen la misma duración temporal. Observaremos esta variabilidad para cualquier par de casos y periodo de tiempo individual, incluido el [periodo de incubación](../learners/reference.md#incubation) y [periodo infeccioso](../learners/reference.md#infectiousness). + +![Intervalos seriales de posibles parejas de casos en (a) COVID-19 y (b) MERS-CoV. Los pares representan un supuesto infector y su presunto infectado trazados por fecha de inicio de los síntomas ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#fig6)).](fig/serial-interval-pairs.jpg) + +Para resumir estos datos de periodos de tiempo individuales y de pares, podemos encontrar las **distribuciones estadísticas** que mejor se ajusten a los datos ([McFarland et al., 2023](https://www.eurosurveillance.org/content/10.2807/1560-7917.ES.2023.28.27.2200806)). + + + +![Distribución ajustada del intervalo serial para (a) COVID-19 y (b) MERS-CoV basada en pares de transmisión notificados en Arabia Saudí. Ajustamos tres distribuciones comunmente usadas, Log normal, Gamma y Weibull, respectivamente ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#fig5)).](fig/seria-interval-fitted-distributions.jpg) + +Las distribuciones estadísticas se resumen en función de sus **estadísticas de resumen** como la *ubicación* (media y percentiles) y *dispersión* (varianza o desviación estándar) de la distribución, o con su **parámetros de distribución** que informan sobre la *forma* (forma y tasa/escala) de la distribución. Estos valores estimados pueden reportarse con su **incertidumbre** (intervalos de confianza del 95%). + +| Gamma | media | forma | velocidad/escala | +| :--------- | :--------------- | :-------------- | :--------------- | +| 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 | media | forma | velocidad/escala | +| :--------- | :--------------- | :-------------- | :--------------- | +| 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 | media | media-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) | + +Tabla: Estimaciones del intervalo serial utilizando las distribuciones Gamma, Weibull y Log Normal. Los intervalos de confianza del 95% para los parámetros de forma y escala (logmedia y sd para Log Normal) se muestran entre paréntesis ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#tbl3)). + +::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Intervalo serial + +Supongamos que COVID-19 y SARS tienen valores similares de número de reproducción y que el intervalo serial se aproxima al tiempo de generación. + +Dado el intervalo serial de ambas infecciones en la siguiente gráfica + +- ¿Cuál sería más difícil de controlar? +- ¿Por qué llegas a esa conclusión? + +![El Intervalo serial de nuevas infecciones por coronavirus (COVID-19) superpuesto a una distribución publicada del SRAS. ([Nishiura et al., 2020](https://www.ijidonline.com/article/S1201-9712\(20\)30119-3/fulltext))](fig/serial-interval-covid-sars.jpg) + +::::::::::::::::: hint + +El pico de cada curva puede informarte sobre la ubicación de la media de cada distribución. Cuanto mayor sea la media, mayor será el intervalo serial. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +**¿Cuál sería más difícil de controlar?** + +COVID-19 + +**¿Por qué concluyes eso?** + +COVID-19 tiene el intervalo serial promedioo más bajo. El valor promedio aproximado del intervalo serial de COVID-19 es de unos cuatro días, mientras que del SARS es de aproximadamentesiete días. Por lo tanto, es probable que COVID-19 tenga nuevas generaciones en menos tiempo que el SARS, asumiendo valores de número de reproducción similares. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::: instructor + +El objetivo de la evaluación anterior es valorar la interpretación de un tiempo de generación mayor o menor. + +:::::::::::::::::::::: + +## Elección de parámetros epidemiológicos + +En esta sección, utilizaremos `{epiparameter}` para obtener el intervalo serial de COVID-19, como una alternativa al tiempo de generación. + +Preguntémonos ahora cuántos parámetros tenemos en la base de datos de distribuciones epidemiológicas (`epidist_db()`) con la enfermedad`disease` denominada `covid`\-19. ¡Ejecútalo localmente! + +```{r, eval=FALSE} +epiparameter::epidist_db( + disease = "covid" +) +``` + +Desde el paquete `{epiparameter}` podemos utilizar la función `epidist_db()` para consultar cualquier enfermedad `disease` y también para una distribución epidemiológica concreta (`epi_dist`). Ejecútalo en tu consola: + +```{r, eval=FALSE} +epiparameter::epidist_db( + disease = "COVID", + epi_dist = "serial" +) +``` + +Con esta combinación de consultas, obtenemos más de una distribución de retraso. Esta salida es un `` objeto de clase. + +::::::::::::::::: callout + +### INSENSIBLE A MAYÚSCULAS Y MINÚSCULAS + +`epidist_db` es [insensible a mayúsculas y minúsculas](https://dillionmegida.com/p/case-sensitivity-vs-case-insensitivity/#case-insensitivity). Esto significa que puedes utilizar cadenas con letras en mayúsculas o minúsculas indistintamente. Cadenas como `"serial"`, `"serial interval"` o `"serial_interval"` también son válidos. + +::::::::::::::::::::::::: + +Como se sugiere en los resultados, para resumir una `` y obtener los nombres de las columnas de la base de datos de parámetros subyacente, podemos añadir la función `epiparameter::parameter_tbl()` al código anterior utilizando la tubería `%>%`: + +```{r} +epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial" +) %>% + epiparameter::parameter_tbl() +``` + +En el `epiparameter::parameter_tbl()` salida, también podemos encontrar distintos tipos de distribuciones de probabilidad (por ejemplo, Log-normal, Weibull, Normal). + +`{epiparameter}` utiliza la `base` R para las distribuciones. Por eso **Normal logarítmica** se llama `lnorm`. + +::::::::::::::::: spoiler + +### ¿Por qué tenemos una entrada "NA"? + +Las entradas con un valor faltante (``) en la columna `prob_distribution` son entradas *no parametrizada*. Tienen estadísticas de resumen, pero no una distribución de probabilidad. Compara estos dos resultados: + +```{r, eval=FALSE} +# get an object +distribution <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "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() +``` + +### Las entradas parametrizadas tienen un método de Inferencia + +Como se detalla en `?is_parameterised` una distribución parametrizada es la entrada que tiene una distribución de probabilidad asociada proporcionada por un método `inference_method` como se muestra en los metadatos`metadata`: + +```{r, eval=FALSE} +distribution[[1]]$metadata$inference_method +distribution[[2]]$metadata$inference_method +distribution[[4]]$metadata$inference_method +``` + +::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### ¡Encuentra tus distribuciones de retraso! + +Tómate 2 minutos para explorar el paquete `{epiparameter}`. + +**Elige** una enfermedad de interés (por ejemplo, Influenza estacional, sarampión, etc.) y una distribución de retrasos (por ejemplo, el periodo de incubación, desde el inicio hasta la muerte, etc.). + +Encuéntra: + +- ¿Cuántas distribuciones de retraso hay para esa enfermedad? + +- ¿Cuántos tipos de distribución de probabilidad (por ejemplo, gamma, log normal) hay para un retraso determinado en esa enfermedad? + +Pregunta: + +- ¿Reconoces los artículos? + +- ¿Debería la revisión de literatura de`{epiparameter}` considerar otro artículo? + +::::::::::::::::: hint + +La función `epidist_db()` con `disease` sólo con la enfermedad cuenta el número de entradas como + +- estudios, y +- distribuciones de retrasos. + +La función `epidist_db()` función con la enfermedad `disease` y `epi_dist` obtiene una lista de todas las entradas con: + +- la cita completa, +- en **tipo** de distribución de probabilidad, y +- valores de los parámetros de la distribución. + +La combinación de `epidist_db()` y `parameter_tbl()` obtiene un marco de datos de todas las entradas con columnas como + +- el **tipo** de la distribución de probabilidad por cada fila, y +- autor y año del estudio. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +Elegimos explorar las distribuciones de retraso del Ébola: + +```{r} +# we expect 16 delays distributions for ebola +epiparameter::epidist_db( + disease = "ebola" +) +``` + +Ahora, a partir de la salida de `epiparameter::epidist_db()` ¿Qué es un [distribución de la descendencia](../learners/reference.md#offspringdist)? + +Elegimos encontrar los periodos de incubación del ébola. Esta salida lista todos los documentos y parámetros encontrados. Ejecútalo localmente si es necesario: + +```{r, eval=FALSE} +epiparameter::epidist_db( + disease = "ebola", + epi_dist = "incubation" +) +``` + +Utilizamos `parameter_tbl()` para obtener una visualización resumida de todo: + +```{r, eval=TRUE} +# we expect 2 different types of delay distributions +# for ebola incubation period +epiparameter::epidist_db( + disease = "ebola", + epi_dist = "incubation" +) %>% + parameter_tbl() +``` + +Encontramos dos tipos de distribuciones de probabilidad para esta consulta: *log normal* y *gamma*. + +¿Cómo realiza `{epiparameter}` la recopilación y revisión de la literatura revisada por pares? ¡Te invitamos a leer la viñeta sobre ["Protocolo de Recopilación y Síntesis de Datos"](https://epiverse-trace.github.io/epiparameter/articles/data_protocol.html) ! + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Selecciona una única distribución + +En `epiparameter::epidist_db()` funciona como una función de filtrado o subconjunto. Utilicemos el argumento `author` para filtrar los parámetros `Hiroshi Nishiura`: + +```{r} +epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Hiroshi" +) %>% + epiparameter::parameter_tbl() +``` + +Seguimos obteniendo más de un parámetro epidemiológico. Podemos establecer el argumento `single_epidist` en `TRUE` para obtener sólo uno: + +```{r} +epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Hiroshi", + single_epidist = TRUE +) +``` + +::::::::::::::::: callout + +### ¿Cómo funciona 'single\_epidist'? + +Consultando la documentación de ayuda de `?epiparameter::epidist_db()`: + +- Si varias entradas coinciden con los argumentos suministrados y `single_epidist = TRUE` entonces devolverá el + `` parametrizado con el *mayor tamaño de muestra* +- Si varias entradas son iguales después de esta clasificación, se devolverá la *primera entrada*. + +¿Qué es un ``*parametrizado* ? Mira `?is_parameterised`. + +::::::::::::::::::::::::: + +Asignemos este objeto de clase `` al objeto`covid_serialint`. + +```{r, message=FALSE} +covid_serialint <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Nishiura", + single_epidist = TRUE + ) +``` + +Puedes utilizar `plot()` para objetos `` para visualizarlos: + +- la *Función de densidad de probabilidad (PDF, por sus siglas en inglés)* y +- la *Función de distribución acumulativa (CDF, por sus siglas en inglés)*. + +```{r} +# plot object +plot(covid_serialint) +``` + +Con el argumento `day_range`, puedes cambiar la duración o el número de días del `x` eje. Explora cómo se ve esto: + +```{r, eval=FALSE} +# plot object +plot(covid_serialint, day_range = 0:20) +``` + +## Extrae las estadísticas de resumen + +Podemos obtener la media o primedio`mean` y la desviación estándar(`sd`) a partir de `` accediendo al objeto`summary_stats`: + +```{r} +# get the mean +covid_serialint$summary_stats$mean +``` + +¡Ahora tenemos un parámetro epidemiológico que podemos reutilizar! Dado que el `covid_serialint` es una distribución log normal `lnorm` o, podemos reemplazar las **estadísticas de resumen** que introducimos en la función `EpiNow2::LogNormal()` + +```r +generation_time <- + EpiNow2::LogNormal( + mean = covid_serialint$summary_stats$mean, # replaced! + sd = covid_serialint$summary_stats$sd, # replaced! + max = 20 + ) +``` + +En el próximo episodio aprenderemos a utilizar `{EpiNow2}` para especificar correctamente las distribuciones y estimar la transmisibilidad. Después, cómo utilizar **funciones de distribución** para obtener un valor máximo (`max`) para `EpiNow2::LogNormal()` y utilizar `{epiparameter}` en tu análisis. + +:::::::::::::::::::::::::::::: callout + +### Distribuciones logarítmicas normales + +Si necesitas los parámetros de la distribución log normal **log normales** en lugar de las estadísticas de resumen, podemos utilizar `epiparameter::get_parameters()`: + +```{r} +covid_serialint_parameters <- + epiparameter::get_parameters(covid_serialint) + +covid_serialint_parameters +``` + +Se obtiene un vector de clase `` ¡listo para usar como entrada para cualquier otro paquete! + +:::::::::::::::::::::::::::::: + +## Desafíos + +:::::::::::::::::::::::::::::: challenge + +### Intervalo serial del ébola + +Tómate 1 minuto para + +Obtener acceso al intervalo serial de ébola con el mayor tamaño de muestra. + +Responde: + +- ¿Qué es el `sd` de la distribución epidemiológica? + +- ¿Cuál es el tamaño de muestra `sample_size` utilizado en ese estudio? + +::::::::: hint + +Utiliza el `$` más el operador tab o para explorarlos como una lista desplegable: + +```r +covid_serialint$ +``` + +Utiliza el `str()` para mostrar la estructura del objeto de R ``. + +:::::::::::::::::: + +:::::::::: solution + +```{r, eval=TRUE} +# ebola serial interval +ebola_serial <- + epiparameter::epidist_db( + disease = "ebola", + epi_dist = "serial", + single_epidist = TRUE + ) + +ebola_serial +``` + +```{r, eval=TRUE} +# get the sd +ebola_serial$summary_stats$sd + +# get the sample_size +ebola_serial$metadata$sample_size +``` + +Intenta visualizar esta distribución utilizando `plot()`. + +Explora también todos los demás elementos anidados dentro del objecto `` . + +Comparte sobre: + +- ¿Qué elementos encuentras útiles para tu análisis? +- ¿Qué otros elementos te gustaría ver en este objeto? ¿Cómo? + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::: instructor + +Un elemento interesante del contenido anidado es el `method_assess`, que se refiere a los métodos utilizados por los autores del estudio para evaluar el sesgo al estimar la distribución del intervalo serial. + +```{r} +covid_serialint$method_assess +``` + +¡Exploraremos estos conceptos en los siguientes episodios! + +:::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Parámetro de severidad del ébola + +Un parámetro de severidad como la duración de la hospitalización podría añadir información necesaria sobre la capacidad de camas en respuesta a un brote ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + + + +Para el ébola: + +- ¿Cuál es la *estimación puntual* reportada de la duración media de la asistencia sanitaria y el aislamiento de casos? + +::::::::::::::::: hint + +Un retraso informativo debe medir el tiempo transcurrido desde el inicio de los síntomas hasta la recuperación o la muerte. + +Encuentra una forma de acceder a toda la base de datos `{epiparameter}` y averigua cómo se puede almacenar ese retraso. La salida de `parameter_tbl()` es un dataframe o tabla de datos. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r, eval=TRUE} +# one way to get the list of all the available parameters +epidist_db(disease = "all") %>% + parameter_tbl() %>% + as_tibble() %>% + distinct(epi_distribution) + +ebola_severity <- epidist_db( + disease = "ebola", + epi_dist = "onset to discharge" +) + +# point estimate +ebola_severity$summary_stats$mean +``` + +Comprueba que para algunas entradas de `{epiparameter}` también tendrás la *incertidumbre* en torno a las *estimación puntual* de cada estadística de síntesis: + +```{r} +# 95% confidence intervals +ebola_severity$summary_stats$mean_ci +# limits of the confidence intervals +ebola_severity$summary_stats$mean_ci_limits +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::: discussion + +### Un zoológico de distribuciones + +¡Explora esta shinyapp llamada **The distribution zoo** ! + +Sigue estos pasos para reproducir la forma de la distribución de intervalo serial COVID desde `{epiparameter}` (`covid_serialint` objeto): + +1. Accede al sitio web de shiny app + , +2. Ve al panel izquierdo, +3. Mantén pulsado el botón *Categoría de distribución*: `Continuous Univariate`, +4. Selecciona un nuevo *Tipo de distribución*: `Log-Normal`, +5. Mueve los controles **deslizantes** es decir, el elemento de control gráfico que te permite ajustar un valor moviendo una barra horizontal hacia la posición `covid_serialint` parámetros. + +Reprodúcelos con el botón `distribution` y todos sus elementos de lista: `[[2]]`, `[[3]]` y `[[4]]`. Explora cómo cambia la forma de una distribución cuando cambian sus parámetros. + +Comparte sobre: + +- ¿Qué otras funciones del sitio web te parecen útiles? + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: instructor + +En el contexto de las interfaces de usuario y de las interfaces gráficas de usuario (GUI), como el [Zoo de la Distribución](https://ben18785.shinyapps.io/distribution-zoo/) una aplicación **deslizador** es un elemento de control gráfico que permite a los usuarios ajustar un valor moviendo la barra. Conceptualmente, proporciona una forma de seleccionar un valor numérico dentro de un rango especificado deslizando o arrastrando visualmente un puntero (el tirador) a lo largo de un eje continuo. + +::::::::::::::::::::::::: + + + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utiliza `{epiparameter}` para acceder al catálogo de literatura sobre distribuciones epidemiológicas de retraso. +- Utiliza `epidist_db()` para seleccionar distribuciones de retraso individuales. +- Utiliza `parameter_tbl()` para obtener una visión general de las distribuciones de retardo múltiples. +- Reutiliza las estimaciones conocidas para una enfermedad desconocida en la fase inicial de un brote cuando no se disponga de datos de rastreo de contactos. + +:::::::::::::::::::::::::::::::::::::::::::::::: + diff --git a/locale/es/episodes/quantify-transmissibility.Rmd b/locale/es/episodes/quantify-transmissibility.Rmd new file mode 100644 index 00000000..f5caf186 --- /dev/null +++ b/locale/es/episodes/quantify-transmissibility.Rmd @@ -0,0 +1,595 @@ +--- +title: 'Cuantificar la transmisión' +teaching: 30 +exercises: 0 +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- ¿Cómo puedo estimar el número de reproducción variable en el tiempo ($Rt$) y la tasa de crecimiento a partir de una serie temporal de datos de casos? +- ¿Cómo puedo cuantificar la heterogeneidad geográfica a partir de estas métricas de transmisión? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Aprender a estimar las métricas de transmisión a partir de una serie temporal de datos de casos utilizando el paquete R `EpiNow2` + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Requisitos previos + +Los alumnos deben familiarizarse con los siguientes conceptos antes de trabajar con este tutorial: + +**Estadística** Distribuciones de probabilidad y principio del análisis bayesiano. + +**Teoría epidémica** Número de reproducción efectiva. + +**Ciencia de los datos** Transformación y visualización de datos. Puedes revisar el episodio en [Agregar y visualizar](https://epiverse-trace.github.io/tutorials-early/describe-cases.html) datos de incidencia. + +::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: callout + +### Recordatorio: el Número de Reproducción Efectiva, $R_t$ + +El [número básico de reproducción](../learners/reference.md#basic), $R_0$ es el número medio de casos causados por un individuo infeccioso en una población totalmente susceptible. + +Pero en un brote en curso, la población no permanece totalmente susceptible, ya que los que se recuperan de la infección suelen ser inmunes. Además, puede haber cambios de comportamiento u otros factores que afecten la transmisión. Por lo tanto, cuando nos interesa controlar los cambios en la transmisión, es más importante tener en cuenta el valor del **número de reproducción efectiva**, $R_t$ y el número medio de casos causados por un individuo infeccioso en la población en el momento $t$. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Introducción + +La intensidad de la transmisión de un brote se cuantifica mediante dos métricas clave: el número de reproducción, que informa sobre la fuerza de la transmisión indicando cuántos casos nuevos se esperan de cada caso existente; y la [tasa de crecimiento](../learners/reference.md#growth) que informa sobre la velocidad de la transmisión, indicando la rapidez con que el brote se propaga o disminuye (tiempo de duplicación/desaparición) dentro de una población. Para más detalles sobre la distinción entre velocidad y fuerza de transmisión y las implicaciones para el control, revisa [Dushoff y Park, 2021](https://royalsocietypublishing.org/doi/full/10.1098/rspb.2020.1556). + +Para estimar estas métricas clave utilizando datos de casos, debemos tener en cuenta los retrasos entre la fecha de las infecciones y la fecha de los casos notificados. En una situación de brote, normalmente sólo se dispone de datos sobre las fechas notificadas, por lo que debemos utilizar métodos de estimación para tener en cuenta estos retrasos cuando intentemos comprender los cambios en la transmisión a lo largo del tiempo. + +En los próximos tutoriales nos centraremos en cómo utilizar las funciones de `{EpiNow2}` para estimar las métricas de transmisión de los datos de casos. No cubriremos el trasfondo teórico de los modelos ni el marco de inferencia; para más detalles sobre estos conceptos, consulta la [viñeta](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections.html). + +En este tutorial vamos a aprender a utilizar el paquete `{EpiNow2}` para estimar el número de reproducción variable en el tiempo. Obtendremos los datos de entrada de `{incidence2}`. Utilizaremos el paquete `{tidyr}` y `{dplyr}` para ordenar algunas de sus salidas, `{ggplot2}` para visualizar la distribución de casos, y el operador tubería `%>%` para conectar algunas de sus funciones, así que también llamaremos al paquete `{tidyverse}`: + +```r +library(EpiNow2) +library(incidence2) +library(tidyverse) +``` + +```{r, echo=FALSE, eval=TRUE, message=FALSE, warning=FALSE} +library(tidyverse) +``` + +::::::::::::::::::: checklist + +### El doble punto + +El doble punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza la función `filter()` del paquete `{dplyr}`. + +Esto nos ayuda a recordar las funciones del paquete y a evitar conflictos de espacio de nombres. + +::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: instructor + +Este tutorial muestra el uso de la función `epinow()` para estimar el número de reproducción variable en el tiempo y los tiempos de infección, las entradas necesarias para el modelo y las limitaciones de su resultado. + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: callout + +### Inferencia bayesiana + +El paquete R `EpiNow2` utiliza [inferencia bayesiana](../learners/reference.md#bayesian) para estimar las cifras de reproducción y los tiempos de infección basándose en las fechas de notificación. + +En la inferencia bayesiana, utilizamos el conocimiento previo (distribuciones previas) con los datos (en una función de verosimilitud) para hallar la probabilidad posterior. + +

Probabilidad posterior $\propto$ verosimilitud $\times$ probabilidad previa +

+ +:::::::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::: instructor + +Consulta la distribución de probabilidad a priori y la [probabilidad posterior](https://en.wikipedia.org/wiki/Posterior_probability). + +En la ["`Expected change in daily cases`"](#expected-change-in-daily-cases) por "la probabilidad posterior de que $R_t < 1$", nos referimos específicamente a la [área bajo la curva de distribución de probabilidad po](https://www.nature.com/articles/nmeth.3368/figures/1). + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Distribuciones de retrasos y datos de casos + +### Datos de casos + +Para explorar las funciones de `EpiNow2` utilizaremos los datos del brote del inicio de la pandemia COVID-19 del Reino Unido. Los datos están disponibles en el paquete R `{incidence2}`. + +```{r} +dplyr::as_tibble(incidence2::covidregionaldataUK) +``` + +Para utilizar los datos, debemos darles formato para que tengan dos columnas: + +- `date`: la fecha (para validar si un objeto es de tipo fecha ver `?is.Date()`), +- `confirm` número de casos confirmados en esa fecha. + +Utilicemos `{tidyr}` y `{incidence2}` para ello: + +```{r, warning=FALSE, message=FALSE} +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) +``` + +Con `incidence2::incidence()` agregamos casos en distintos tiempos *intervalos* (es decir, días, semanas o meses) o por *grupo* categorías. También podemos tener fechas completas para todo el rango de fechas por categoría de grupo utilizando `complete_dates = TRUE` +Explora más adelante la [`incidence2::incidence()` manual de referencia](https://www.reconverse.org/incidence2/reference/incidence.html) + +::::::::::::::::::::::::: spoiler + +### ¿Podemos replicar {incidence2} con {dplyr}? + +Podemos obtener un objeto similar a `cases` de la tabla de datos (`data.frame`) `incidence2::covidregionaldataUK` utilizando las siguientes funciones del paquete `{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() +``` + +Sin embargo, la función `incidence2::incidence()` contiene argumentos prácticos como `complete_dates` que facilitan la obtención de un objeto de incidencia con el mismo rango de fechas para cada agrupación sin necesidad de líneas de código adicionales ni de un paquete de series temporales. + +::::::::::::::::::::::::: + +Hay datos de casos disponibles para `r dim(cases)[1]` días, pero en una situación de brote es probable que sólo tuviéramos acceso al principio de este conjunto de datos. Por lo tanto, suponemos que sólo disponemos de los primeros 90 días de estos datos. + +```{r, echo=FALSE} +# keep the first 90 dates and visualize epicurve +cases %>% + dplyr::slice_head(n = 90) %>% + # use ggplot2 + ggplot(aes(x = date, y = confirm)) + + geom_col() + + theme_grey( + base_size = 15 + ) +``` + +### Distribuciones de retraso + +Suponemos que hay retrasos desde el momento de la infección hasta el momento en que se notifica un caso. Especificamos estos retrasos como distribuciones para tener en cuenta la incertidumbre en las diferencias a nivel individual. El retraso puede consistir en múltiples tipos de retrasos/procesos. Un retraso típico desde el momento de la infección hasta la notificación del caso puede consistir en: + +**tiempo desde la infección hasta la aparición de los síntomas** (el [período de incubación](../learners/reference.md#incubation)) + **tiempo desde el inicio de los síntomas hasta la notificación del caso** (el tiempo de notificación). + +La distribución del retraso para cada uno de estos procesos puede estimarse a partir de los datos u obtenerse de la bibliografía. Podemos expresar la incertidumbre sobre cuáles son los parámetros correctos de las distribuciones, suponiendo que las distribuciones tienen parámetros **fijos** (`_fixed`) o si tienen parámetros **variables** (`_variable`). Para entender la diferencia entre distribuciones **fijas** y **variables**, consideremos el periodo de incubación. + +::::::::::::::::::::::::::::::::::::: callout + +### Retrasos y datos + +El número de retrasos y su tipo son una entrada flexible que depende de los datos. Los siguientes ejemplos muestran cómo se pueden especificar los retrasos para distintas fuentes de datos: + +
+ +| Fuente de datos | Retraso(s) | +| ------------------------------ | --------------------------------------------------------------------------------------------- | +| Hora de inicio de los síntomas | Periodo de incubación | +| Hora del informe del caso | Periodo de incubación + tiempo desde el inicio de los síntomas hasta la notificación del caso | +| Tiempo de hospitalización | Periodo de incubación + tiempo desde el inicio de los síntomas hasta la hospitalización | + +
+ +:::::::::::::::::::::::::::::::::::::::::::::::: + +#### Distribución del periodo de incubación + +La distribución del periodo de incubación de muchas enfermedades suele obtenerse de la bibliografía. El paquete `{epiparameter}` contiene una biblioteca de parámetros epidemiológicos de distintas enfermedades obtenidos de la literatura. + +Especificamos una distribución gamma (fija) con media $\mu = 4$ y desviación típica $\sigma= 2$ (forma = $4$, escala = $1$) mediante la función `Gamma()` de la siguiente manera: + +```{r} +incubation_period_fixed <- EpiNow2::Gamma( + mean = 4, + sd = 2, + max = 20 +) + +incubation_period_fixed +``` + +El argumento `max` es el valor máximo que puede tomar la distribución, en este ejemplo 20 días. + +::::::::::::::::::::::::::::::::::::: callout + +### ¿Por qué una distribución gamma? + +El periodo de incubación debe tener un valor positivo. Por lo tanto, tenemos que especificar una distribución en `{EpiNow2}` que sea sólo para valores positivos. + +`Gamma()` admite distribuciones Gamma y `LogNormal()` Distribuciones logarítmicas normales, que son distribuciones sólo para valores positivos. + +Para todos los tipos de retraso, tendremos que utilizar distribuciones sólo para valores positivos: ¡no queremos incluir retrasos de días negativos en nuestro análisis! + +:::::::::::::::::::::::::::::::::::::::::::::::: + +#### Incluyendo la incertidumbre de distribución + +Para especificar una distribución **variable**, incluimos la incertidumbre en torno a la media $\mu$ y la desviación típica $\sigma$ de nuestra distribución gamma. Si nuestra distribución del periodo de incubación tiene una media $\mu$ y una desviación típica $\sigma$ entonces suponemos que la media ($\mu$) sigue una distribución Normal con desviación típica $\sigma_{\mu}$: + +$$\mbox{Normal}(\mu,\sigma_{\mu}^2)$$ + +y una desviación típica ($\sigma$) sigue una distribución Normal con desviación típica $\sigma_{\sigma}$: + +$$\mbox{Normal}(\sigma,\sigma_{\sigma}^2).$$ + +Lo especificamos utilizando `Normal()` para cada argumento: la media ($\mu=4$ con $\sigma_{\mu}=0.5$) y la desviación típica ($\sigma=2$ con $\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 +``` + +#### Retrasos en los informes + +Tras el periodo de incubación, habrá un retraso adicional desde el inicio de los síntomas hasta la notificación del caso: el retraso de notificación. Podemos especificarlo como una distribución fija o variable, o estimar una distribución a partir de los datos. + +Al especificar una distribución, es útil visualizar la densidad de probabilidad para ver el pico y la dispersión de la distribución, en este caso utilizaremos una *log normal* logarítmica normal. Podemos utilizar las funciones `convert_to_logmean()` y `convert_to_logsd()` para convertir la media y la desviación típica de una distribución normal en las de una distribución logarítmica normal. + +Si queremos suponer que la media del retraso en la notificación es de 2 días (con una desviación típica de 1 día), escribimos: + +```{r} +# obtener logmean a partir de la media y sd +log_mean <- EpiNow2::convert_to_logmean(mean = 2, sd = 1) + +# obtener logsd a partir de la media y sd +log_sd <- EpiNow2::convert_to_logsd(mean = 2, sd = 1) +``` + +:::::::::::::::::::::: spoiler + +### Visualiza una distribución log Normal utilizando {epiparameter} + +Utilizando `epiparameter::epidist()` podemos crear una distribución personalizada. La distribución log normal tendrá el siguiente aspecto: + +```r +library(epiparameter) +``` + +```{r, message=FALSE, warning=FALSE} +epiparameter::epidist( + disease = "covid", + epi_dist = "reporting delay", # retraso del reporte + prob_distribution = "lnorm", + prob_distribution_params = c( + meanlog = log_mean, + sdlog = log_sd + ) +) %>% + plot() +``` + +:::::::::::::::::::::: + +Utilizando la media y la desviación típica de la distribución log normal, podemos especificar una distribución fija o variable utilizando `LogNormal()` como antes: + +```{r, warning=FALSE, message=FALSE} +reporting_delay_variable <- EpiNow2::LogNormal( + meanlog = EpiNow2::Normal(mean = log_mean, sd = 0.5), + sdlog = EpiNow2::Normal(mean = log_sd, sd = 0.5), + max = 10 +) +``` + +Podemos trazar distribuciones simples y combinadas generadas por `{EpiNow2}` utilizando `plot()`. Combinemos en un gráfico el retraso desde la infección hasta la notificación, que incluye el periodo de incubación y el retraso en la notificación: + +```{r} +plot(incubation_period_variable + reporting_delay_variable) +``` + +:::::::::::::::::: callout + +Si disponemos de datos sobre el tiempo transcurrido entre el inicio de los síntomas y la notificación, podemos utilizar la función `estimate_delay()` para estimar una distribución log normal a partir de un vector de retrasos. El siguiente código muestra cómo utilizar `estimate_delay()` con datos sintéticos de retrasos. + +```{r, eval=FALSE} +delay_data <- rlnorm(500, log(5), 1) # datos de retraso sintéticos + +reporting_delay <- EpiNow2::estimate_delay( + delay_data, + samples = 1000, + bootstraps = 10 +) +``` + +:::::::::::::::::: + +#### Tiempo de generación + +También debemos especificar una distribución para el tiempo de generación. Aquí utilizaremos una distribución log normal con media 3.6 y desviación típica 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 +) +``` + +## Estimaciones de hallazgos + +La función `epinow()` es una envoltura de la función `estimate_infections()` utilizada para estimar los casos por fecha de infección. La distribución del tiempo de generación y las distribuciones del retraso deben pasarse utilizando las funciones ` generation_time_opts()` y `delay_opts()` respectivamente. + +Hay muchas otras entradas que se pueden pasar a `epinow()` ver `?EpiNow2::epinow()` para más detalles. +Una entrada opcional es especificar una *log normal* para el número de reproducción efectivo $R_t$ al inicio del brote. Especificamos una media de 2 días y una desviación típica de 2 días como argumentos de `prior` dentro de `rt_opts()`: + +```{r, eval=TRUE} +# define Rt prior distribution +rt_prior <- EpiNow2::rt_opts(prior = base::list(mean = 2, sd = 2)) +``` + +::::::::::::::::::::::::::::::::::::: callout + +### Inferencia bayesiana con Stan + +La inferencia bayesiana se realiza utilizando métodos MCMC con el programa [Stan](https://mc-stan.org/). Hay una serie de entradas por defecto para las funciones Stan, incluido el número de cadenas y el número de muestras por cadena (ver `?EpiNow2::stan_opts()`). + +Para reducir el tiempo de cálculo, podemos ejecutar las cadenas en paralelo. Para ello, debemos establecer el número de núcleos que se van a utilizar. Por defecto, se ejecutan 4 cadenas MCMC (ver `stan_opts()$chains`), por lo que podemos establecer un número igual de núcleos para que se utilicen en paralelo de la siguiente manera: + +```{r, warning=FALSE, message=FALSE} +withr::local_options(base::list(mc.cores = 4)) +``` + +Para averiguar el número máximo de núcleos disponibles en tu máquina, utiliza `parallel::detectCores()`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::: checklist + +**Nota:** En el siguiente código `_fixed` se utilizan distribuciones en lugar de `_variable` (distribuciones de retraso con incertidumbre). Esto se hace para acelerar el tiempo de cálculo. En general, se recomienda utilizar distribuciones variables que tengan en cuenta la incertidumbre adicional. + +```{r, echo=TRUE} +# alternativas: distribuciones con parámetros fijos +generation_time_fixed <- EpiNow2::LogNormal( + mean = 3.6, + sd = 3.1, + max = 20 +) + +reporting_delay_fixed <- EpiNow2::LogNormal( + mean = log_mean, + sd = log_sd, + max = 10 +) +``` + +::::::::::::::::::::::::: + +Ahora estás listo para ejecutar `EpiNow2::epinow()` para estimar el número de reproducción variable en el tiempo durante los primeros 90 días: + +```{r, message=FALSE, eval=TRUE} +reported_cases <- cases %>% + dplyr::slice_head(n = 90) +``` + +```{r, message=FALSE, eval=TRUE, echo=TRUE} +estimates <- EpiNow2::epinow( + # casos + data = reported_cases, + # retrasos + generation_time = EpiNow2::generation_time_opts(generation_time_fixed), + delays = EpiNow2::delay_opts(incubation_period_fixed + reporting_delay_fixed), + # prior + rt = rt_prior +) +``` + + + + + + + + + + + + + + + + + + + + + + + + + +::::::::::::::::::::::::::::::::: callout + +### No esperes a que esto continúe + +Para efectos de este tutorial, podemos utilizar opcionalmente `EpiNow2::stan_opts()` para reducir el tiempo de cálculo. Podemos especificar un número fijo de `samples = 1000` y `chains = 3` al argumento `stan` de la función `EpiNow2::epinow()`. Esperamos que esto lleve aproximadamente 3 minutos. + + + +```r +# puedes adicionar el argumento `stan` +EpiNow2::epinow( + ..., + stan = EpiNow2::stan_opts(samples = 1000, chains = 3) +) +``` + +**Recuerda:** Utilizar un número adecuado de *muestras* y *cadenas* es crucial para garantizar la convergencia y obtener estimaciones fiables en los cálculos bayesianos con Stan. Los resultados más precisos se obtienen a costa de la velocidad. + +::::::::::::::::::::::::::::::::: + +### Resultados + +Podemos extraer y visualizar estimaciones del número de reproducción efectivo a lo largo del tiempo: + +```{r} +estimates$plots$R +``` + +La incertidumbre de las estimaciones aumenta con el tiempo. Esto se debe a que las estimaciones se basan en datos del pasado, dentro de los periodos de retraso. Esta diferencia de incertidumbre se clasifica en **Estimación** (verde) utiliza todos los datos y **Estimación basada en datos parciales** (naranja) estimaciones que se basan en menos datos (porque es más probable que las infecciones que se produjeron en su momento no se hayan observado todavía), por este motivo, tienen intervalos cada vez más amplios hacia la fecha del último punto de datos. Por último, el **Pronóstico** (morado) es una proyección a futuro. + +También podemos visualizar la estimación de la tasa de crecimiento a lo largo del tiempo: + +```{r} +estimates$plots$growth_rate +``` + +Para extraer un resumen de las métricas clave de transmisión en la *última fecha* de los datos: + +```{r} +summary(estimates) +``` + +Como estas estimaciones se basan en datos parciales, tienen un amplio intervalo de incertidumbre. + +- Del resumen de nuestro análisis se desprende que el cambio esperado en los casos diarios es de `r summary(estimates)$estimate[summary(estimates)$measure=="Expected change in daily cases"]` con la estimación de nuevos casos confirmados `r summary(estimates)$estimate[summary(estimates)$measure=="New confirmed cases by infection date"]`. + +- El número de reproducción efectivo $R_t$ estimado (en la última fecha de los datos) es `r summary(estimates)$estimate[summary(estimates)$measure=="Effective reproduction no."]`. + +- La tasa de crecimiento exponencial del número de casos es `r summary(estimates)$estimate[summary(estimates)$measure=="Rate of growth"]`. + +- El tiempo de duplicación (el tiempo que tarda en duplicarse el número de casos) es `r summary(estimates)$estimate[summary(estimates)$measure=="Doubling/halving time (days)"]`. + +::::::::::::::::::::::::::::::::::::: callout + +### `Expected change in daily cases` + +Un factor que describe el cambio esperado en los casos diarios, basado en la probabilidad posterior de que $R_t < 1$. + +
+| Probabilidad ($p$) | Cambio esperado | +| ------------- |-------------| +|$p < 0,05$ |Aumentando |$ 0,05 +|$0,05 \leq p< 0,4$ |Probable aumento | +|0,4 p< 0,6$ Estable +|0,6 p < 0,95$ Probable disminución +|0,95 \leq p \leq 1$ |En disminución |Estable +
+ +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Cuantificar la heterogeneidad geográfica + +Los datos del brote del inicio de la pandemia COVID-19 del Reino Unido del paquete R `{incidence2}` incluyen la región en la que se registraron los casos. Para encontrar estimaciones regionales del número de reproducción efectiva y de casos, debemos dar formato a los datos para que tengan tres columnas: + +- `date`: la fecha. +- `region`: la región. +- `confirm`: número de casos confirmados para una región en una fecha determinada. + +```{r, warning=FALSE, message=FALSE} +regional_cases <- incidence2::covidregionaldataUK %>% + # usar {tidyr} para pre-procesar los valores faltantes + tidyr::replace_na(base::list(cases_new = 0)) %>% + # usar {incidence2} para convertir datos agregados en datos de incidencia + 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) + +# mantener las primeras 90 fechas para todas las regiones + +# obtener el vector de las primeras 90 fechas +date_range <- regional_cases %>% + dplyr::distinct(date) %>% + # desde {incidence2}, las fechas ya están ordenadas en orden ascendente + dplyr::slice_head(n = 90) %>% + dplyr::pull(date) + +# filtrar las fechas en la variable date_range +regional_cases <- regional_cases %>% + dplyr::filter(magrittr::is_in(x = date, table = date_range)) + +dplyr::as_tibble(regional_cases) +``` + +Para hallar las estimaciones regionales, utilizamos los mismos datos que `epinow()` para la función `regional_epinow()`: + +```{r, message=FALSE, eval=TRUE, echo=TRUE} +estimates_regional <- EpiNow2::regional_epinow( + # casos + data = regional_cases, + # retrasos + generation_time = EpiNow2::generation_time_opts(generation_time_fixed), + delays = EpiNow2::delay_opts(incubation_period_fixed + reporting_delay_fixed), + # prior + rt = rt_prior +) +``` + + + + + + + + + + + + + + + + + + + + + + + + + +```{r, message=FALSE, eval=TRUE} +estimates_regional$summary$summarised_results$table + +estimates_regional$summary$plots$R +``` + + + + + + + +## Resumen + +`EpiNow2` puede utilizarse para estimar las métricas de transmisión a partir de los datos de casos en cualquier momento del curso de un brote. La fiabilidad de estas estimaciones depende de la calidad de los datos y de la elección adecuada de las distribuciones de retraso. En el siguiente tutorial aprenderemos a hacer previsiones e investigaremos algunas de las opciones adicionales de inferencia disponibles en `EpiNow2`. + +::::::::::::::::::::::::::::::::::::: keypoints + +- Las métricas de transmisión pueden estimarse a partir de los datos del caso tras tener en cuenta los retrasos +- La incertidumbre puede tenerse en cuenta en las distribuciones de retrasos + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/es/episodes/severity-static.Rmd b/locale/es/episodes/severity-static.Rmd new file mode 100644 index 00000000..f7423d71 --- /dev/null +++ b/locale/es/episodes/severity-static.Rmd @@ -0,0 +1,872 @@ +--- +title: 'Estimación de la gravedad del brote' +teaching: 10 +exercises: 2 +editor_options: + chunk_output_type: inline +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- ¿Por qué estimamos la gravedad clínica de una epidemia? + +- ¿Cómo se puede estimar el tasa de letalidad (TL o CFR por sus siglas en inglés: _Case Fatality Risk_) al principio de una epidemia en curso? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Estimar la tasa de letalidad a partir de datos de casos agregados utilizando el paquete `{cfr}`, llamado así dado que tasa de letalidad se conoce como *case fatality risk* en inglés (riesgo de fatalidad de casos). + +- Estima la tasa de letalidad, ajustando este cálculo teniendo en cuenta el intervalo entre la aparición de síntomas y la muerte del paciente utilizando los paquetes `{epiparameter}` y `{cfr}`. + +- Estima la letalidad de una enfermedad durante la fase de crecimiento exponencial de una epidemia en expansión utilizando `{cfr}`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Requisitos previos + +Este episodio requiere que estés familiarizado con + +**Ciencia de datos** Programación básica con R + +**Teoría epidémica**: [Distribuciones temporales](../learners/reference.md#delaydist). + +::::::::::::::::::::::::::::::::: + +## Introducción + +Entre las preguntas más comunes en la fase inicial de una epidemia se incluyen: + +- ¿Cuál es el impacto probable del brote en la salud pública en términos de gravedad clínica? +- ¿Cuáles son los grupos más gravemente afectados? +- ¿Tiene el brote potencial para causar una epidemia de grandes dimensiones o incluso una pandemia? + +Podemos evaluar el potencial pandémico de una epidemia con dos medidas críticas: la transmisibilidad y la gravedad clínica +([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)). + +![Escenarios de Planificación de Pandemias del HHS basados en el Marco de Evaluación de la Gravedad de la Pandemia. Éste utiliza una medida combinada de gravedad clínica y transmisibilidad para caracterizar los escenarios de pandemia de gripe. **HHS**: Departamento de Salud y Servicios Humanos de los Estados Unidos ([CDC, 2016](https://www.cdc.gov/flu/pandemic-resources/national-strategy/severity-assessment-framework-508.html)).](fig/cfr-hhs-scenarios-psaf.png) + +Un enfoque epidemiológico para estimar la gravedad clínica consiste en cuantificar la tasa de letalidad (TL). TL es la probabilidad condicional de muerte una vez confirmado el diagnóstico de la enfermedad, calculada como el número acumulado de muertes por una enfermedad infecciosa dividido por el número de casos diagnosticados confirmados. Sin embargo, calcularlo directamente durante el curso de una epidemia tiende a dar como resultado un TL sesgado, dado el [intervalo temporal](../learners/reference.md#delaydist) que ocurre desde el inicio de lo síntomas hasta la muerte. Este retraso temporal varía sustancialmente a medida que avanza la epidemia y se estabiliza en las últimas fases del brote ([Ghani et al., 2005](https://academic.oup.com/aje/article/162/5/479/82647?login=false#620743)). + +![Estimaciones sesgadas de la tasa de letalidad como función del tiempo (línea gruesa), calculado como el número acumulado +de muertes dividido por el número de casos confirmados en el tiempo $t$. La estimación de la tasa de letalidad al final de un brote (~30 de mayo) corresponde con la tasa de letalidad verdadera. +La línea continua horizontal y las líneas de puntos muestran el valor esperado y los intervalos de confianza del 95% ($95%$ IC) de la predicción de la tasa de letalidad ajustada al retraso temporal entre el periodo inicial de síntomas y muerte +, utilizando los datos observados hasta el 27 de Marzo de 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) + +::::::::::::::::::::::: instructor + +Los periodos de tiempo son relevantes: Periodo 1 -- 15 días en los que la TL es cero para indicar que no se han notificado muertes; Periodo del 15 de marzo -- 26 de abril en el que la TL parece aumentar; Periodo del 30 de abril -- 30 de mayo en el que la estimación de la TL se estabiliza. + +::::::::::::::::::::::: + +En términos más generales, estimar la gravedad puede ser útil incluso fuera de un escenario de planificación pandémica y en el contexto de la salud pública rutinaria. +Saber si un brote tiene o tuvo una gravedad diferente a la del registro histórico puede motivar investigaciones causales, +que podrían ser intrínsecas al agente infeccioso (por ejemplo, una nueva cepa más grave) o debidas a factores subyacentes en la población (por ejemplo, inmunidad reducida o factores de morbilidad) ([Lipsitch et al., 2015](https://journals.plos.org/plosntds/article?id=10.1371/journal.pntd.0003846)). + +En este tutorial vamos a aprender a utilizar la función `{cfr}` para calcular y ajustar una estimación de la tasa de letalidad utilizando [distribuciones temporales](../learners/reference.md#delaydist) provenientes de `{epiparameter}` o de otras fuentes, basándose en los métodos desarrollados por [Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) además, aprenderemos como reimplementar las funciones de `{cfr}` para realizar otras mediciones de la gravedad de la enfermedad, por ejemplo, el riesgo de fatalidad hospitalaria. + +Utilizaremos el operador `%>%` para conectar funciones, por lo que es necesario también acceder al paquete`{tidyverse}`: + +```{r, message=FALSE, warning=FALSE} +library(cfr) +library(epiparameter) +library(tidyverse) +library(outbreaks) +``` + +::::::::::::::::::: checklist + +### El doble punto + +El doble punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza `filter()` del paquete `{dplyr}`. + +Esto nos ayuda a recordar las funciones requeridas y evitar usar funciones que fueron creadas con el mismo nombre pero provienen de otros paquetes. + +::::::::::::::::::: + +## Fuentes de datos para la gravedad clínica + +¿Qué fuentes de datos podemos utilizar para estimar la gravedad clínica de un brote epidémico? [Verity et al., 2020](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099\(20\)30243-7/fulltext) resume el espectro de casos de COVID-19: + +![Espectro de casos de COVID-19. La tasa de letalidad pretende estimar la proporción de muertes entre los casos confirmados en una epidemia. +([Verity et al., 2020](https://www.thelancet.com/journals/laninf/article/PIIS1473-3099\(20\)30243-7/fulltext#gr1))](fig/cfr-spectrum-cases-covid19.jpg) + +- En la cúspide de la pirámide, los que cumplían los criterios de caso de la OMS para **grave** o críticos, identificados en el ámbito hospitalario, presentando una neumonía vírica atípica. Estos casos se habrían identificado en China continental y entre los categorizados internacionalmente como de transmisión local. +- Es probable que haya muchos más casos **sintomáticos** (es decir, con fiebre, tos o mialgia) pero no requiriesen hospitalización. Estos casos se habrían identificado mediante el rastro de casos potenciales en vuelos internacionales a zonas de alto riesgo y mediante el rastreo de los contactos de los casos confirmados, o a través de vigilancia pasiva de otras enfermedades infecciosas respiratorias en la población. +- La parte inferior de la pirámide representa enfermedad **leve** (y posiblemente **asintomática**). Estos casos podrían identificarse mediante el rastreo de contactos, mediante pruebas serológicas. + + ## Tasa de letalidad no ajustada + +Medimos la gravedad de la enfermedad en términos de riesgo/tasa de letalidad (TL). TL se interpreta como la probabilidad condicional de muerte dado un diagnóstico confirmado, calculada como el número acumulado de muertes $D_{t}$ sobre el número acumulado de casos confirmados $C_{t}$ en un momento determinado $t$. Podemos referirnos al *TL sesgado* ($b_{t}$): + +$$ b_{t} = \frac{D_{t}}{C_{t}} $$ + +Este cálculo es *sesgado* porque genera una subestimación de la TL real, debido al retraso temporal desde el inicio de los síntomas hasta la muerte, que sólo se estabiliza en las últimas fases del brote. + + + + + +Para calcular la TL de forma directa y sin ajustar el retraso temporal entre la aparición de síntomas y la muerte del paciente (conocida como tasa de letalidad "naive"), el paquete `{cfr}` requiere un una base de datos (dataframe) que contenga las siguientes tres columnas: + +- `date` +- `cases` +- `deaths` + +Exploremos la base de datos `ebola1976` incluido en {cfr} que procede del primer brote de ébola en lo que entonces se llamaba Zaire (ahora República Democrática del Congo) en 1976, analizado por Camacho et al. (2014). + +```{r} +# Cargamos la base de datos Ebola 1976, incluida en el paquete {cfr} +data("ebola1976") + +# Asumiendo que solo tenemos datos para los primeros 30 días del brote +ebola1976 %>% + slice_head(n = 30) %>% + as_tibble() +``` + +:::::::::::::::::: callout + +### Necesitamos datos de incidencia agregados + +`{cfr}` lee datos de incidencia **agregados** por día + + + +```{r, eval=FALSE, echo=FALSE} +EpiNow2::example_confirmed %>% as_tibble() +``` + +Estos deben ser **agregados** por día, es decir, cada fila de la base de datos contiene el número diario de casos y muertes notificadas. También deben incluirse aquellos días que tengan valores nulos o ausentes, de forma similar a los datos de series temporales. + +`{cfr}` requiere datos diarios y no puede considerar otras unidades temporales de agregación, como semanas o meses. + + + + + +:::::::::::::::::: + +Utilizando la función `cfr_static()` directamente, calculamos la tasa de letalidad sin ajustar: + +```{r} +# Cálculo de la tasa de letalidad sin ajustar durante los primeros 30 días +cfr::cfr_static(data = ebola1976 %>% slice_head(n = 30)) +``` + +:::::::::::::::::::::::::::::::::::::::: challenge + +Descarga el archivo [sarscov2\_casos\_defunciones.csv](data/sarscov2_cases_deaths.csv) y léelo en R. + +Estima la tasa de letalidad sin ajustar. + +:::::::::::::::::::: hint + +Comprueba el formato de los datos introducidos. + +- ¿Contiene datos diarios? +- ¿Los nombres de las columnas son los requeridos por `cfr_static()`? +- ¿Cómo se cambian los nombres de las columnas de una base de datos (dataframe) en R? + +:::::::::::::::::::: + +:::::::::::::::::::: solution + +Leemos los datos introducidos mediante `readr::read_csv()`. Esta función reconoce que la columna `date` tiene el formato correcto,``, que corresponde a fechas. + +```{r, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE} +# carga la base de datos que se encuentra en el repositorio de este tutorial +sarscov2_input <- + readr::read_csv(file.path("data", "sarscov2_cases_deaths.csv")) +``` + +```{r, eval=FALSE, echo=TRUE, warning=FALSE, message=FALSE} +# lee la base de datos +# por ejemplo, si la ruta al archivo es data/raw-data/ebola_cases.csv : +sarscov2_input <- + readr::read_csv(here::here("data", "raw-data", "sarscov2_cases_deaths.csv")) +``` + +```{r} +# Inspect data +sarscov2_input +``` + +Podemos utilizar `dplyr::rename()` para cambiar los nombres de las columnas de este archivo y adaptarlos a los requeridos por `cfr_static()`. + +```{r} +# Cambio de nombre de las columnas en base al formato requerido por `cfr_static` +sarscov2_input %>% + dplyr::rename( + cases = cases_jpn, + deaths = deaths_jpn + ) %>% + cfr::cfr_static() +``` + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: + +## Sesgos que afectan a la estimación de la TL + +::::::::::::::::::::::::::::: discussion + +### Dos sesgos que afectan a la estimación de la TL + +[Lipsitch y otros, 2015](https://journals.plos.org/plosntds/article?id=10.1371/journal.pntd.0003846) describen dos posibles sesgos que pueden afectar a la estimación de la tasa de letalidad (y sus posibles soluciones): + +::::::::::::::::::::::::::::: + +::::::::::::: solution + +### 1\. Sesgo por la identificación predominante de los casos más graves + +Para enfermedades con un *espectro* de presentaciones clínicas, es más probable que los casos de mayor gravedad sean reconocidos y notificados a las autoridades de salud pública y se registran en las bases de datos de vigilancia, ya que las personas con síntomas graves son las que suelen buscar atención médica y acuden al centro de salud/hospital. + +Por lo tanto, la TL será normalmente más elevada entre *los casos detectados* que entre toda la población de casos, dado que esta última puede incluir individuos con presentaciones leves, subclínicas, y (según algunas definiciones de "caso") asintomáticas. + +::::::::::::: + +:::::::::::: solution + +### 2\. Sesgo debido al retraso en la notificación de la defunción + +En tiempo real durante una epidemia, suele haber un retraso temporal entre el momento en que alguien muere y el momento en que se notifica su muerte a la autoridad correspondiente. Por lo tanto, la lista de casos en tiempo real incluye a personas que morirán a causa de la enfermedad en el futuro, pero que aún siguen vivas, o que han muerto, pero cuya muerte no se ha notificado aún. Así pues, dividir el número acumulado de muertes notificadas por el número acumulado de casos notificados en un momento concreto durante un brote epidémico subestimará la TL verdadera. + +Los determinantes clave de la magnitud del sesgo son la *tasa de crecimiento* de la epidemia y la *distribución* del intervalo de tiempo desde la notificación del caso hasta la notificación de la defunción. Cuanto más largos sea este intervalo de tiempo y mayor sea la tasa de crecimiento, mayor será el sesgo. + +En este episodio del tutorial, vamos a centrarnos en las soluciones para hacer frente a este sesgo utilizando el paquete de R`{cfr}` ¡! + +:::::::::::: + +:::::::::::::::::::: solution + +### Caso de estudio: Gripe A (H1N1), México, 2009 + +Mejorar la estimación de la tasa de letalidad, ajustando su cálculo al retraso temporal entre notificación de casos y muerte es crucial para determinar la gravedad de la enfermedad, adaptar la intensidad y el tipo de intervenciones de salud pública y asesorar a la población. + +En 2009, durante el virus de la gripe porcina, Gripe A (H1N1) en México, la estimación temprana de la tasa de letalidad fue sesgada. Los informes iniciales del gobierno de México sugerían una infección virulenta, mientras que, en otros países, el mismo virus se percibía como leve ([TIME, 2009](https://content.time.com/time/health/article/0,8599,1894534,00.html)). + +En EE.UU. y Canadá, no se atribuyó ninguna muerte al virus en los diez primeros días tras la declaración de emergencia de salud pública por parte de la Organización Mundial de la Salud. + +[Fraser et al., 2009](https://www.science.org/doi/full/10.1126/science.1176062) reinterpretó los datos evaluando los sesgos y obteniendo una gravedad clínica inferior a la de la pandemia de gripe de 1918, pero comparable a la observada en la pandemia de 1957. + +:::::::::::::::::::: + +:::::::::::::::::::: instructor + +Podemos mostrar este sesgo utilizando la función [concepto descrito en esta viñeta del paquete`{cfr}`](https://epiverse-trace.github.io/cfr/articles/cfr.html#concept-how-reporting-delays-bias-cfr-estimates). + + + +:::::::::::::::::::: + +## TL ajustada al retraso temporal + +[Nishiura et al, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) desarrollaron un método que tiene en cuenta la **distribución temporal** desde el inicio de los síntomas hasta la muerte. + +Los brotes en tiempo real pueden tener un número de muertes insuficiente para determinar la distribución temporal entre el inicio de síntomas y la muerte. Por tanto, podemos estimar la *distribución temporal* en brotes históricos o utilizar las distribuciones incluidas en paquetes de R como `{epiparameter}` o `{epireview}` que los recogen de la literatura científica publicada. Para una guía paso a paso, lee el episodio tutorial sobre cómo [acceder a distribuciones temporales epidemiológicas](https://epiverse-trace.github.io/tutorials-early/delays-reuse.html). + +Utilicemos `{epiparameter}`: + +```{r, message=FALSE, warning=FALSE} +# Get delay distribution +onset_to_death_ebola <- + epiparameter::epidist_db( + disease = "Ebola", + epi_dist = "onset_to_death", + single_epidist = TRUE + ) + +# Plot object +plot(onset_to_death_ebola, day_range = 0:40) +``` + +Para calcular la TL ajustada, podemos utilizar la función `cfr_static()`, a través del argumento `delay_density`. + +```{r} +# Calculate the delay-adjusted CFR +# for the first 30 days +cfr::cfr_static( + data = ebola1976 %>% slice_head(n = 30), + delay_density = function(x) density(onset_to_death_ebola, x) +) +``` + +```{r, echo=FALSE} +out_delay_adjusted <- + cfr::cfr_static( + data = ebola1976 %>% slice_head(n = 30), + delay_density = function(x) density(onset_to_death_ebola, x) + ) + +out_estimate <- out_delay_adjusted %>% pull(severity_estimate) +out_low <- out_delay_adjusted %>% pull(severity_low) +out_high <- out_delay_adjusted %>% pull(severity_high) +``` + +La tasa de letalidad ajustada indicó que la gravedad de la enfermedad *al final del brote* o con el *últimos datos disponibles en ese momento* es `r out_estimate` con un intervalo de confianza del 95% entre `r out_low` y `r out_high`, con un valor superior al obtenido a través del cálculo directo sin ajustar. + +:::::::::::::::::: callout + +### Utiliza la clase epidist + +Cuando utilices una clase `` puedes utilizar esta expresión como plantilla: + +`function(x) density(, x)` + +Para distribuciones cuyos parámetros no estén disponibles en `{epiparameter}`, te proponemos dos alternativas: + +- Crear un objeto ``, que puede ser utilizado con otros paquetes de R para análisis de brotes. Lee la [documentación de referencia de `epiparameter::epidist()`](https://epiverse-trace.github.io/epiparameter/reference/epidist.html) o + +- Lee la viñeta para [una introducción al trabajo con distribuciones temporales](https://epiverse-trace.github.io/cfr/articles/delay_distributions.html). + +:::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: challenge + +Utiliza el mismo archivo del reto anterior ([sarscov2\_casos\_muertes.csv](data/sarscov2_cases_deaths.csv)). + +Estima la TL ajustada al retraso temporal utilizando la distribución apropiada y + +- ¡Compara los valores de la TL ajustada y sin ajuste temporal! + +:::::::::::::::::::: hint + +- Encuentra el `` ¡apropiado! + +:::::::::::::::::::: + +:::::::::::::::::::: solution + +Utilizamos `{epiparameter}` para acceder a una distribución temporal para los datos de incidencia agregados del SARS-CoV-2: + +```{r, message=FALSE, warning=FALSE} +library(epiparameter) + +sarscov2_delay <- + epidist_db( + disease = "covid", + epi_dist = "onset to death", + single_epidist = TRUE + ) +``` + +Leemos el archivo de datos mediante `readr::read_csv()`. Esta función reconoce que la columna `date` es de la clase ``, es decir, una fecha. + +```{r, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE} +# read data from the tutorial repository R project +sarscov2_input <- + readr::read_csv(file.path("data", "sarscov2_cases_deaths.csv")) +``` + +```{r, eval=FALSE, echo=TRUE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +sarscov2_input <- + readr::read_csv(here::here("data", "raw-data", "sarscov2_cases_deaths.csv")) +``` + +```{r} +# Inspect data +sarscov2_input +``` + +Podemos utilizar `dplyr::rename()` para cambiar los nombres de las columnas del archivo a los requeridos por`cfr_static()`. + +```{r} +# Rename before Estimate naive CFR +sarscov2_input %>% + dplyr::rename( + cases = cases_jpn, + deaths = deaths_jpn + ) %>% + cfr::cfr_static(delay_density = function(x) density(sarscov2_delay, x)) +``` + +Interpreta las diferencias entre las estimaciones de la tasa de letalidad sin ajustar y con ajuste temporal al intervalo entre la aparición inicial de síntomas en los casos y su muerte. + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::: spoiler + +### ¿Cuándo utilizar distribuciones discretas? + +En `cfr_static()` y toda la familia de funciones en `cfr_*()`, la opción más adecuada son las distribuciones **discretas**. Esto se debe a que trabajaremos con datos diarios de casos y defunciones. + +Podemos suponer que la función de densidad de probabilidad (PDF) de una distribución *continua* es equivalente a la función de masa de probabilidad (PMF) de la distribución *discreta* correspondiente. + +Sin embargo, esta suposición puede no ser adecuada en el caso de distribuciones con picos pronunciados y baja varianza, en las que los valores se concentran alrededor de la tendencia central. En tales casos, se espera que la disparidad media entre la PDF y la PMF sea más pronunciada en comparación con las distribuciones más dispersas. Una forma de abordar esto es discretizar la distribución continua. Esto lo podemos hacer en R, si discretizamos los objetos ``, utilizando la función `epiparameter::discretise()`. + +:::::::::::::::::: + +::::::::::::::::::::::::::: spoiler + +### ¿Cómo funciona {cfr}? + +Para ajustar la tasa de letalidad, [Nishiura y otros, 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) utilizan los datos de incidencia de casos y muertes para estimar el número de casos con resultados conocidos: + +$$ +u_t = \dfrac{\sum_{i = 0}^t +\sum_{j = 0}^\infty c_{i - j} f_{j}}{\sum_{i = 0} c_i}, +$$ + +donde + +- $c_{t}$ es la incidencia diaria de casos en el momento $t$, +- $f_{t}$ es el valor de la función de masa de probabilidad (PMF) de la **distribución temporal** entre el inicio de síntomas y la muerte, y +- $u_{t}$ representa el factor de subestimación de los resultados conocidos. + +$u_{t}$ se utiliza para **escalar** el valor del número acumulado de casos en el denominador en el cálculo de la TL. Se calcula internamente con la función [`estimate_outcomes()`](https://epiverse-trace.github.io/cfr/reference/estimate_outcomes.html) + +El estimador para la tasa de letalidad puede expresarse como: + +$$p_{t} = \frac{b_{t}}{u_{t}}$$ + +donde $p_{t}$ es la proporción realizada de casos confirmados que morirán a causa de la infección (o la TL real), y $b_{t}$ es la estimación cruda y sesgada de la TL. + +A partir de esta última ecuación, observamos que la TL no sesgada $p_{t}$ es mayor que la TL sesgada $b_{t}$ porque en $u_{t}$ el numerador es menor que el denominador (observa que $f_{t}$ es la distribución de probabilidad del *retraso temporal* entre síntomas y muerte). Por tanto, nos referimos a $b_{t}$ como el estimador sesgado de la tasa de letalidad. + +Cuando observamos todo el curso de una epidemia (desde $t \rightarrow \infty$), $u_{t}$ tiende a 1, lo que hace que $b_{t}$ tiende a $p_{t}$ y se convierta en un estimador no sesgado ([Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852)). + +::::::::::::::::::::::::::: + +## Estimación temprana de la TL + +En el reto anterior, descubrimos que el valor de la tasa de letalidad ajustada y no ajustada son diferentes. + +La TL sin ajustar es útil para obtener una estimación global de la gravedad del brote. Una vez que el brote haya finalizado o haya progresado de forma que se notifiquen más muertes, la TL estimada es entonces *más cercana a* la TL "verdadera" o no sesgada. + +Por otra parte, la TL **ajustada** puede ser utilizada para estimar la gravedad de una enfermedad infecciosa emergente de una forma más temprana durante una epidemia. + +Podemos explorar la *TL ajustada al retraso temporal* de forma temprana utilizando la función `cfr_rolling()` + +:::::::::::::::::::::: callout + +`cfr_rolling()` es una función que calcula automáticamente la TL en cada día del brote con los datos disponibles hasta ese día, lo que ahorra tiempo al usuario, ya que no hace falta calcular este parámetro manualmente para cada momento. + +:::::::::::::::::::::: + +```{r} +# Calculate the rolling daily naive CFR +# for all the 73 days in the Ebola dataset +rolling_cfr_naive <- cfr::cfr_rolling(data = ebola1976) + +utils::tail(rolling_cfr_naive) +``` + +```{r} +# Calculate the rolling daily delay-adjusted CFR +# for all the 73 days in the Ebola dataset +rolling_cfr_adjusted <- cfr::cfr_rolling( + data = ebola1976, + delay_density = function(x) density(onset_to_death_ebola, x) +) + +utils::tail(rolling_cfr_adjusted) +``` + +Con `utils::tail()` mostramos como los últimos valores estimados de la TL ajustada y sin ajustar tienen rangos superpuestos de intervalos de confianza del 95%. + +Ahora, visualicemos ambos resultados en una serie temporal. ¿Cómo se comportarían en tiempo real las estimaciones de TL ajustadas y sin ajustar? + +```{r, echo=TRUE, warning=FALSE, message=FALSE} +# get the latest delay-adjusted CFR +rolling_cfr_adjusted_end <- + rolling_cfr_adjusted %>% + dplyr::slice_tail() + +# bind by rows both output data frames +bind_rows( + rolling_cfr_naive %>% + mutate(method = "naive"), + rolling_cfr_adjusted %>% + mutate(method = "adjusted") +) %>% + # visualise both adjusted and unadjusted rolling estimates + ggplot() + + geom_ribbon( + aes( + date, + ymin = severity_low, + ymax = severity_high, + fill = method + ), + alpha = 0.2, show.legend = FALSE + ) + + geom_line( + aes(date, severity_estimate, colour = method) + ) + + geom_hline( + data = rolling_cfr_adjusted_end, + aes(yintercept = severity_estimate) + ) + + geom_hline( + data = rolling_cfr_adjusted_end, + aes(yintercept = severity_low), + lty = 2 + ) + + geom_hline( + data = rolling_cfr_adjusted_end, + aes(yintercept = severity_high), + lty = 2 + ) +``` + +La línea horizontal representa la TL ajustada al retraso temporal, estimada al final del brote. La línea punteada significa que la estimación tiene un intervalo de confianza del 95% (IC 95%). + +**Observa** que este cálculo ajustado al retraso temporal entre síntomas y muerte es especialmente útil cuando los únicos datos disponibles son *curvas epidémica de casos confirmados* (es decir, cuando no se dispone de datos individuales, especialmente durante la fase inicial de la epidemia). Cuando hay pocas muertes o ninguna, hay que hacer una suposición para la *distribución temporal* desde la aparición de síntomas hasta la muerte, por ejemplo, a partir de la literatura basada en brotes anteriores. [Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852) representan esto en las figuras con datos del brote de SARS en Hong Kong, 2003. + +:::::::::::::::::::::::::::::::::: spoiler + +### Caso de estudio: Brote de SARS, Hong Kong, 2003 + +Las figuras A y B muestran el número acumulado de casos y muertes por SRAS, y la figura C muestra las estimaciones observadas (sesgadas) del CFR en función del tiempo, es decir, el número acumulado de muertes sobre casos en el momento $t$. Debido al retraso temporal desde el inicio de los síntomas hasta la muerte, la estimación sesgada de la Tasa de Letalidad en el tiempo $t$ subestima el valor en las etapas finales del brote (es decir, 302/1755 = 17,2%). + +![Riesgo observado (sesgado) de letalidad confirmada del síndrome respiratorio agudo grave (SRAS) en Hong Kong, 2003. ([Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852))](fig/cfr-pone.0006852.g003-fig_abc.png) + +No obstante, incluso utilizando únicamente los datos observados para el periodo comprendido entre el 19 de marzo y el 2 de abril, `cfr_static()` puede obtener una predicción adecuada (Figura D), por ejemplo, la TL ajustada al retraso en el 27 de marzo es del 18,1% (IC del 95%: 10,5, 28,1). Se observa una sobreestimación en las fases muy tempranas de la epidemia, pero los límites de confianza del 95% en las fases posteriores incluyen la TL realizado (es decir, 17,2 %). + +![Determinación temprana del riesgo de letalidad confirmada ajustado al retraso del síndrome respiratorio agudo grave (SRAS) en Hong Kong, 2003. ([Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852))](fig/cfr-pone.0006852.g003-fig_d.png) + +:::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::: discussion + +### Interpretar la estimación de la TL en la fase inicial del brote + +Basándote en la figura anterior: + +- ¿Cuántos días hay entre el inicio del brote y la fecha en la que el intervalo de confianza de la *TL ajustada* se cruza con el intervalo de confianza de la *TL sin ajustar*? ¿Los intervalos se cruzan con la TL estimada al final del brote? + +Discusión: + +- ¿Cuáles son las implicaciones para la política de salud pública de tener una *TL ajustada por retraso temporal*? + +:::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::: hint + +Podemos utilizar la inspección visual o el análisis de los marcos de datos de salida. + +:::::::::::::::::::::: + +:::::::::::::::::::::: solution + +Hay casi un mes de diferencia. + +Nótese que la estimación tiene una incertidumbre considerable al principio de la serie temporal. Al cabo de dos semanas, la TL ajustada se aproxima a la estimación global de la TL al final del brote. + +¿Es este patrón similar al de otros brotes? Podemos utilizar los conjuntos de datos de los retos de este episodio. ¡Te invitamos a averiguarlo! + +:::::::::::::::::::::: + +:::::::::::::::::::::: discussion + +### Lista de verificación + +Con `{cfr}` estimamos la TL como la proporción de muertes entre **confirmadas** confirmados. + +Utilizando sólo el número de casos **confirmados** está claro que se pasarán por alto todos los casos que no busquen tratamiento médico o no sean notificados, así como todos los casos asintomáticos. Esto significa que la estimación de la TL es superior a la proporción de muertes entre los infectados. + +:::::::::::::::::::::: + +::::::::::::::::::::::::::: solution + +### ¿Por qué difieren la TL sin ajustar y la ajustada al retraso temporal? + +`{cfr}` tiene como objetivo obtener un estimador insesgado "mucho antes" de observar el curso completo del brote. Para ello `{cfr}` utiliza el factor de subestimación $u_{t}$ para estimar la TL sin sesgo $p_{t}$ , utilizando métodos de máxima verosimilitud, dado el *proceso de muestreo* definido por [Nishiura et al., 2009](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0006852). + +::::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solution + +### ¿Qué es el proceso de muestreo? + +![La población de casos confirmados y el proceso de muestreo para estimar la TL sin sesgo durante el transcurso de un brote. ([Nishiura et al., 2009](https://doi.org/10.1371/journal.pone.0006852.g001))](fig/cfr-pone.0006852.g001.png) + +En *datos agregados de incidencia* en el momento $t$ conocemos el número acumulado de casos confirmados y muertes, $C_{t}$ y $D_{t}$ y deseamos estimar la TL sin sesgo $\pi$ mediante el factor de subestimación $u_{t}$. + +Si conociéramos el factor de subestimación $u_{t}$ podríamos especificar el tamaño de la población de casos confirmados que ya no corren riesgo ($u_{t}C_{t}$, **sombreado**), aunque no sabemos qué individuos supervivientes pertenecen a este grupo. Una proporción $\pi$ de los del grupo de casos aún en riesgo (tamaño $(1- u_{t})C_{t}$, **sin sombrear**) se espera que muera. + +Ya que cada caso que deja de estar en riesgo tiene una probabilidad independiente de morir, $\pi$ el número de muertes, $D_{t}$ es una muestra de una distribución binomial con tamaño de muestra $u_{t}C_{t}$ y probabilidad de morir $p_{t}$ = $\pi$. + +Esto se representa mediante la siguiente función de verosimilitud para obtener la estimación de máxima verosimilitud de la TL sin sesgo $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)}, +$$ + +Esta estimación la realiza la función interna `?cfr:::estimate_severity()`. + +:::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solution + +### Limitaciones + +- La TL ajustada al retraso temporal no aborda todas las fuentes de error en los datos, como el infradiagnóstico de individuos infectados. + +:::::::::::::::::::::::::: + +## Desafíos + +::::::::::::::::: callout + +### Los datos agregados difieren de los listados de casos individuales + +Los datos de incidencia *agregados* difieren de **lista** en los que cada observación contiene datos a nivel individual. + +```{r} +outbreaks::ebola_sierraleone_2014 %>% as_tibble() +``` + +::::::::::::::::: + +:::::::::::::::::::::::::::::::::: challenge + +### Utiliza el paquete incidence2 para reordenar tus datos + +Usando el paquete`{outbreaks}`, carga el listado de casos "MERS" incluido en el objeto `mers_korea_2015`. + +Reordena el listado de casos para que tenga la estructura de entrada requerida por el paquete `{cfr}`. + +Estima el HFR ajustado al retardo utilizando el retardo de distribución correspondiente. + +::::::::::::::::: hint + +**¿Cómo reorganizar mis datos de entrada?** + +Reorganizar los datos de entrada para el análisis de datos puede llevarte la mayor parte del tiempo. Para estar listo para el análisis con *datos de incidencia agregados* te animamos a utilizar `{incidence2}` ¡! + +Primero, en la viñeta [Inicio](https://www.reconverse.org/incidence2/articles/incidence2.html) de `{incidence2}` explora cómo utilizar `date_index` al leer un listado de casos con fechas en varias columnas. + +A continuación, consulta la viñeta [Manejo de datos de `{incidence2}`](https://epiverse-trace.github.io/cfr/articles/data_from_incidence2.html) del paquete `{cfr}`, sobre cómo utilizar la función `cfr::prepare_data()` con los objetos incidence2. + + + +::::::::::::::::: + +::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +# Carga los paquetes +library(cfr) +library(epiparameter) +library(incidence2) +library(outbreaks) +library(tidyverse) + +# Accede a la distribución de retrasos temporales +mers_delay <- + epidist_db( + disease = "mers", + epi_dist = "onset to death", + single_epidist = TRUE + ) + +# Lee el listado de casos +mers_korea_2015$linelist %>% + as_tibble() %>% + select(starts_with("dt_")) + +# Usa {incidence2} para contabilizar la incidencia diaria +mers_incidence <- mers_korea_2015$linelist %>% + # convertir a un objeto incidence2 + incidence(date_index = c("dt_onset", "dt_death")) %>% + # completa las fechas de la primera a la última + incidence2::complete_dates() + +# Explora los resultados de incidence2 +mers_incidence + +# Prepara los datos {incidence2} para usarlos en {cfr} +mers_incidence %>% + prepare_data( + cases_variable = "dt_onset", + deaths_variable = "dt_death" + ) + +# Estima la TL ajustada a retrasos temporales +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 + +### Heterogeneidad de la gravedad + +La TL puede diferir entre poblaciones (por ejemplo, edad, espacio, tratamiento); cuantificar estas heterogeneidades puede ayudar a dirigir los recursos adecuadamente y a comparar distintos regímenes asistenciales ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +Utiliza la base de datos `cfr::covid_data` para estimar una TL ajustada al retraso temporal estratificada por países. + +::::::::::::::::::::::::: hint + +Una forma de hacer un *análisis estratificado* es aplicar un modelo a datos anidados. Esta [viñeta `{tidyr}`](https://tidyr.tidyverse.org/articles/nest.html#nested-data-and-models) te muestra cómo aplicar la función `group_by()` + `nest()` a los datos anidados, y luego `mutate()` + `map()` para aplicar el modelo. + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: solution + +```{r, message=FALSE, warning=FALSE} +library(cfr) +library(epiparameter) +library(tidyverse) + +covid_data %>% glimpse() + +delay_onset_death <- + epidist_db( + disease = "covid", + epi_dist = "onset to death", + single_epidist = TRUE + ) + +covid_data %>% + group_by(country) %>% + nest() %>% + mutate( + temp = + map( + .x = data, + .f = cfr::cfr_static, + delay_density = function(x) density(delay_onset_death, x) + ) + ) %>% + unnest(cols = temp) +``` + +¡Estupendo! Ahora puedes utilizar un código similar para cualquier otro análisis estratificado, como la edad, las regiones u otros. + +Pero, ¿cómo podemos interpretar que existe una variabilidad de gravedad por países a partir del mismo patógeno diagnosticado? + +Factores locales como la capacidad de análisis, la definición de caso y el régimen de muestreo pueden afectar a la notificación de casos y muertes, afectando así a la comprobación de los casos. Echa un vistazo a la viñeta [Estimar la proporción de casos que se determinan durante un brote](https://epiverse-trace.github.io/cfr/articles/estimate_ascertainment.html) del paquete `{cfr}` para más información ¡! + +::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +## Apéndice + +El paquete `{cfr}` tiene una función llamada `cfr_time_varying()` con una funcionalidad distinta de `cfr_rolling()`. + +::::::::::::::::: callout + +### ¿Cuándo utilizar cfr\_rolling()? + +**cfr\_rolling()** muestra la TL estimada en cada día del brote, dado que los datos futuros sobre casos y muertes no están disponibles en ese momento. El valor final de *cfr\_rolling()* estimado es idéntico al de *cfr\_static()* con los mismos datos. + +Recuerda, como se muestra arriba *cfr\_rolling()* es útil para obtener estimaciones de la TL en las primeras fases y comprobar si la estimación de la TL de un brote se ha estabilizado. Así, *cfr\_rolling()* no es sensible a la duración ni al tamaño de la epidemia. + +::::::::::::::::: + +::::::::::::::::: callout + +### ¿Cuándo utilizar cfr\_time\_varying()? + +Por otra parte, **cfr\_time\_varying()** calcula la TL a lo largo de una ventana móvil y ayuda a comprender los cambios en la TL debidos a cambios en la epidemia, por ejemplo, debidos a una nueva variante o a una mayor inmunidad por vacunación. + +Sin embargo, *cfr\_time\_variying()* es sensible a la incertidumbre del muestreo. Por tanto, es sensible al tamaño del brote. Cuanto mayor sea el número de casos con resultados esperados en un día determinado, más estimaciones razonables de la TL variable en el tiempo obtendremos. + +Por ejemplo, con 100 casos, la estimación del riesgo de mortalidad tendrá, a grandes rasgos, un intervalo de confianza del 95% ±10% de la estimación media (IC binomial). Por tanto, si tenemos >100 casos con resultados esperados *en un día determinado* podemos obtener estimaciones razonables de la TL variable en el tiempo. Pero si sólo tenemos >100 casos *a lo largo de toda la epidemia* probablemente tengamos que basarnos en **cfr\_rolling()** que utiliza los datos acumulados. + +Te invitamos a leer esta [viñeta sobre `cfr_time_varying()`](https://epiverse-trace.github.io/cfr/articles/estimate_time_varying_severity.html). + +::::::::::::::::: + +:::::::::::::::::::::::::::::::: discussion + +### Más medidas de gravedad + +Supongamos que necesitamos evaluar la gravedad clínica de la epidemia en un contexto distinto al de los datos de vigilancia, como la gravedad entre los casos que llegan a los hospitales o los casos que recogiste en una encuesta serológica representativa. + +Utilizando `{cfr}` podemos cambiar las entradas para el numerador **casos** (`cases`) y el denominador **muertes** (`deaths`) para estimar más medidas de gravedad, como el Riesgo de Fatalidad por Infección (RFI) o el Riesgo de Fatalidad por Hospitalización (RFH). Podemos seguir esta analogía: + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::: solution + +### Riesgo de mortalidad por infección y hospitalización + +Si para la una *Tasa de letalidad* (TL o CFR en inglés), exigimos: + +- *Incidencia* de casos y muertes, con una: +- Distribución de retraso temporal entre casos y muertes (o una aproximación cercana, como el tiempo entre inicio de los síntomas y la muerte). + +Entonces, el *Riesgo de Fatalidad por Infección* (IFR, por sus siglas en inglés) requiere: + +- Incidencia de *infecciones* y muertes, con una: +- Distribución de retraso temporal desde la infección hasta la muerte (o una aproximación cercana). + +Del mismo modo, el *Riesgo de Fatalidad por Hospitalización* (HFR) requiere: + +- Incidencia de *hospitalizaciones* y muertes, y una: +- Distribución del retraso temporal entre la hospitalización y la muerte. + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::::: solution + +### Fuentes de datos para más medidas de gravedad + +[Yang y otros, 2020](https://www.nature.com/articles/s41467-020-19238-2/figures/1) resume diferentes definiciones y fuentes de datos: + +![Niveles de gravedad de las infecciones por SRAS-CoV-2 y parámetros de interés. Se supone que cada nivel es un subconjunto del nivel inferior.](fig/cfr-s41467-020-19238-2-fig_a.png) + +- sCFR riesgo sintomático de letalidad, +- sCHR riesgo sintomático de hospitalización, +- mCFR riesgo de caso-fatalidad médicamente atendido, +- mCHR riesgo de hospitalización de casos atendidos médicamente, +- HFR riesgo de hospitalización-fatalidad. + +![Diagrama esquemático de los análisis de referencia. Las flechas rojas, azules y verdes indican el flujo de datos desde los casos confirmados por laboratorio de la vigilancia pasiva, los casos diagnosticados clínicamente y los casos confirmados por laboratorio de los cribados activos.](fig/cfr-s41467-020-19238-2-fig_b.png) + +:::::::::::::::::::::::::::: + +:::::::::::::::::::: discussion + +Basándote en tu experiencia: + +- Comparte algún brote anterior en el que hayas participado en su respuesta. + +Responde a estas preguntas: + +- ¿Cómo evaluaste la gravedad clínica del brote? +- ¿Cuáles fueron las principales fuentes de sesgo? +- ¿Qué hiciste para tener en cuenta el sesgo identificado? +- ¿Qué análisis complementario harías para resolver el sesgo? + +:::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: keypoints + +- Utiliza `{cfr}` para estimar la gravedad + +- Utiliza `cfr_static()` para estimar la TL global con los últimos datos disponibles. + +- Utiliza `cfr_rolling()` para mostrar cuál sería la TL estimada en cada día del brote. + +- Utiliza la `delay_density` para ajustar la TL según la distribución de retrasos correspondiente. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +