diff --git a/R/get_expected_total_infections.R b/R/get_expected_total_infections.R index fd2197780e72d9c4415149a0400d7ad838ef69ce..a2fb431bbf66b39bbea7d3a107b88779ac77fe88 100644 --- a/R/get_expected_total_infections.R +++ b/R/get_expected_total_infections.R @@ -1,87 +1,55 @@ #' Expected number of total symptomatic infections #' -#' Calculates the expected total number of symptomatic infections, -#' based on the size of the group, the age group and the setting of the event. +#' Calculates the expected total number of symptomatic infections after a group event, +#' based on the observed infections so far. #' -#' The values of age-specific symptomatic and susceptibility rates are from -#' Davies et al. (2020). +#' meanlog and sdlog are the log-normal distribution parameters derived from +#' the incubation period characteristics described in Xin et al. (2021). +#' Note that the function often clearly overestimates the number of symptomatic infections +#' if last_day_reported_infections is less than 3. #' #' @param group_size integer, size of the group. -#' @param age_group character, the age group of the group, default is "mixed", -#' possible other entries are "children", "adults" or "elderly". -#' @param setting character, the setting of the event, default is "neutral", -#' possible entries are "high risk" or "low risk". -#' @return The number of expected symptomatic infections. -#' -#' @references Davies NG, Klepac P, Liu Y et al. (2020) "Age-dependent effects -#' in the transmission and control of COVID-19 epidemics". \emph{Nature Medicine}, -#' 26: 1205-1211. +#' @param last_day_reported_infection Number of days the last infection was reported after the event (0 = event day). +#' @param total_reported_infections Number of reported symptomatic infections so far. +#' @param meanlog Number, the parameter of mean from the log-normal distribution. +#' @param sdlog Number, the parameter of sd from the log-normal distribution. +#' @return The total number of expected symptomatic infections. #' #' @examples -#' get_expected_total_infections(20) -#' get_expected_total_infections(20, age_group = "elderly", setting = "high risk") +#' get_expected_total_infections(25, 5, 4) #' #' @export get_expected_total_infections <- function(group_size, - age_group = "mixed", - setting = "neutral") { + last_day_reported_infection, + total_reported_infections, + meanlog = 1.69, + sdlog = 0.55) { val_get_expected_total_infections(group_size, - age_group, - setting) - - exposed <- group_size # so far assumption everyone was exposed to virus - ## but e.g. for a group of 500 probably not every person was really exposed + last_day_reported_infection, + total_reported_infections, + meanlog, + sdlog) - if (age_group == "children") { # age < 20 - symptomatic_rate <- 0.25 - if (setting == "high risk") { - infections <- 0.55 * exposed - } else if (setting == "low risk") { - infections <- 0.26 * exposed - } else { - infections <- 0.39 * exposed - } - } else if (age_group == "adults") { # age 20-59 - symptomatic_rate <- 0.38 - if (setting == "high risk") { - infections <- 0.97 * exposed - } else if (setting == "low risk") { - infections <- 0.63 * exposed - } else { - infections <- 0.81 * exposed - } - } else if (age_group == "elderly") { # age >= 60 - symptomatic_rate <- 0.66 - if (setting == "high risk") { - infections <- 0.95 * exposed - } else if (setting == "low risk") { - infections <- 0.63 * exposed - } else { - infections <- 0.81 * exposed - } - } else { # mixed age groups - symptomatic_rate <- 0.41 - if (setting == "high risk") { - infections <- 0.85 * exposed - } else if (setting == "low risk") { - infections <- 0.54 * exposed - } else { - infections <- 0.71 * exposed - } - } + theoretical_probs <- smidm::get_incubation_day_distribution(last_day_reported_infection, + meanlog, + sdlog) - # round up for worst case - return(ceiling(symptomatic_rate * infections)) + return(min(ceiling(total_reported_infections * sum(theoretical_probs)^-1), + group_size)) } val_get_expected_total_infections <- function(group_size, - age_group, - setting){ + last_day_reported_infection, + total_reported_infections, + meanlog, + sdlog){ smidm_is_natural_number(group_size) - smidm_is_character(age_group) - smidm_is_character(setting) + smidm_is_natural_number(last_day_reported_infection) + smidm_is_natural_number(total_reported_infections) + smidm_is_parameter_log_mean(meanlog) + smidm_is_parameter_log_sd(sdlog) } diff --git a/man/get_expected_total_infections.Rd b/man/get_expected_total_infections.Rd index a8a69faf7208ff165086a466ca2846f62715e341..e215cef075031521e7ab6bcd8917bc5194a280fc 100644 --- a/man/get_expected_total_infections.Rd +++ b/man/get_expected_total_infections.Rd @@ -6,37 +6,37 @@ \usage{ get_expected_total_infections( group_size, - age_group = "mixed", - setting = "neutral" + last_day_reported_infection, + total_reported_infections, + meanlog = 1.69, + sdlog = 0.55 ) } \arguments{ \item{group_size}{integer, size of the group.} -\item{age_group}{character, the age group of the group, default is "mixed", -possible other entries are "children", "adults" or "elderly".} +\item{last_day_reported_infection}{Number of days the last infection was reported after the event (0 = event day).} -\item{setting}{character, the setting of the event, default is "neutral", -possible entries are "high risk" or "low risk".} +\item{total_reported_infections}{Number of reported symptomatic infections so far.} + +\item{meanlog}{Number, the parameter of mean from the log-normal distribution.} + +\item{sdlog}{Number, the parameter of sd from the log-normal distribution.} } \value{ -The number of expected symptomatic infections. +The total number of expected symptomatic infections. } \description{ -Calculates the expected total number of symptomatic infections, -based on the size of the group, the age group and the setting of the event. +Calculates the expected total number of symptomatic infections after a group event, +based on the observed infections so far. } \details{ -The values of age-specific symptomatic and susceptibility rates are from -Davies et al. (2020). +meanlog and sdlog are the log-normal distribution parameters derived from +the incubation period characteristics described in Xin et al. (2021). +Note that the function often clearly overestimates the number of symptomatic infections +if last_day_reported_infections is less than 3. } \examples{ -get_expected_total_infections(20) -get_expected_total_infections(20, age_group = "elderly", setting = "high risk") +get_expected_total_infections(25, 5, 4) } -\references{ -Davies NG, Klepac P, Liu Y et al. (2020) "Age-dependent effects -in the transmission and control of COVID-19 epidemics". \emph{Nature Medicine}, -26: 1205-1211. -} diff --git a/man/predict_future_infections.Rd b/man/predict_future_infections.Rd index 889d8c3c5cde79ddf36ada3e6d4ee355075afaf3..51bdbf3dbd6cd438e0ee9e2f882a23d9da613a54 100644 --- a/man/predict_future_infections.Rd +++ b/man/predict_future_infections.Rd @@ -13,11 +13,11 @@ predict_future_infections( ) } \arguments{ -\item{last_day_reported_infection}{Number of days the last infection was reported after the event (1 = event day)} +\item{last_day_reported_infection}{Number of days the last infection was reported after the event (0 = event day).} -\item{total_reported_infections}{Number of reported symptomatic infections so far} +\item{total_reported_infections}{Number of reported symptomatic infections so far.} -\item{total_expected_infections}{Number of expected symptomatic infections in total} +\item{total_expected_infections}{Number of expected symptomatic infections in total.} \item{meanlog}{Number, the parameter of mean from the log-normal distribution.} diff --git a/tests/testthat/test_get_expected_total_infections.R b/tests/testthat/test_get_expected_total_infections.R index f487b636ec7b8125165f913fe8ea25828a219a24..c8f79d15ee90b0798ed1d2efe54e4e5cd8a82bf9 100644 --- a/tests/testthat/test_get_expected_total_infections.R +++ b/tests/testthat/test_get_expected_total_infections.R @@ -1,23 +1,14 @@ test_that("get_expected_total_infections_defaults", { - expect_equal(get_expected_total_infections(1),1) - expect_equal(get_expected_total_infections(10),3) - expect_equal(get_expected_total_infections(100),30) -}) + expect_equal(get_expected_total_infections(1,1,1),1) + expect_equal(get_expected_total_infections(10,1,1),10) + expect_equal(get_expected_total_infections(100,1,1),100) + expect_equal(get_expected_total_infections(1,3,1),1) + expect_equal(get_expected_total_infections(10,3,1),8) + expect_equal(get_expected_total_infections(100,3,1),8) -test_that("get_expected_total_infections_high_risk_elderly", { - age_group <- "elderly" - setting <- "high risk" - expect_equal(get_expected_total_infections(1, age_group, setting),1) - expect_equal(get_expected_total_infections(10, age_group, setting),7) - expect_equal(get_expected_total_infections(100, age_group, setting),63) + expect_equal(get_expected_total_infections(1,5,1),1) + expect_equal(get_expected_total_infections(10,5,1),3) + expect_equal(get_expected_total_infections(100,5,1),3) }) - -test_that("get_expected_total_infections_low_risk_children", { - age_group <- "children" - setting <- "low risk" - expect_equal(get_expected_total_infections(1, age_group, setting),1) - expect_equal(get_expected_total_infections(10, age_group, setting),1) - expect_equal(get_expected_total_infections(100, age_group, setting),7) -}) diff --git a/vignettes/future_infections.Rmd b/vignettes/future_infections.Rmd index b87b1253a4d5e62aefe89852388cf6b50fc2fd26..24828b4bcbc45b90fe73af7c79cfcedaac06a465 100644 --- a/vignettes/future_infections.Rmd +++ b/vignettes/future_infections.Rmd @@ -53,9 +53,9 @@ library(ggplot2) ## Question -A family party with 25 participants took place on the 15.03.2022 in a closed room and no masks were worn. In the following days some participants start to show symptoms of a COVID-19 infection: one on 17.03.2022 and three on 18.03.2022. How many further symptomatic infections can be expected in the following days? +A family party with 25 participants took place on the 15.03.2022 in a closed room and no masks were worn. In the following days some participants start to show symptoms of a COVID-19 infection: one on 18.03.2022 and three on 20.03.2022. How many further symptomatic infections can be expected in the following days? -## Calculating a literature-based prediction of total number of infections with `get_expected_total_infections` +## Calculating a prediction of the total number of infections with `get_expected_total_infections` The function `get_expected_total_infections()` can be used to give a first answer to the question. It returns a prediction how many people in the group are expected to show symptoms in total. @@ -65,30 +65,30 @@ The following input values are necessary for the function `get_expected_total_in The `group_size` is the number of people participating in the event, including all observed infections. -Next, the `age_group` can be given as `"children"` for people aged 0-19, `"adults"` for people aged 20-59, `"elderly"` for people of age 60 or older and `"mixed"` (the default) if there is no clear age group or it is unknown. +The `last_day_reported_infection` is the number of days after the event when the last symptom begin was observed and the `total_reported_infections` is the total number of observed infections so far. -Lastly, the `setting` can be described as `"high risk"`, e.g. if no masks were worn in a closed room for a long time, `"low risk"`, e.g. if masks were worn outside and the people kept enough distance, or `"neutral"` (the default) if the risk is between high and low or unknown. +Finally, `meanlog` and `sdlog` are the mean and standard deviation parameters of the log-normal distribution for the incubation time. ### Methodology -It is assumed that every participant was directly exposed to the virus. Hence, the `group_size` is simply multiplied by the rate of expected symptomatic infections based on the `age_group` and the `setting`. The values of age-specific symptomatic and susceptibility rates are from Davies et al. [1]. +Based on the incubation time distribution one can calculate the percentage of all symptomatic infections that will have their symptom onset up to the `last_day_reported_infection`. Then, said percentage is combined with the `total_reported_infections` to calculate the total symptomatic infections. The minimum between the result and the `group_size` is returned, because the `group_size`is obviously an upper bound for the total infections. ### Output ```{r get_expected_total_infections} group_size = 25 -age_group = "mixed" -setting = "high risk" +last_day_reported_infections = 5 # day 0 = event day +total_reported_infections = 4 predicted_total_infections <- get_expected_total_infections(group_size, - age_group, - setting) + last_day_reported_infections, + total_reported_infections) print(predicted_total_infections) ``` The output represents how many people are expected to get a symptomatic infection. -In the example 9 infections are predicted in total, which implies one can expect 5 further people starting to show symptoms in the next days because 4 infections were already observed. +In the example 10 infections are predicted in total, which implies one can expect 6 further people starting to show symptoms in the next days because 4 infections were already observed. ## Generating a vector with number of people starting to show symptoms on each day using \newline `predict_future_infections` @@ -101,7 +101,7 @@ Multiple arguments are necessary for the function `predict_future_infections()` The `last_day_reported_infection` is the number of days after the event when the last symptom begin was observed and the `total_reported_infections` is the total number of observed infections so far. -Then, the `total_expected_infections` is needed, which defines the total number of expected infections, including the ones already observed. If no own estimation for this is available, the output of `get_expected_total_infections()` can be used. +Then, the `total_expected_infections` is needed, which defines the total number of expected infections, including the ones already observed. One can use the output of `get_expected_total_infections()` or an own estimation based on e.g. reported symptomatic infection rates in a population of interest. If the output of `get_expected_total_infections()` is used, then it should be based on the same `meanlog` and `sdlog` as in the call to `predict_future_infections()`. Finally, `meanlog` and `sdlog` are the mean and standard deviation parameters of the log-normal distribution for the incubation time. @@ -119,9 +119,9 @@ When at some point the updated `total_reported_infections` is not smaller than ` ### Output ```{r predict_future_infections} -last_day_reported_infections = 3 # day 0 = event day +last_day_reported_infections = 5 # day 0 = event day total_reported_infections = 4 -total_expected_infections = get_expected_total_infections(25, "mixed", "high risk") +total_expected_infections = get_expected_total_infections(25, 5, 4) predicted_daily_infections <- predict_future_infections(last_day_reported_infections, total_reported_infections, @@ -135,8 +135,8 @@ The function `predict_future_infections()` creates a vector with values represen ## An example for visualizing the output of \newline `predict_future_infections` ```{r libraries, foldcode = TRUE, message = FALSE} -data <- data.frame("Erkrankungsdatum" = as.Date("2022-03-15") + 0:3, - "Neue_Faelle" = c(0, 0, 1, 3)) +data <- data.frame("Erkrankungsdatum" = as.Date("2022-03-15") + 0:5, + "Neue_Faelle" = c(0, 0, 0, 1, 0, 3)) expected <- data.frame("Erkrankungsdatum" = as.Date("2022-03-15") + 1:(length(predicted_daily_infections)), "ErwarteteWeitereFaelle" = predicted_daily_infections) g <- ggplot(expected) +