Potential discrepancy in epidemic sizes
Closed this issue · 2 comments
Pasted from Slack:
I’m trying to think through epidemic size expectations in model scenarios that differ only in their transmission rate (or R, if you prefer). I would expect that for an identical number of initial infections, the ratio of epidemic sizes at time t
for two different transmission rates beta
and beta2
would be ((1 + beta) / (1 + beta2))^t
. I’m clearly missing something here, as this isn’t borne out in the reprex below. What am I missing?
Useful reference: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1766383/
library(epidemics)
contact_matrix <- matrix(1)
demography_vector <- c(10e6)
# make initial conditions - order is important
initial_conditions <- matrix(
c(S = 1 - 1e-6, E = 0, I = 1e-6, R = 0, V = 0),
nrow = 1, byrow = FALSE
)
# create a population
pop <- population(
contact_matrix = contact_matrix,
demography_vector = demography_vector,
initial_conditions = initial_conditions
)
beta = 1.3 / 7
beta2 = 0.8 * (1.3 / 7)
time = 100
# with regular beta
data <- model_default(
pop, transmission_rate = beta,
infectiousness_rate = 1,
time_end = 100
)
new_infections(data)
#> Key: <time, demography_group>
#> time demography_group new_infections
#> <num> <char> <num>
#> 1: 0 demo_group_1 0.000000
#> 2: 1 demo_group_1 1.769585
#> 3: 2 demo_group_1 1.722958
#> 4: 3 demo_group_1 1.750475
#> 5: 4 demo_group_1 1.803541
#> ---
#> 97: 96 demo_group_1 50.898345
#> 98: 97 demo_group_1 52.780868
#> 99: 98 demo_group_1 54.732965
#> 100: 99 demo_group_1 56.757202
#> 101: 100 demo_group_1 58.856242
# with 20% reduced beta
data2 <- model_default(
pop, transmission_rate = beta2,
infectiousness_rate = 1,
time_end = 100
)
new_infections(data2)
#> Key: <time, demography_group>
#> time demography_group new_infections
#> <num> <char> <num>
#> 1: 0 demo_group_1 0.000000
#> 2: 1 demo_group_1 1.409427
#> 3: 2 demo_group_1 1.341663
#> 4: 3 demo_group_1 1.323585
#> 5: 4 demo_group_1 1.321985
#> ---
#> 97: 96 demo_group_1 2.083332
#> 98: 97 demo_group_1 2.093725
#> 99: 98 demo_group_1 2.104169
#> 100: 99 demo_group_1 2.114665
#> 101: 100 demo_group_1 2.125214
# ratio of epidemic sizes at time = 100
epidemic_size(data) / epidemic_size(data2)
#> No 'dead' compartment found in `data`; counting only 'recovered' individuals in the epidemic size.
#> No 'dead' compartment found in `data`; counting only 'recovered' individuals in the epidemic size.
#> demo_group_1
#> 7.64958
# ratio of new infections
tail(new_infections(data)[["new_infections"]], 1) /
tail(new_infections(data2)[["new_infections"]], 1)
#> [1] 27.69427
# the expected ratio of two exponential processes with different rates
# not similar to ratio of epidemic sizes
ratio = ((1 + beta) / (1 + beta2))^100
ratio
#> [1] 24.1104
Created on 2024-03-22 with reprex v2.0.2
I think the problem is that it's fiddlier to derive growth rate from R for SEIR models (equation 3.2 in above paper), and hence project forward with a simple (1+r)^n function.
Instead, I had a go at estimating empirical growth rate from the simulation and comparing with the SIR growth rate from above paper, and looks like theory and simulation match OK (noting I approximate the empirical calculation with an exponential). I also put some people in the E
compartment to remove the initial transient dynamic and made
initial_conditions <- matrix(
c(S = 1 - 2e-6, E = 1e-6, I = 1e-6, R = 0, V = 0),
nrow = 1, byrow = FALSE
)
# .....
recovery_rate <- 1/7
infectiousness_rate <- 1/7
beta = 2*recovery_rate
beta2 = 0.8 * 2 * recovery_rate
time_max = 100
# .....
# convert reproduction number to SEIR growth rate (from Wallinga & Lipsitch)
convert_R_to_r <- function(R,infectiousness_rate=1/7,recovery_rate=1/7){
0.5*(-(infectiousness_rate+recovery_rate)+sqrt((infectiousness_rate+recovery_rate)^2 - 4* infectiousness_rate*recovery_rate*(1-R)))
}
# function to calcualte empirical growth rate
empirical_growth_rate <- function(x){
log(x[100]/x[51])/50
}
growth1_empirical <- empirical_growth_rate(new_infections(data)[["new_infections"]])
growth2_empirical <- empirical_growth_rate(new_infections(data2)[["new_infections"]])
growth1_empirical/growth2_empirical
#> 1.562317
# calculate daily growth rates
growth1 <- convert_R_to_r(2,recovery_rate)
growth2 <- convert_R_to_r(0.8*2,recovery_rate)
growth1/growth2
#> 1.563595
Thanks a lot - that's really helpful! Keeping this issue open for future reference.