-
Notifications
You must be signed in to change notification settings - Fork 3
/
mixing.Rmd
148 lines (116 loc) · 4.31 KB
/
mixing.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
---
title: "Mixing models"
author:
- George Vega Yon
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Mixing models}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>", out.width = "80%", fig.width = 7, fig.height = 5,
fig.align = "center"
)
```
## Introduction
This vignette shows how to create a mixing model using the `epiworldR` package. Mixing models feature multiple populations. Each group, called `Entities`, has a subset of the agents. The agents can interact with each other within the same group and with agents from other groups. A contact matrix defines the interaction between agents.
## An SEIR model with mixing
For this example, we will simulate an outbreak featuring three populations. The contact matrix is defined as follows:
$$
\left[%
\begin{array}{ccc}
0.9 & 0.05 & 0.05 \\
0.1 & 0.8 & 0.1 \\
0.1 & 0.2 & 0.7 \\
\end{array}%
\right]
$$
This matrix represents the probability of an agent from population $i$ interacting with an agent from population $j$. The matrix is row-stochastic, meaning that the sum of each row is equal to 1.
We will build this model using the `entity` class in epiworld. The following code chunk instantiates three entities and the contact matrix.
```{r entity-matrix-setup}
library(epiworldR)
e1 <- entity("Population 1", 3e3, as_proportion = FALSE)
e2 <- entity("Population 2", 3e3, as_proportion = FALSE)
e3 <- entity("Population 3", 3e3, as_proportion = FALSE)
# Row-stochastic matrix (rowsums 1)
cmatrix <- c(
c(0.9, 0.05, 0.05),
c(0.1, 0.8, 0.1),
c(0.1, 0.2, 0.7)
) |> matrix(byrow = TRUE, nrow = 3)
```
With these in hand, we can proceed to create a mixing model. The following code chunk creates a model, an SEIR with mixing, and adds the entities to the model:
```{r model-build}
N <- 9e3
flu_model <- ModelSEIRMixing(
name = "Flu",
n = N,
prevalence = 1 / N,
contact_rate = 20,
transmission_rate = 0.1,
recovery_rate = 1 / 7,
incubation_days = 7,
contact_matrix = cmatrix
)
# Adding the entities
flu_model |>
add_entity(e1) |>
add_entity(e2) |>
add_entity(e3)
```
The function `add_entity` adds the corresponding entity. The default behavior randomly assigns agents to the entities at the beginning of the simulation. Agents may be assigned to more than one entity. The following code-chunk simulates the model for 100 days, summarizes the results, and plots the incidence curve:
```{r model-simulate}
set.seed(331)
run(flu_model, ndays = 100)
summary(flu_model)
plot_incidence(flu_model)
```
## Investigating the history
After running the simulation, a possible question is: how many agents from each entity were infected each day? The following code chunk retrieves the agents from each entity and the transmissions that occurred during the simulation:
```{r investigate, eval=TRUE}
library(data.table)
agents_entities <- lapply(get_entities(flu_model), \(e) {
entity_get_agents(e)
}) |> rbindlist()
head(agents_entities)
```
We can retrieve the daily incidence for each entity by merging the transmissions with the agents' entities. The following code chunk accomplishes this:
```{r transmissions}
# Retrieving the transmissions
transmissions <- get_transmissions(flu_model) |>
data.table()
# We only need the date and the source
transmissions <- subset(
transmissions,
select = c("date", "source")
)
# Attaching the entity to the source
transmissions <- merge(
transmissions,
agents_entities,
by.x = "source", by.y = "agent"
)
# Aggregating by date x entity (counts)
transmissions <- transmissions[, .N, by = .(date, entity)]
# Taking a look at the data
head(transmissions)
```
With this information, we can now visualize the daily incidence for each entity. The following code chunk plots the daily incidence for each entity:
```{r transmissions-plot}
setorder(transmissions, date, entity)
ran <- range(transmissions$N)
transmissions[entity == 0, plot(
x = date, y = N, type = "l", col = "black", ylim = ran)]
transmissions[entity == 1, lines(x = date, y = N, col = "red")]
transmissions[entity == 2, lines(x = date, y = N, col = "blue")]
legend(
"topright",
legend = c("Population 1", "Population 2", "Population 3"),
col = c("black", "red", "blue"),
lty = 1
)
```