10-09-2026            >eR-BioStat and STAEM-3D
Modeling infectious diseases using R - age structured population
Ziv Shkedy and Rashider Aloni based on Chapter 2-4 in the book Modeling infectious diseases parameters based on serological and social contact data (https://www.simid.be/modeling-infectious-disease-parameters-based-on-serological-and-social-contact-data/)
## load/install libraries
.libPaths(c("./Rpackages",.libPaths()))
library(knitr)
library(tidyverse)
library(deSolve)
library(minpack.lm)
library(ggpubr)
library(readxl)
library(gamlss)
library(data.table)
library(grid)
library(png)
library(nlme)
library(gridExtra)
library(mvtnorm)
library(e1071)
library(lattice)
library(ggplot2)
library(dslabs)
library(NHANES)
library(plyr)
library(dplyr)
library(nasaweather)
library(ggplot2)
library(gganimate)
library(av)
library(gifski)
library(foreach)
library("DAAG")
library(DT)
library(TeachingDemos)
library(gridExtra)
A special case of a SIR model with interacting subpopulations is an age-time dependent SIR model or age-structured SIR model. In such a model the population is divided into a finite number of age groups interacting with each other. Note that compared with the model discussed in the previous section, the flow of individuals into the susceptible class is possible only in the first age class. A second difference is that in the current model, individuals can pass to the same compartment in successive age classes, this means that a susceptible individual in age group \(i\) can remain susceptible and transfer (age passes) to the susceptible compartment in the successive age group, i.e., this individual passes from \(S_{i}\) to \(S_{i+1}\).
For a population with \(K\) age groups, the system of ordinary differential equations for the first age group (\(i=1\)) in an age-structured SIR model is given by
\[ \left \{ \begin{array}{l} \frac{dS_{i}(t)}{dt} = - \left( \Sigma_{j=1}^{K}\beta_{ij}I_{j} \right )S_{i} +N\mu_{i}-\mu_{i}S_{i} -\eta_{i}S_{i},\\ \frac{dI_{i}(t)}{dt} = \left( \Sigma_{j=1}^{K}\beta_{ij}I_{j} \right )S_{i} - \nu_{i} I_{i} -\eta_{i}I_{i},\\ \frac{dR_{i}(t)}{dt} = \nu_{i}I_{i}-\mu_{i}R_{i}-\eta_{i}R_{i}. \end{array} \right. \]
Here, \(\eta_{i}\) is the rate at which individuals pass from \(S_{i},I_{i},R_{i}\) to \(S_{i+1},I_{i+1},R_{i+1}\). From the second age group onwards, the system of differential equations is similar to the system in one population but without births into the susceptible class (i.e. without \(N \mu_{i}\)) and with the additional flows \(\eta_{i-1}S_{i-1}\), \(\eta_{i-1}I_{i-1}\) and \(\eta_{i-1}R_{i-1}\) corresponding to the susceptible, infected and recovered compartment from the previous age group, respectively.
\[ \left \{ \begin{array}{l} \frac{dS_{i}(t)}{dt} = - \left( \Sigma_{j=1}^{K}\beta_{ij}I_{j} \right )S_{i} +\eta_{i-1}S_{i-1}-\mu_{i}S_{i} -\eta_{i}S_{i},\\ \frac{dI_{i}(t)}{dt} = \left( \Sigma_{j=1}^{K}\beta_{ij}I_{j} \right )S_{i} +\eta_{i-1}I_{i-1}- (\nu_{i}+\mu) I_{i}-\eta_{i}I_{i},\\ \frac{dR_{i}(t)}{dt} = \nu_{i}I_{i}-\mu_{i}R_{i}+\eta_{i-1}R_{i-1}. \end{array} \right. \]
The age-structured SIR model introduces the challenge of estimating the mixing matrix which, up to this point, was assumed to be known. In practice the mixing matrix is unknown and should be estimated. In order to estimate the WAIFW matrix, Anderson and May (1985) introduced a framework in which the mixing matrix itself was assumed unknown but its structure, the mixing pattern, was assumed to be known. Let us consider an age-structured SIR model with two age groups, \([0,a_{1})\) and \([a_{1},L)\), as described above. For each age-group there is an age-specific constant force of infection, \(\lambda_{i}, \; i=1,2\). Using the mixing matrix above it follows that \[ \left ( \begin{array}{c} \lambda_{1} \\ \lambda_{2} \end{array} \right ) = \left( \begin{array}{cc} \beta_{11} & \beta_{12}\\ \beta_{21} & \beta_{22} \end{array} \right ) \left ( \begin{array}{c} I_{1} \\ I_{2} \end{array} \right ). \]
Let us assume that both \(\lambda_{i}\) and \(I_{i}\) were estimated from pre vaccination cross-sectional serological data. In that case we can plug in the estimates \(\hat{I}_{1}\) and \(\hat{I}_{2}\) and it follows that
\[ \begin{array}{c} \hat{\lambda}_{1} = \beta_{11} \hat{I}_{1} + \beta_{12} \hat{I}_{2},\\ \hat{\lambda}_{2} = \beta_{21}\hat{I}_{1} + \beta_{22} \hat{I}_{2}. \end{array} \]
We consider the following transmission rates for a population with two age group \(\beta_11=\beta_22=0.0001\) and \(\beta_12=\beta_{21}=0.0000075\). The contact matrix is given by
\[ C= \left( \begin{array}{cc} 0.0001 & 0.0000075\\ 0.0000075 & 0.0001 \end{array} \right). \]
We assume two age groups, 0-20 and 20-75, life expectancy of 75 years (birth rate=death rate (mu =\(\frac{1}{75}\)) and a population size of 1000000 individuals. In R, the parameter vector is given by
parameters <- c(beta11=0.0001,beta12=0.0000075,beta21=0.0000075,beta22=0.0001,
v1=4,v2=4,mu=1/75,mu2=1/20,N=1000000)
parameters
## beta11 beta12 beta21 beta22 v1 v2
## 1.000000e-04 7.500000e-06 7.500000e-06 1.000000e-04 4.000000e+00 4.000000e+00
## mu mu2 N
## 1.333333e-02 5.000000e-02 1.000000e+06
Note that the object mu2 is the rate in which individuals move from \(S_{i-1}\) to \(S_{i}\), \(I_{i-1}\) to \(I_{i}\) and \(R_{i-1}\) to \(R_{i}\) (\(\eta\)) and in our example it is equal to \(\frac{1}{20}\) since the first age group is 0-20.
In the first age group, \(S(0)=266665, I(0)=1, R(0)=0\) and in the second age group \(S(0)=733334, I(0)=0, R(0)=0\). The state vector in R is
state <- c(Y1=266665,Y2=1,Y3=0,Y4=733334,Y5=0.0,Y6=0)
state
## Y1 Y2 Y3 Y4 Y5 Y6
## 266665 1 0 733334 0 0
times<-seq(0,60,by=0.01)
The SIR model with two age groups is implemented using the R function SIRtwo.
SIRtwo<-function(t,state,parameters)
{
with(as.list(c(state, parameters)),
{
dY1 <- -(beta11*Y2+beta12*Y5)*Y1+N*mu-mu*Y1-mu2*Y1
dY2 <- (beta11*Y2+beta12*Y5)*Y1-v1*Y2-mu*Y2-mu2*Y2
dY3 <- v1*Y2 - mu*Y3-mu2*Y3
dY4 <- -(beta21*Y2+beta22*Y5)*Y4-mu*Y4+mu2*Y1
dY5 <- (beta21*Y2+beta22*Y5)*Y4-v2*Y5-mu*Y5+mu2*Y2
dY6 <- v2*Y5-mu*Y6+mu2*Y3
list(c(dY1,dY2,dY3,dY4,dY5,dY6))
})
}
require(deSolve)
out <- as.data.frame(ode(y=state,times=times,func=SIRtwo,parms=parameters))
out1<-out #Example 1
head(out1)
## time Y1 Y2 Y3 Y4 Y5 Y6
## 1 0.00 266665.0 1.000000 0.00000000 733334.0 0.00000000 0.000000000
## 2 0.01 266629.2 1.254411 0.04487737 733369.5 0.08870454 0.001535006
## 3 0.02 266593.3 1.576325 0.10119126 733404.8 0.28878949 0.008602739
## 4 0.03 266557.3 1.986445 0.17202439 733439.8 0.71777656 0.027740930
## 5 0.04 266521.2 2.514482 0.26145085 733474.4 1.61272323 0.072303628
## 6 0.05 266484.9 3.205256 0.37500523 733507.9 3.45075564 0.169375119
Figure 1 and 2 show the number of susceptible and infected over time, respectively.
par(mfrow=c(1,1))
plot(times,out1$Y1+out1$Y4,ylim=c(0,500000),type="l",main=" ",xlab="time",ylab="S")
lines(times,out1$Y1,lty=2)
lines(times,out1$Y4,lty=3)
legend(10,500000,c("total","age group I","age group II"),lty=c(1,2,3))
Figure 1: SIR model with two age groups: susceptible.
par(mfrow=c(1,1))
plot(times,out1$Y2+out1$Y5,ylim=c(0,50000),type="l",main=" ",xlab="time",ylab="I")
lines(times,out1$Y2,lty=2)
lines(times,out1$Y5,lty=3)
legend(10,50000,c("total","age group I","age group II"),lty=c(1,2,3))
Figure 2: SIR model with two age groups: infected.
Let us assume that the transmission rate within the first age group reduces from \(\beta{11}=0.0001\) to \(\beta_{11}=0.000001\) while the other parameters remain constant. The new contact matrix is given by
\[ C= \left( \begin{array}{cc} 0.000001 & 0.0000075\\ 0.0000075 & 0.0001 \end{array} \right). \]
in R, we updated the parameters vector
parameters <- c(beta11=0.000001,beta12=0.0000075,beta21=0.0000075,beta22=0.0001,
v1=4,v2=4,mu=1/75,mu2=1/20,N=1000000)
parameters
## beta11 beta12 beta21 beta22 v1 v2
## 1.000000e-06 7.500000e-06 7.500000e-06 1.000000e-04 4.000000e+00 4.000000e+00
## mu mu2 N
## 1.333333e-02 5.000000e-02 1.000000e+06
require(deSolve)
out <- as.data.frame(ode(y=state,times=times,func=SIRtwo,parms=parameters))
out05<-out #Example 2
head(out05)
## time Y1 Y2 Y3 Y4 Y5 Y6
## 1 0.00 266665.0 1.0000000 0.00000000 733334.0 0.00000000 0.000000000
## 2 0.01 266629.5 0.9634372 0.03924640 733369.5 0.07876116 0.001411269
## 3 0.02 266593.9 0.9304458 0.07707275 733404.8 0.23349479 0.007336380
## 4 0.03 266558.4 0.9030501 0.11365843 733440.0 0.54055317 0.022164270
## 5 0.04 266522.9 0.8853659 0.14930072 733474.8 1.15291406 0.054693785
## 6 0.05 266487.4 0.8856963 0.18453536 733509.0 2.37708411 0.122558953
Figure 3 and 4 show the number of susceptible and infected individuals in the population under the new scenario.
par(mfrow=c(1,1))
plot(times,out05$Y1+out05$Y4,ylim=c(0,500000),type="l",main=" ",xlab="time",ylab="S")
lines(times,out05$Y1,lty=2)
lines(times,out05$Y4,lty=3)
legend(10,500000,c("total","age group I","age group II"),lty=c(1,2,3))
Figure 3: SIR model with two age groups: susceptible, beta_11=0.000001.
plot(times,out05$Y2+out05$Y5,ylim=c(0,50000),type="l",main=" ",xlab="time",ylab="I")
lines(times,out05$Y2,lty=2)
lines(times,out05$Y5,lty=3)
legend(10,50000,c("total","age group I","age group II"),lty=c(1,2,3))
Figure 4: SIR model with two age groups: infected (beta_11=0.000001.
Figure 5 shows the total number of susceptible under the new scenarios. note that due to the reduction in the transmission rate in the first age group, the susceptible class is buldit slowly and it takes more time to observed an outbreak. In addition, the new equilibrium is reached with more individual in the susceptible class as can be seen in Figure 7 as well.
par(mfrow=c(1,1))
plot(times,out1$Y1+out1$Y4,ylim=c(0,500000),type="l",main=" ",xlab="time",ylab="S")
lines(times,out05$Y1+out05$Y4,lty=2)
legend(10,500000,c("Example 1 (beta_11=0.0001)","Example 2 (beta_11=0.000001)"),lty=c(1,2))
Figure 5: SIR model with two age groups: susceptible.
The longer inter-epidemic period under scenario 2 can be clearly seen in Figure 6.
par(mfrow=c(1,1))
plot(times,out1$Y2+out1$Y5,ylim=c(0,50000),type="l",main=" ",xlab="time",ylab="S")
lines(times,out05$Y2+out05$Y5,lty=2)
legend(10,50000,c("Example 1 (beta_11=0.0001)","Example 2 (beta_11=0.000001)"),lty=c(1,2))
Figure 6: SIR model with two age groups: infected.
par(mfrow=c(1,2))
plot(out1$Y1,out1$Y2,type="l")
lines(out05$Y1,out05$Y2,lty=2)
title("age group 1")
plot(out1$Y4,out1$Y5,type="l")
lines(out05$Y4,out05$Y5,lty=2)
title("age group 2")
Figure 7: Equilibrium plot.