diff --git a/config.yaml b/config.yaml index fca02e50..1e8b76f1 100644 --- a/config.yaml +++ b/config.yaml @@ -59,6 +59,8 @@ contact: 'andree.valle-campos@lshtm.ac.uk' #FIXME # Order of episodes in your lesson episodes: +- quantify-transmissibility.Rmd +- create-forecast.Rmd - simulating-transmission.Rmd - model-choices.Rmd - modelling-interventions.Rmd diff --git a/episodes/create-forecast.Rmd b/episodes/create-forecast.Rmd new file mode 100644 index 00000000..48c85e5f --- /dev/null +++ b/episodes/create-forecast.Rmd @@ -0,0 +1,348 @@ +--- +title: 'Create a short-term forecast' +teaching: 30 +exercises: 30 +editor_options: + chunk_output_type: inline +--- + +```{r setup, echo = FALSE, warning = FALSE, message = FALSE} +library(EpiNow2) +withr::local_options(list(mc.cores = 4)) +``` + + +:::::::::::::::::::::::::::::::::::::: questions + +- How do I create short-term forecasts from case data? +- How do I account for incomplete reporting in forecasts? + + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Learn how to make forecasts of cases using R package `EpiNow2` +- Learn how to include an observation process in estimation + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Prerequisites + ++ Complete tutorial [Quantifying transmission](../episodes/quantify-transmissibility.md) + +Learners should familiarise themselves with following concept dependencies before working through this tutorial: + +**Statistics** : probability distributions, principle of Bayesian analysis. + +**Epidemic theory** : Effective reproduction number. + +::::::::::::::::::::::::::::::::: + +## Introduction + +Given case data, we can create estimates of the current and future number of cases by accounting for both delays in reporting and under reporting. To make statements about the future, we need to make an assumption of how observations up to today are related to what we expect to happen in the future. The simplest way of doing so is to assume "no change", i.e. the reproduction number remains the same in the future as last observed. In this tutorial we will create short-term forecasts by assuming the reproduction number will remain the same as it was estimated to be on the final date for which data was available. + +## Create a short-term forecast + +The function `epinow()` described in the previous tutorial is a wrapper for the function `estimate_infections()` used to estimate cases by date of infection. Using the same code in the previous tutorial we can extract the short-term forecast using: + +```{r, echo = FALSE} +cases <- aggregate( + cases_new ~ date, + data = incidence2::covidregionaldataUK[, c("date", "cases_new")], + FUN = sum +) +colnames(cases) <- c("date", "confirm") +rt_log_mean <- convert_to_logmean(2, 1) +rt_log_sd <- convert_to_logsd(2, 1) + +incubation_period_fixed <- dist_spec( + mean = 4, sd = 2, + max = 20, distribution = "gamma" +) + +log_mean <- convert_to_logmean(2, 1) +log_sd <- convert_to_logsd(2, 1) +reporting_delay_fixed <- dist_spec( + mean = log_mean, sd = log_sd, + max = 10, distribution = "lognormal" +) + +generation_time_fixed <- dist_spec( + mean = 3.6, sd = 3.1, + max = 20, distribution = "lognormal" +) +``` + + +```{r, message = FALSE, eval = TRUE} +reported_cases <- cases[1:90, ] +estimates <- epinow( + reported_cases = reported_cases, + generation_time = generation_time_opts(generation_time_fixed), + delays = delay_opts(incubation_period_fixed + reporting_delay_fixed), + rt = rt_opts(prior = list(mean = rt_log_mean, sd = rt_log_sd)) +) +``` + + +We can visualise the estimates of the effective reproduction number and the estimated number of cases using `plot()`. The estimates are split into three categories: + ++ **Estimate** (green): utilises all data, + ++ **Estimate based on partial data** (orange): estimates that are based less data are therefore more uncertain, + ++ **Forecast** (purple): forecasts into the future. + + +```{r} +plot(estimates) +``` + + +::::::::::::::::::::::::::::::::::::: callout +### Forecasting with estimates of $R_t$ + +By default, the short-term forecasts are created using the latest estimate of the reproduction number $R_t$. As this estimate is based on partial data, it has considerable uncertainty. + +The reproduction number that is projected into the future can be changed to a less recent estimate based on more data using `rt_opts()`: + +```{r, eval = FALSE} +rt_opts(future = "estimate") +``` + +The result will be less uncertain forecasts (as they are based on $R_t$ with a narrower uncertainty interval) but the forecasts will be based on less recent estimates of $R_t$ and assume no change since then. + +Additionally, there is the option to project the value of $R_t$ into the future using a generic model by setting `future = "project"`. As this option uses a model to forecast the value of $R_t$, the result will be forecasts that are more uncertain than `estimate`, for an example [see here](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections_options.html#projecting-the-reproduction-number-with-the-gaussian-process). + +:::::::::::::::::::::::::::::::::::::::::::::::: + + +### Incomplete observations + +In the previous tutorial we accounted for delays in reporting. In `EpiNow2` we also can account for incomplete observations as in reality, 100% of cases are not reported. + +We will pass another input into `epinow()` called `obs` to define an observation model. The format of `obs` must be the `obs_opt()` function (see `?EpiNow2::obs_opts` for more detail). + +Let's say we believe the COVID-19 outbreak data from the previous tutorial do not include all reported cases. We believe that we only observe 40% of cases. To specify this in the observation model, we must pass a scaling factor with a mean and standard deviation. If we assume that 40% of cases are in the case data (with standard deviation 1%), then we specify the `scale` input to `obs_opts()` as follows: + +```{r} +obs_scale <- list(mean = 0.4, sd = 0.01) +``` + +To run the inference framework with this observation process, we add `obs = obs_opts(scale = obs_scale)` to the input arguments of `epinow()`: + +```{r, message = FALSE, eval = TRUE} +obs_scale <- list(mean = 0.4, sd = 0.01) +reported_cases <- cases[1:90, ] +estimates <- epinow( + reported_cases = reported_cases, + generation_time = generation_time_opts(generation_time_fixed), + delays = delay_opts(incubation_period_fixed + reporting_delay_fixed), + rt = rt_opts(prior = list(mean = rt_log_mean, sd = rt_log_sd)), + obs = obs_opts(scale = obs_scale) +) +summary(estimates) +``` + + +The estimates of transmission measures such as the effective reproduction number and rate of growth are similar (or the same in value) compared to when we didn't account for incomplete observations (see previous tutorial). However the number of new confirmed cases by infection date has changed substantially in magnitude to reflect the assumption that only 40% of cases are in the data set. + +We can also change the default distribution from Negative Binomial to Poisson, remove the default week effect and more. See `?EpiNow2::obs_opts` for more detail. + + +## Forecast secondary observations + +`EpiNow2` also has the ability to estimate and forecast secondary observations e.g. deaths, hospitalisations from a primary observation e.g. cases. Here we will illustrate how to forecast the number of deaths arising from observed cases of COVID-19 in the early stages of the UK outbreak. + +First, we must format our data to have the following columns: + ++ `date` : the date (as a date object see `?is.Date()`), ++ `primary` : number of primary observations on that date, in this example **cases**, ++ `secondary` : number of secondary observations date, in this example **deaths**. + +```{r} +reported_cases_deaths <- aggregate( + cbind(cases_new, deaths_new) ~ date, + data = + incidence2::covidregionaldataUK[, c("date", "cases_new", "deaths_new")], + FUN = sum +) +colnames(reported_cases_deaths) <- c("date", "primary", "secondary") +``` + + +Using the first 30 days of data on cases and deaths, we will estimate the relationship between the primary and secondary observations using `estimate_secondary()`, then forecast future deaths using `forecast_secondary()`. For detail on the model see the [model documentation](https://epiforecasts.io/EpiNow2/dev/articles/estimate_secondary.html). + +We must specify the type of observation using `type` in `secondary_opts()`, options include: + ++ "incidence" : secondary observations arise from previous primary observations, i.e. deaths arising from recorded cases. ++ "prevalence" : secondary observations arise from a combination current primary observations and past secondary observations, i.e. hospital bed usage arising from current hospital admissions and past hospital bed usage. + +In this example we specify `secondary_opts(type = "incidence")`. See `?EpiNow2::secondary_opts` for more detail). + +The final key input is the delay distribution between the primary and secondary observations. Here this is the delay between case report and death, we assume this follows a gamma distribution with mean of 14 days and standard deviation of 5 days. Using `dist_spec()` we specify a fixed gamma distribution. + +There are further function inputs to `estimate_secondary()` which can be specified, including adding an observation process, see `?EpiNow2::estimate_secondary` for detail on the options. + +To find the model fit between cases and deaths : +```{r} +estimate_cases_to_deaths <- estimate_secondary( + reports = reported_cases_deaths[1:30, ], + secondary = secondary_opts(type = "incidence"), + delays = delay_opts(dist_spec( + mean = 14, sd = 5, + max = 30, distribution = "gamma" + )) +) +``` + + +::::::::::::::::::::::::::::::::::::: callout +### Be cautious of timescale + +In the early stages of an outbreak there can be substantial changes in testing and reporting. If there are testing changes from one month to another, then there will be a bias in the model fit. Therefore, you should be cautious of the time-scale of data used in the model fit and forecast. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +We plot the model fit (shaded ribbons) with the secondary observations (bar plot) and primary observations (dotted line) as follows: + +```{r} +plot(estimate_cases_to_deaths, primary = TRUE) +``` + +To use this model fit to forecast deaths, we pass a data frame consisting of the primary observation (cases) for dates not used in the model fit. + +*Note : in this tutorial we are using data where we know the deaths and cases, so we create a data frame by extracting the cases. But in practice, this would be a different data set consisting of cases only.* +```{r} +cases_to_forecast <- reported_cases_deaths[31:60, c("date", "primary")] +colnames(cases_to_forecast) <- c("date", "value") +``` + +To forecast, we use the model fit `estimate_cases_to_deaths`: + +```{r} +deaths_forecast <- forecast_secondary( + estimate = estimate_cases_to_deaths, + primary = cases_to_forecast +) +plot(deaths_forecast) +``` + +The plot shows the forecast secondary observations (deaths) over the dates which we have recorded cases for. +It is also possible to forecast deaths using forecast cases, here you would specify `primary` as the `estimates` output from `estimate_infections()`. + + +## Challenge : Ebola outbreak analysis + +::::::::::::::::::::::::::::::::::::: challenge + +Download the file [ebola_cases.csv](data/ebola_cases.csv) and read it into R. The simulated data consists of the date of symptom onset and number of confirmed cases of the early stages of the Ebola outbreak in Sierra Leone in 2014. + +Using the first 3 months (120 days) of data: + +1. Estimate of cases increasing or decreasing on day 120 of the outbreak (Hint: Find the effective reproduction number and growth rate on day 120) +2. Create a two week forecast of number of cases + +You can use the following parameter values for the delay distribution(s) and generation time distribution. + ++ Incubation period : Log normal$(2.487,0.330)$ ([Eichner et al. 2011](https://doi.org/10.1016/j.phrp.2011.04.001) via `{epiparameter}`) ++ Generation time : Gamma$(15.3, 10.1)$ ([WHO Ebola Response Team 2014](https://www.nejm.org/doi/full/10.1056/NEJMoa1411100)) + +You may include some uncertainty around the mean and standard deviation of these distributions. + +::::::::::::::::: hint + +### HINT : data format + +Ensure the data is in the correct format : + ++ `date` : the date (as a date object see `?is.Date()`), ++ `confirm` : number of confirmed cases on that date. + + +:::::::::::::::::::::: + + +::::::::::::::::: solution + +### SOLUTION + +To estimate the effective reproduction number and growth rate, we will use the function `epinow()`. + +As the data consists of date of symptom onset, we only need to specify a delay distribution for the incubation period and the generation time. + +We specify the distributions with some uncertainty around the mean and standard deviation of the log normal distribution for the incubation period and the Gamma distribution for the generation time. + +```{r,eval=TRUE,echo=TRUE} +ebola_incubation_period <- dist_spec( + mean = 2.487, sd = 0.330, + mean_sd = 0.5, sd_sd = 0.5, + max = 20, distribution = "lognormal" +) + +ebola_generation_time <- dist_spec( + mean = 15.3, sd = 10.1, + mean_sd = 0.5, sd_sd = 0.5, + max = 30, distribution = "gamma" +) +``` + +As we want to also create a two week forecast, we specify `horizon = 14` to forecast 14 days instead of the default 7 days. + +```{r, eval=TRUE,echo=FALSE} +# read data from the tutorial repository R project +ebola_cases <- + read.csv(file.path("data", "ebola_cases.csv")) +``` + +```{r,eval=FALSE,echo=TRUE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +ebola_cases <- + read.csv(here::here("data", "raw-data", "ebola_cases.csv")) +``` + +```{r,eval=TRUE,echo=TRUE, message = FALSE} +# format date column +ebola_cases$date <- as.Date(ebola_cases$date) + +ebola_estimates <- epinow( + reported_cases = ebola_cases[1:120, ], # first 3 months of data only + generation_time = generation_time_opts(ebola_generation_time), + delays = delay_opts(ebola_incubation_period), + # horizon needs to be 14 days to create two week forecast (default is 7 days) + horizon = 14 +) + +summary(ebola_estimates) +``` + +The effective reproduction number $R_t$ estimate (on the last date of the data) is `r summary(ebola_estimates)[measure=="Effective reproduction no."]$estimate`. The exponential growth rate of case numbers is `r summary(ebola_estimates)[measure=="Rate of growth"]$estimate`. + +Visualize the estimates: + +```{r,eval=FALSE,echo=TRUE} +plot(ebola_estimates) +``` + +::::::::::::::::::::::::::: + + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Summary + +`EpiNow2` can be used to create short term forecasts and to estimate the relationship between different outcomes. There are a range of model options that can be implemented for different analysis, including adding an observational process to account for incomplete reporting. See the [vignette](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections_options.html) for more details on different model options in `EpiNow2` that aren't covered in these tutorials. + + +::::::::::::::::::::::::::::::::::::: keypoints + +- We can create short-term forecasts by making assumptions about the future behaviour of the reproduction number +- Incomplete case reporting can be accounted for in estimates + + +:::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/quantify-transmissibility.Rmd b/episodes/quantify-transmissibility.Rmd new file mode 100644 index 00000000..e6073b07 --- /dev/null +++ b/episodes/quantify-transmissibility.Rmd @@ -0,0 +1,416 @@ +--- +title: 'Quantifying transmission' +teaching: 30 +exercises: 0 +--- + +```{r setup, echo = FALSE, warning = FALSE, message = FALSE} +library(EpiNow2) +library(ggplot2) +withr::local_options(list(mc.cores = 4)) +``` + +:::::::::::::::::::::::::::::::::::::: questions + +- How can I estimate key transmission metrics from a time series of case data? +- How can I quantify geographical heterogeneity in these metrics? + + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Learn how to estimate transmission metrics from a time series of case data using the R package `EpiNow2` + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Prerequisites + +Learners should familiarise themselves with following concept dependencies before working through this tutorial: + +**Statistics** : probability distributions, principle of Bayesian analysis. + +**Epidemic theory** : Effective reproduction number. + +::::::::::::::::::::::::::::::::: + + + +::::::::::::::::::::::::::::::::::::: callout +### Reminder: the Effective Reproduction Number, $R_t$ + +The [basic reproduction number](../learners/reference.md#basic), $R_0$, is the average number of cases caused by one infectious individual in a entirely susceptible population. + +But in an ongoing outbreak, the population does not remain entirely susceptible as those that recover from infection are typically immune. Moreover, there can be changes in behaviour or other factors that affect transmission. When we are interested in monitoring changes in transmission we are therefore more interested in the value of the **effective reproduction number**, $R_t$, the average number of cases caused by one infectious individual in the population at time $t$. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + +## Introduction + +Quantifying transmission metrics at the start of an outbreak can give important information on the strength of transmission (reproduction number) and the speed of transmission ([growth rate](../learners/reference.md#growth), doubling/halving time). To estimate these key metrics using case data we must account for delays between the date of infections and date of reported cases. In an outbreak situation, data are usually available on reported dates only, therefore we must use estimation methods to account for these delays when trying to understand changes in transmission over time. + +In the next tutorials we will focus on how to implement the functions in `{EpiNow2}` to estimate transmission metrics of case data. We will not cover the theoretical background of the models or inference framework, for details on these concepts see the [vignette](https://epiforecasts.io/EpiNow2/dev/articles/estimate_infections.html). +For more details on the distinction between speed and strength of transmission and implications for control, see [Dushoff & Park, 2021](https://royalsocietypublishing.org/doi/full/10.1098/rspb.2020.1556). + + +::::::::::::::::::::::::::::::::::::: callout +### Bayesian inference + +The R package `EpiNow2` uses a [Bayesian inference](../learners/reference.md#bayesian) framework to estimate reproduction numbers and infection times based on reporting dates. + +In Bayesian inference, we use prior knowledge (prior distributions) with data (in a likelihood function) to find the posterior probability. + +

Posterior probability $\propto$ likelihood $\times$ prior probability +

+ +:::::::::::::::::::::::::::::::::::::::::::::::: + + +The first step is to load the `{EpiNow2}` package : + +```{r, eval = FALSE} +library(EpiNow2) +``` + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: instructor + +This tutorial illustrates the usage of `epinow()` to estimate the time-varying reproduction number and infection times. Learners should understand the necessary inputs to the model and the limitations of the model output. + +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +## Delay distributions and case data +### Case data + +To illustrate the functions of `EpiNow2` we will use outbreak data of the start of the COVID-19 pandemic from the United Kingdom. The data are available in the R package `{incidence2}`. + +```{r} +head(incidence2::covidregionaldataUK) +``` + +To use the data, we must format the data to have two columns: + ++ `date` : the date (as a date object see `?is.Date()`), ++ `confirm` : number of confirmed cases on that date. + +```{r} +cases <- aggregate( + cases_new ~ date, + data = incidence2::covidregionaldataUK[, c("date", "cases_new")], + FUN = sum +) +colnames(cases) <- c("date", "confirm") +``` + + +There are case data available for `r dim(cases)[1]` days, but in an outbreak situation it is likely we would only have access to the beginning of this data set. Therefore we assume we only have the first 90 days of this data. + +```{r echo = FALSE} +ggplot(cases[1:90, ], aes(x = date, y = confirm)) + + geom_col() + + theme_grey( + base_size = 15 + ) +``` + + + +### Delay distributions +We assume there are delays from the time of infection until the time a case is reported. We specify these delays as distributions to account for the uncertainty in individual level differences. The delay can consist of multiple types of delays/processes. A typical delay from time of infection to case reporting may consist of : + +

**time from infection to symptom onset** (the [incubation period](../learners/reference.md#incubation)) + **time from symptom onset to case notification** (the reporting time) +.

+ +The delay distribution for each of these processes can either estimated from data or obtained from the literature. We can express uncertainty about what the correct parameters of the distributions by assuming the distributions have **fixed** parameters or whether they have **variable** parameters. To understand the difference between **fixed** and **variable** distributions, let's consider the incubation period. + +::::::::::::::::::::::::::::::::::::: callout +### Delays and data +The number of delays and type of delay is a flexible input that depends on the data. The examples below highlight how the delays can be specified for different data sources: + +
+ +| Data source | Delay(s) | +| ------------- |-------------| +|Time of case report |Incubation period + time from symptom onset to case notification | +|Time of hospitalisation |Incubation period + time from symptom onset to hospitalisation | +|Time of symptom onset |Incubation period | + +
+ + +:::::::::::::::::::::::::::::::::::::::::::::::: + + + +#### Incubation period distribution + +The distribution of incubation period can usually be obtained from the literature. The package `{epiparameter}` contains a library of epidemiological parameters for different diseases obtained from the literature. + +We specify a (fixed) gamma distribution with mean $\mu = 4$ and standard deviation $\sigma^2= 2$ (shape = $4$, scale = $1$) using the function `dist_spec()` as follows: + +```{r} +incubation_period_fixed <- dist_spec( + mean = 4, sd = 2, + max = 20, distribution = "gamma" +) +incubation_period_fixed +``` + +The argument `max` is the maximum value the distribution can take, in this example 20 days. + +::::::::::::::::::::::::::::::::::::: callout +### Why a gamma distrubution? + +The incubation period has to be positive in value. Therefore we must specific a distribution in `dist_spec` which is for positive values only. + +`dist_spec()` supports log normal and gamma distributions, which are distributions for positive values only. + +For all types of delay, we will need to use distributions for positive values only - we don't want to include delays of negative days in our analysis! + +:::::::::::::::::::::::::::::::::::::::::::::::: + + + +#### Including distribution uncertainty + +To specify a **variable** distribution, we include uncertainty around the mean $\mu$ and standard deviation $\sigma^2$ of our gamma distribution. If our incubation period distribution has a mean $\mu$ and standard deviation $\sigma^2$, then we assume the mean ($\mu$) follows a Normal distribution with standard deviation $\sigma_{\mu}^2$: + +$$\mbox{Normal}(\mu,\sigma_{\mu}^2)$$ + +and a standard deviation ($\sigma^2$) follows a Normal distribution with standard deviation $\sigma_{\sigma^2}^2$: + +$$\mbox{Normal}(\sigma^2,\sigma_{\sigma^2}^2).$$ + +We specify this using `dist_spec` with the additional arguments `mean_sd` ($\sigma_{\mu}^2$) and `sd_sd` ($\sigma_{\sigma^2}^2$). + +```{r} +incubation_period_variable <- dist_spec( + mean = 4, sd = 2, + mean_sd = 0.5, sd_sd = 0.5, + max = 20, distribution = "gamma" +) +incubation_period_variable +``` + + + +#### Reporting delays + +After the incubation period, there will be an additional delay of time from symptom onset to case notification: the reporting delay. We can specify this as a fixed or variable distribution, or estimate a distribution from data. + +When specifying a distribution, it is useful to visualise the probability density to see the peak and spread of the distribution, in this case we will use a log normal distribution. We can use the functions `convert_to_logmean()` and `convert_to_logsd()` to convert the mean and standard deviation of a normal distribution to that of a log normal distribution. + +If we want to assume that the mean reporting delay is 2 days (with a standard deviation of 1 day), the log normal distribution will look like: + +```{r} +log_mean <- convert_to_logmean(2, 1) +log_sd <- convert_to_logsd(2, 1) +x <- seq(from = 0, to = 10, length = 1000) +df <- data.frame(x = x, density = dlnorm(x, meanlog = log_mean, sdlog = log_sd)) +ggplot(df) + + geom_line( + aes(x, density) + ) + + theme_grey( + base_size = 15 + ) +``` + +Using the mean and standard deviation for the log normal distribution, we can specify a fixed or variable distribution using `dist_spec()` as before: + +```{r} +reporting_delay_variable <- dist_spec( + mean = log_mean, sd = log_sd, + mean_sd = 0.5, sd_sd = 0.5, + max = 10, distribution = "lognormal" +) +``` + +If data is available on the time between symptom onset and reporting, we can use the function `estimate_delay()` to estimate a log normal distribution from a vector of delays. The code below illustrates how to use `estimate_delay()` with synthetic delay data. + +```{r, eval = FALSE } +delay_data <- rlnorm(500, log(5), 1) # synthetic delay data +reporting_delay <- estimate_delay( + delay_data, + samples = 1000, + bootstraps = 10 +) +``` + + +#### Generation time + +We also must specify a distribution for the generation time. Here we will use a log normal distribution with mean 3.6 and standard deviation 3.1 ([Ganyani et al. 2020](https://doi.org/10.2807/1560-7917.ES.2020.25.17.2000257)). + + +```{r} +generation_time_variable <- dist_spec( + mean = 3.6, sd = 3.1, + mean_sd = 0.5, sd_sd = 0.5, + max = 20, distribution = "lognormal" +) +``` + + +## Finding estimates + +The function `epinow()` is a wrapper for the function `estimate_infections()` used to estimate cases by date of infection. The generation time distribution and delay distributions must be passed using the functions ` generation_time_opts()` and `delay_opts()` respectively. + +There are numerous other inputs that can be passed to `epinow()`, see `EpiNow2::?epinow()` for more detail. +One optional input is to specify a log normal prior for the effective reproduction number $R_t$ at the start of the outbreak. We specify a mean and standard deviation as arguments of `prior` within `rt_opts()`: + +```{r, eval = FALSE} +rt_log_mean <- convert_to_logmean(2, 1) +rt_log_sd <- convert_to_logsd(2, 1) +rt <- rt_opts(prior = list(mean = rt_log_mean, sd = rt_log_sd)) +``` + +::::::::::::::::::::::::::::::::::::: callout +### Bayesian inference using Stan + +The Bayesian inference is performed using MCMC methods with the program [Stan](https://mc-stan.org/). There are a number of default inputs to the Stan functions including the number of chains and number of samples per chain (see `?EpiNow2::stan_opts()`). + +To reduce computation time, we can run chains in parallel. To do this, we must set the number of cores to be used. By default, 4 MCMC chains are run (see `stan_opts()$chains`), so we can set an equal number of cores to be used in parallel as follows: + +```{r} +withr::with_options(mc.cores = 4) +``` + +To find the maximum number of available of cores on your machine, use `parallel::detectCores()`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +```{r, echo = FALSE} +rt_log_mean <- convert_to_logmean(2, 1) +rt_log_sd <- convert_to_logsd(2, 1) + +incubation_period_fixed <- dist_spec( + mean = 4, sd = 2, + max = 20, distribution = "gamma" +) + +log_mean <- convert_to_logmean(2, 1) +log_sd <- convert_to_logsd(2, 1) +reporting_delay_fixed <- dist_spec( + mean = log_mean, sd = log_sd, + max = 10, distribution = "lognormal" +) + +generation_time_fixed <- dist_spec( + mean = 3.6, sd = 3.1, + max = 20, distribution = "lognormal" +) +``` + +*Note : in the code below fixed distributions are used instead of variable. This is to speed up computation time. It is generally recommended to use variable distributions that account for additional uncertainty.* + +```{r, message = FALSE, eval = TRUE} +reported_cases <- cases[1:90, ] +estimates <- epinow( + reported_cases = reported_cases, + generation_time = generation_time_opts(generation_time_fixed), + delays = delay_opts(incubation_period_fixed + reporting_delay_fixed), + rt = rt_opts(prior = list(mean = rt_log_mean, sd = rt_log_sd)) +) +``` + +### Results + +We can extract and visualise estimates of the effective reproduction number through time: + +```{r} +estimates$plots$R +``` + +The uncertainty in the estimates increases through time. This is because estimates are informed by data in the past - within the delay periods. This difference in uncertainty is categorised into **Estimate** (green) utilises all data and **Estimate based on partial data** (orange) estimates that are based on less data (because infections that happened at the time are more likely to not have been observed yet) and therefore have increasingly wider intervals towards the date of the last data point. Finally, the **Forecast** (purple) is a projection ahead of time. + +We can also visualise the growth rate estimate through time: +```{r} +estimates$plots$growth_rate +``` + +To extract a summary of the key transmission metrics at the *latest date* in the data: + +```{r} +summary(estimates) +``` + +As these estimates are based on partial data, they have a wide uncertainty interval. + ++ From the summary of our analysis we see that the expected change in daily cases is `r summary(estimates)$estimate[summary(estimates)$measure=="Expected change in daily cases"]` with the estimated new confirmed cases `r summary(estimates)$estimate[summary(estimates)$measure=="New confirmed cases by infection date"]`. + ++ The effective reproduction number $R_t$ estimate (on the last date of the data) is `r summary(estimates)$estimate[summary(estimates)$measure=="Effective reproduction no."]`. + ++ The exponential growth rate of case numbers is `r summary(estimates)$estimate[summary(estimates)$measure=="Rate of growth"]`. + ++ The doubling time (the time taken for case numbers to double) is `r summary(estimates)$estimate[summary(estimates)$measure=="Doubling/halving time (days)"]`. + +::::::::::::::::::::::::::::::::::::: callout +### `Expected change in daily cases` + +A factor describing expected change in daily cases based on the posterior probability that $R_t < 1$. + +
+| Probability ($p$) | Expected change | +| ------------- |-------------| +|$p < 0.05$ |Increasing | +|$0.05 \leq p< 0.4$ |Likely increasing | +|$0.4 \leq p< 0.6$ |Stable | +|$0.6 \leq p < 0.95$ |Likely decreasing | +|$0.95 \leq p \leq 1$ |Decreasing | +
+ +:::::::::::::::::::::::::::::::::::::::::::::::: + + + + +## Quantify geographical heterogeneity + +The outbreak data of the start of the COVID-19 pandemic from the United Kingdom from the R package `{incidence2}` includes the region in which the cases were recorded. To find regional estimates of the effective reproduction number and cases, we must format the data to have three columns: + ++ `date` : the date, ++ `region` : the region, ++ `confirm` : number of confirmed cases for a region on a given date. + +```{r} +regional_cases <- + incidence2::covidregionaldataUK[, c("date", "cases_new", "region")] +colnames(regional_cases) <- c("date", "confirm", "region") + +# extract the first 90 dates for all regions +dates <- sort(unique(regional_cases$date))[1:90] +regional_cases <- regional_cases[which(regional_cases$date %in% dates), ] + +head(regional_cases) +``` + +To find regional estimates, we use the same inputs as `epinow()` to the function `regional_epinow()`: + +```{r, message = FALSE, eval = TRUE} +estimates_regional <- regional_epinow( + reported_cases = regional_cases, + generation_time = generation_time_opts(generation_time_fixed), + delays = delay_opts(incubation_period_fixed + reporting_delay_fixed), + rt = rt_opts(prior = list(mean = rt_log_mean, sd = rt_log_sd)) +) + +estimates_regional$summary$summarised_results$table + +estimates_regional$summary$plots$R +``` + + +## Summary + +`EpiNow2` can be used to estimate transmission metrics from case data at the start of an outbreak. The reliability of these estimates depends on the quality of the data and appropriate choice of delay distributions. In the next tutorial we will learn how to make forecasts and investigate some of the additional inference options available in `EpiNow2`. + +::::::::::::::::::::::::::::::::::::: keypoints + +- Transmission metrics can be estimated from case data after accounting for delays +- Uncertainty can be accounted for in delay distributions + +:::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/learners/data/ebola_cases.csv b/learners/data/ebola_cases.csv new file mode 100644 index 00000000..260b8f8a --- /dev/null +++ b/learners/data/ebola_cases.csv @@ -0,0 +1,121 @@ +"date","confirm" +2014-05-18,1 +2014-05-20,2 +2014-05-21,4 +2014-05-22,6 +2014-05-23,1 +2014-05-24,2 +2014-05-26,10 +2014-05-27,8 +2014-05-28,2 +2014-05-29,12 +2014-05-30,7 +2014-05-31,2 +2014-06-01,5 +2014-06-02,2 +2014-06-03,1 +2014-06-05,3 +2014-06-06,7 +2014-06-07,4 +2014-06-08,6 +2014-06-09,1 +2014-06-10,29 +2014-06-11,1 +2014-06-12,10 +2014-06-13,20 +2014-06-14,17 +2014-06-15,4 +2014-06-16,1 +2014-06-17,4 +2014-06-18,8 +2014-06-19,11 +2014-06-20,9 +2014-06-21,3 +2014-06-22,3 +2014-06-23,2 +2014-06-24,9 +2014-06-25,9 +2014-06-26,14 +2014-06-27,15 +2014-06-28,21 +2014-06-29,9 +2014-06-30,15 +2014-07-01,12 +2014-07-02,11 +2014-07-03,4 +2014-07-04,11 +2014-07-05,17 +2014-07-06,9 +2014-07-07,18 +2014-07-08,11 +2014-07-09,8 +2014-07-10,14 +2014-07-11,8 +2014-07-12,7 +2014-07-13,4 +2014-07-14,7 +2014-07-15,5 +2014-07-16,7 +2014-07-17,8 +2014-07-18,10 +2014-07-19,13 +2014-07-20,13 +2014-07-21,18 +2014-07-22,9 +2014-07-23,13 +2014-07-24,10 +2014-07-25,40 +2014-07-26,8 +2014-07-27,7 +2014-07-28,14 +2014-07-29,9 +2014-07-30,14 +2014-07-31,12 +2014-08-01,12 +2014-08-02,15 +2014-08-03,14 +2014-08-04,5 +2014-08-05,13 +2014-08-06,8 +2014-08-07,8 +2014-08-08,13 +2014-08-09,8 +2014-08-10,13 +2014-08-11,4 +2014-08-12,9 +2014-08-13,6 +2014-08-14,8 +2014-08-15,5 +2014-08-16,1 +2014-08-17,5 +2014-08-18,17 +2014-08-19,18 +2014-08-20,35 +2014-08-21,18 +2014-08-22,16 +2014-08-23,18 +2014-08-24,38 +2014-08-25,25 +2014-08-26,42 +2014-08-27,16 +2014-08-28,26 +2014-08-29,30 +2014-08-30,23 +2014-08-31,24 +2014-09-01,29 +2014-09-02,29 +2014-09-03,43 +2014-09-04,41 +2014-09-05,15 +2014-09-06,44 +2014-09-07,30 +2014-09-08,42 +2014-09-09,38 +2014-09-10,21 +2014-09-11,39 +2014-09-12,37 +2014-09-13,38 +2014-09-14,49 +2014-09-15,68 +2014-09-16,84 +2014-09-17,56 diff --git a/learners/reference.md b/learners/reference.md index 14c8148d..1b73c9d5 100644 --- a/learners/reference.md +++ b/learners/reference.md @@ -7,7 +7,14 @@ title: 'Glossary of Terms: Epiverse-TRACE' [Airborne transmission]{#airborne} : Individuals become infected via contact with infectious particles in the air. Examples include influenza and COVID-19. Atler et al. (2023) discuss about [factors and management procedures](https://www.ncbi.nlm.nih.gov/books/NBK531468/) of airborne transmission. - +## B +[Basic reproduction number]{#basic} +: A measure of the transmissibility of a disease. Defined as the average number of secondary cases arising from an initial infected case in an entirely susceptible population. [More information on the basic reproduction number](https://en.wikipedia.org/wiki/Basic_reproduction_number). + +[Bayesian inference]{#bayesian} +: A type of statistical inference where prior beliefs are updated using observed data. +[More information on Bayesian inference](https://en.wikipedia.org/wiki/Bayesian_inference). + ## C @@ -29,7 +36,9 @@ title: 'Glossary of Terms: Epiverse-TRACE' - +## G +[Growth rate]{#growth} +: The exponential growth rate tells us how much cases are increasing or decreasing at the start of an epidemic. It gives us a measure of speed of transmission, see [Dushoff & Park, 2021](https://royalsocietypublishing.org/doi/full/10.1098/rspb.2020.1556). @@ -54,7 +63,6 @@ title: 'Glossary of Terms: Epiverse-TRACE' [Latent period]{#latent} : The time between becoming infected and the onset of infectiousness. [More information on the latent period](https://en.wikipedia.org/wiki/Latent_period_(epidemiology)). - ## M [Model parameters (ODEs)]{#parsode} : The model parameters are used in [ordinary differential equation](#ordinary) models to describe the flow between disease states. For example, a transmission rate $\beta$ is a model parameter that can be used to describe the flow between susceptible and infectious states. @@ -92,8 +100,6 @@ title: 'Glossary of Terms: Epiverse-TRACE' [Vector-borne transmission]{#vectorborne} : Vector-borne transmission means an infection can be passed from a vector (e.g. mosquitoes) to humans. Examples of vector-borne diseases include malaria and dengue. The World Health Organization have a [Fact sheet about Vector-borne diseases](https://www.who.int/news-room/fact-sheets/detail/vector-borne-diseases) with key information and a list of them according to their vector. - - diff --git a/renv/profiles/lesson-requirements/renv.lock b/renv/profiles/lesson-requirements/renv.lock index 80207484..b7a0a655 100644 --- a/renv/profiles/lesson-requirements/renv.lock +++ b/renv/profiles/lesson-requirements/renv.lock @@ -13,6 +13,10 @@ { "Name": "CRAN", "URL": "https://cran.rstudio.com" + }, + { + "Name": "RSPM", + "URL": "https://packagemanager.posit.co/cran/latest" } ] }, @@ -63,6 +67,41 @@ ], "Hash": "f3de4a4878163a4629a528bbcc6e655d" }, + "EpiNow2": { + "Package": "EpiNow2", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "BH", + "R", + "R.utils", + "Rcpp", + "RcppEigen", + "RcppParallel", + "StanHeaders", + "data.table", + "futile.logger", + "future", + "future.apply", + "ggplot2", + "lifecycle", + "lubridate", + "methods", + "patchwork", + "progressr", + "purrr", + "rlang", + "rstan", + "rstantools", + "runner", + "scales", + "stats", + "truncnorm", + "utils" + ], + "Hash": "e40c0a2ebd62f69b953b65e9678b2ffe" + }, "MASS": { "Package": "MASS", "Version": "7.3-60", @@ -95,6 +134,57 @@ ], "Hash": "d9c655b30a2edc6bb2244c1d1e8d549d" }, + "QuickJSR": { + "Package": "QuickJSR", + "Version": "1.0.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "Rcpp", + "jsonlite" + ], + "Hash": "1160fb7afae2eebb5f24939590956cdf" + }, + "R.methodsS3": { + "Package": "R.methodsS3", + "Version": "1.8.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "278c286fd6e9e75d0c2e8f731ea445c8" + }, + "R.oo": { + "Package": "R.oo", + "Version": "1.25.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R.methodsS3", + "methods", + "utils" + ], + "Hash": "a0900a114f4f0194cf4aa8cd4a700681" + }, + "R.utils": { + "Package": "R.utils", + "Version": "2.12.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R.methodsS3", + "R.oo", + "methods", + "tools", + "utils" + ], + "Hash": "325f01db13da12c04d8f6e7be36ff514" + }, "R6": { "Package": "R6", "Version": "2.5.1", @@ -139,6 +229,28 @@ ], "Hash": "acb0a5bf38490f26ab8661b467f4f53a" }, + "RcppParallel": { + "Package": "RcppParallel", + "Version": "5.1.7", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "a45594a00f5dbb073d5ec9f48592a08a" + }, + "StanHeaders": { + "Package": "StanHeaders", + "Version": "2.26.28", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "RcppEigen", + "RcppParallel" + ], + "Hash": "35b5aee9ec9507aca2e021997a9e557e" + }, "askpass": { "Package": "askpass", "Version": "1.2.0", @@ -316,6 +428,16 @@ ], "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" }, + "codetools": { + "Package": "codetools", + "Version": "0.2-19", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c089a619a7fae175d149d89164f8c7d8" + }, "colorspace": { "Package": "colorspace", "Version": "2.1-0", @@ -438,6 +560,97 @@ ], "Hash": "0a861334beb4eb8ca0d24a27b28b6679" }, + "codetools": { + "Package": "codetools", + "Version": "0.2-19", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c089a619a7fae175d149d89164f8c7d8" + }, + "colorspace": { + "Package": "colorspace", + "Version": "2.1-0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats" + ], + "Hash": "f20c47fd52fae58b4e377c37bb8c335b" + }, + "countrycode": { + "Package": "countrycode", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "bbc5ab5258e5ddf38f2cd2c5a7afa860" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.4.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "707fae4bbf73697ec8d85f9d7076c061" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "e8a1e41acf02548751f45c718d55aa6a" + }, + "curl": { + "Package": "curl", + "Version": "5.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "9123f3ef96a2c1a93927d828b2fe7d4c" + }, + "data.table": { + "Package": "data.table", + "Version": "1.14.8", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "b4c06e554f33344e044ccd7fdca750a9" + }, + "desc": { + "Package": "desc", + "Version": "1.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "rprojroot", + "utils" + ], + "Hash": "6b9602c7ebbe87101a9c8edb6e8b6d21" + }, "digest": { "Package": "digest", "Version": "0.6.33", @@ -449,6 +662,33 @@ ], "Hash": "b18a9cf3c003977b0cc49d5e76ebe48d" }, + "distcrete": { + "Package": "distcrete", + "Version": "1.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5ad4e98af2a8e4c63b9b394ec05c91e1" + }, + "distributional": { + "Package": "distributional", + "Version": "0.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "digest", + "farver", + "generics", + "ggplot2", + "lifecycle", + "numDeriv", + "rlang", + "scales", + "stats", + "utils", + "vctrs" + ], + "Hash": "0a94c3c917918a1c90f4609171ff41b6" + }, "dotCall64": { "Package": "dotCall64", "Version": "1.1-1", @@ -547,6 +787,26 @@ ], "Hash": "5abca47c2b33eb1a73a412a045823a8f" }, + "epiparameter": { + "Package": "epiparameter", + "Version": "0.0.0.9000", + "Source": "GitHub", + "RemoteType": "github", + "RemoteUsername": "epiverse-trace", + "RemoteRepo": "epiparameter", + "RemoteRef": "HEAD", + "RemoteSha": "7c5a0fb9c732fbfe45177ef055f66e75063e460a", + "RemoteHost": "api.github.com", + "Requirements": [ + "R", + "checkmate", + "distcrete", + "distributional", + "stats", + "utils" + ], + "Hash": "024a8c8a100fcd73dcf92522d7ef2e35" + }, "evaluate": { "Package": "evaluate", "Version": "0.23", @@ -577,6 +837,25 @@ "Repository": "CRAN", "Hash": "8106d78941f34855c440ddb946b8f7a5" }, + "fansi": { + "Package": "fansi", + "Version": "1.0.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "utils" + ], + "Hash": "3e8583a60163b4bc1a80016e63b9959e" + }, + "farver": { + "Package": "farver", + "Version": "2.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "8106d78941f34855c440ddb946b8f7a5" + }, "fastmap": { "Package": "fastmap", "Version": "1.1.1", @@ -626,6 +905,16 @@ ], "Hash": "1a0a9a3d5083d0d573c4214576f1e690" }, + "formatR": { + "Package": "formatR", + "Version": "1.14", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "63cb26d12517c7863f5abb006c5e0f25" + }, "fs": { "Package": "fs", "Version": "1.6.3", @@ -637,6 +926,58 @@ ], "Hash": "47b5f30c720c23999b913a1a635cf0bb" }, + "futile.logger": { + "Package": "futile.logger", + "Version": "1.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "futile.options", + "lambda.r", + "utils" + ], + "Hash": "99f0ace8c05ec7d3683d27083c4f1e7e" + }, + "futile.options": { + "Package": "futile.options", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "0d9bf02413ddc2bbe8da9ce369dcdd2b" + }, + "future": { + "Package": "future", + "Version": "1.33.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "digest", + "globals", + "listenv", + "parallel", + "parallelly", + "utils" + ], + "Hash": "8e92c7bc53e91b9bb1faf9a6ef0e8514" + }, + "future.apply": { + "Package": "future.apply", + "Version": "1.11.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "future", + "globals", + "parallel", + "utils" + ], + "Hash": "ba4be138fe47eac3e16a6deaa4da106e" + }, "gargle": { "Package": "gargle", "Version": "1.5.2", @@ -695,6 +1036,17 @@ ], "Hash": "313d31eff2274ecf4c1d3581db7241f9" }, + "globals": { + "Package": "globals", + "Version": "0.16.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "codetools" + ], + "Hash": "baa9585ab4ce47a9f4618e671778cc6f" + }, "glue": { "Package": "glue", "Version": "1.6.2", @@ -759,6 +1111,13 @@ ], "Hash": "d6db1667059d027da730decdc214b959" }, + "grates": { + "Package": "grates", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "c937fa4cc110a4aabae986a6393dfb15" + }, "gridExtra": { "Package": "gridExtra", "Version": "2.3", @@ -925,18 +1284,69 @@ ], "Hash": "0080607b4a1a7b28979aecef976d8bc2" }, - "jquerylib": { - "Package": "jquerylib", - "Version": "0.1.4", + "httr": { + "Package": "httr", + "Version": "1.4.7", "Source": "Repository", - "Repository": "RSPM", + "Repository": "CRAN", "Requirements": [ - "htmltools" - ], - "Hash": "5aab57a3bd297eee1c1d862735972182" - }, - "jsonlite": { - "Package": "jsonlite", + "R", + "R6", + "curl", + "jsonlite", + "mime", + "openssl" + ], + "Hash": "ac107251d9d9fd72f0ca8049988f1d7f" + }, + "incidence2": { + "Package": "incidence2", + "Version": "2.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "data.table", + "grDevices", + "grates", + "pillar", + "utils" + ], + "Hash": "bd272708a92103589276504d9c3e8855" + }, + "inline": { + "Package": "inline", + "Version": "0.3.19", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "1deaf1de3eac7e1d3377954b3a283652" + }, + "isoband": { + "Package": "isoband", + "Version": "0.2.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grid", + "utils" + ], + "Hash": "0080607b4a1a7b28979aecef976d8bc2" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonlite": { + "Package": "jsonlite", "Version": "1.8.8", "Source": "Repository", "Repository": "CRAN", @@ -987,6 +1397,43 @@ ], "Hash": "7c5e89f04e72d6611c77451f6331a091" }, + "labeling": { + "Package": "labeling", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "graphics", + "stats" + ], + "Hash": "b64ec208ac5bc1852b285f665d6368b3" + }, + "lambda.r": { + "Package": "lambda.r", + "Version": "1.2.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "formatR" + ], + "Hash": "b1e925c4b9ffeb901bacf812cbe9a6ad" + }, + "lattice": { + "Package": "lattice", + "Version": "0.22-5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "stats", + "utils" + ], + "Hash": "7c5e89f04e72d6611c77451f6331a091" + }, "lifecycle": { "Package": "lifecycle", "Version": "1.0.4", @@ -1013,6 +1460,43 @@ ], "Hash": "680ad542fbcf801442c83a6ac5a2126c" }, + "listenv": { + "Package": "listenv", + "Version": "0.9.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4fbd3679ec8ee169ba28d4b1ea7d0e8f" + }, + "loo": { + "Package": "loo", + "Version": "2.6.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "checkmate", + "matrixStats", + "parallel", + "stats" + ], + "Hash": "e5c8f41731502a0e98f353da23f7ca30" + }, + "lubridate": { + "Package": "lubridate", + "Version": "1.9.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "generics", + "methods", + "timechange" + ], + "Hash": "680ad542fbcf801442c83a6ac5a2126c" + }, "magrittr": { "Package": "magrittr", "Version": "2.0.3", @@ -1035,6 +1519,16 @@ ], "Hash": "5f7886e53a3b39d4a110c7bd7fce9164" }, + "matrixStats": { + "Package": "matrixStats", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "68d317093459a3f0852b1dd52d9e1ea6" + }, "memoise": { "Package": "memoise", "Version": "2.0.1", @@ -1116,6 +1610,16 @@ ], "Hash": "a623a2239e642806158bc4dc3f51565d" }, + "numDeriv": { + "Package": "numDeriv", + "Version": "2016.8-1.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "df58958f293b166e4ab885ebcad90e02" + }, "oai": { "Package": "oai", "Version": "0.4.0", @@ -1140,6 +1644,48 @@ ], "Hash": "2a0dc8c6adfb6f032e4d4af82d258ab5" }, + "pak": { + "Package": "pak", + "Version": "0.7.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "tools", + "utils" + ], + "Hash": "17c4c32b4bdc087508f35e8b7dcf4191" + }, + "parallelly": { + "Package": "parallelly", + "Version": "1.36.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "parallel", + "tools", + "utils" + ], + "Hash": "bca377e1c87ec89ebed77bba00635b2e" + }, + "patchwork": { + "Package": "patchwork", + "Version": "1.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cli", + "ggplot2", + "grDevices", + "graphics", + "grid", + "gtable", + "rlang", + "stats", + "utils" + ], + "Hash": "c5754106c02e8e019941100c81149431" + }, "pillar": { "Package": "pillar", "Version": "1.9.0", @@ -1157,6 +1703,24 @@ ], "Hash": "15da5a8412f317beeee6175fbc76f4bb" }, + "pkgbuild": { + "Package": "pkgbuild", + "Version": "1.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "callr", + "cli", + "crayon", + "desc", + "prettyunits", + "processx", + "rprojroot" + ], + "Hash": "beb25b32a957a22a5c301a9e441190b3" + }, "pkgconfig": { "Package": "pkgconfig", "Version": "2.0.3", @@ -1215,6 +1779,18 @@ ], "Hash": "f4625e061cb2865f111b47ff163a5ca6" }, + "progressr": { + "Package": "progressr", + "Version": "0.14.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "digest", + "utils" + ], + "Hash": "ac50c4ffa8f6a46580dd4d7813add3c4" + }, "ps": { "Package": "ps", "Version": "1.7.5", @@ -1374,6 +1950,53 @@ ], "Hash": "d65e35823c817f09f4de424fcdfa812a" }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "1de7ab598047a87bba48434ba35d497d" + }, + "rstan": { + "Package": "rstan", + "Version": "2.32.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "BH", + "QuickJSR", + "R", + "Rcpp", + "RcppEigen", + "RcppParallel", + "StanHeaders", + "ggplot2", + "gridExtra", + "inline", + "loo", + "methods", + "pkgbuild", + "stats4" + ], + "Hash": "4ac5b7639d28cd4fab19baaf46f33c6a" + }, + "rstantools": { + "Package": "rstantools", + "Version": "2.3.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Rcpp", + "RcppParallel", + "desc", + "stats", + "utils" + ], + "Hash": "32d3b6fe28162eb1c430697f95f40a83" + }, "rstudioapi": { "Package": "rstudioapi", "Version": "0.15.0", @@ -1381,6 +2004,19 @@ "Repository": "CRAN", "Hash": "5564500e25cffad9e22244ced1379887" }, + "runner": { + "Package": "runner", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "Rcpp", + "methods", + "parallel" + ], + "Hash": "468ad9a689459cd083a686232eb3ea31" + }, "rvest": { "Package": "rvest", "Version": "1.0.3", @@ -1483,6 +2119,59 @@ ], "Hash": "ffe1f9e95a4375530747b268f82b5086" }, + "scales": { + "Package": "scales", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "RColorBrewer", + "farver", + "labeling", + "lifecycle", + "munsell", + "rlang", + "viridisLite" + ], + "Hash": "906cb23d2f1c5680b8ce439b44c6fa63" + }, + "socialmixr": { + "Package": "socialmixr", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "countrycode", + "curl", + "data.table", + "fields", + "grDevices", + "httr", + "jsonlite", + "lubridate", + "oai", + "wpp2017", + "xml2" + ], + "Hash": "70e8d107f01e2c1b54154c3aa6200e00" + }, + "spam": { + "Package": "spam", + "Version": "2.10-0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "Rcpp", + "dotCall64", + "grid", + "methods" + ], + "Hash": "ffe1f9e95a4375530747b268f82b5086" + }, "stringi": { "Package": "stringi", "Version": "1.8.3", @@ -1652,6 +2341,43 @@ ], "Hash": "8548b44f79a35ba1791308b61e6012d7" }, + "sys": { + "Package": "sys", + "Version": "3.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "3a1be13d68d47a8cd0bfd74739ca1555" + }, + "tibble": { + "Package": "tibble", + "Version": "3.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "fansi", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "a84e2cc86d07289b3b6f5069df7a004c" + }, + "timechange": { + "Package": "timechange", + "Version": "0.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "8548b44f79a35ba1791308b61e6012d7" + }, "tinytex": { "Package": "tinytex", "Version": "0.49", @@ -1693,6 +2419,26 @@ ], "Hash": "3d78edfb977a69fc7a0341bee25e163f" }, + "truncnorm": { + "Package": "truncnorm", + "Version": "1.0-9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ef5b32c5194351ff409dfb37ca9468f1" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "62b65c52671e6665f803ff02954446e9" + }, "vctrs": { "Package": "vctrs", "Version": "0.6.5", @@ -1811,6 +2557,40 @@ ], "Hash": "ee42417b66554b8fb1ab000b6a7a6588" }, + "viridisLite": { + "Package": "viridisLite", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c826c7c4241b6fc89ff55aaea3fa7491" + }, + "withr": { + "Package": "withr", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "stats" + ], + "Hash": "d77c6f74be05c33164e33fbc85540cae" + }, + "wpp2017": { + "Package": "wpp2017", + "Version": "1.2-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "data.table" + ], + "Hash": "ee42417b66554b8fb1ab000b6a7a6588" + }, "xfun": { "Package": "xfun", "Version": "0.41", @@ -1835,6 +2615,17 @@ ], "Hash": "1d0336142f4cd25d8d23cd3ba7a8fb61" }, + "xml2": { + "Package": "xml2", + "Version": "1.3.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "6c40e5cfcc6aefd88110666e18c31f40" + }, "yaml": { "Package": "yaml", "Version": "2.3.8",