Stochastic Simulations for Flattening the Curve Playground
Below, you will find code for creating a shiny flex-dashboard for performing simple stochastic simulations with one time-interruption corresponding to an intervention (unrealistically simulated all at once). Code relies on the excellent EpiModel R package.
---
title: "Stochastic Simulations for Flattening the Curve"
date: "`r format(Sys.time(), '%B %d, %Y')`"
editor_options:
chunk_output_type: console
output: flexdashboard::flex_dashboard
runtime: shiny
---
{r setup, include=FALSE}
knitr::opts_chunk$set(echo = F, warning = F, message = F, fig.align = 'center', results = 'hide', fig.keep = 'all')
library(tidyverse)
library(EpiModel)
library(furrr)
# https://rmarkdown.rstudio.com/flexdashboard/layouts.html#multiple_pages
### Sidebar {.sidebar}
{r, results='asis'}
#..............................................................
# Sliding Panel for Different Parameters we are estimating
#..............................................................
inputPanel(
sliderInput("ntime", label = "Time of Intervention",
min = 0, max = 200, value = 100, step = 10),
sliderInput("obstime", label = "Epidemic Time-Span",
min = 0, max = 300, value = 200, step = 50),
sliderInput("inf.prob", label = "Unmitigated Prob. of Infxn",
min = 0, max = 1, value = 0.5, step = 0.05),
sliderInput("act.rate", label = "Unmitigated Prob. of Contact",
min = 0, max = 1, value = 0.5, step = 0.05),
sliderInput("newinf.prob", label = "Mitigated Prob. of Infxn",
min = 0, max = 1, value = 0.25, step = 0.05),
sliderInput("newact.rate", label = "Mitigated Prob. of Contact",
min = 0, max = 1, value = 0.25, step = 0.05),
actionLink("button", "Ruh Roh!", icon("bug"),
style="color: #fff; background-color: #337ab7; border-color: #2e6da4")
)
### Stochastic Interventions
{r, results='asis', fig.align='center', fig.height=11, fig.width=8}
renderPlot({ withProgress(message = 'Making plot', {
# re-render button
input$button
# make unmitigated model
param <- param.icm(inf.prob = input$inf.prob, act.rate = input$act.rate, rec.rate = 0.01)
init <- init.icm(s.num = 1e3, i.num = 1, r.num = 0)
control <- control.icm(type = "SIR", nsims = 20, nsteps = input$ntime)
mod.unmit <- icm(param, init, control)
# cheap way to have an intervention
unmitdat <- as.data.frame(mod.unmit)
new_init <- unmitdat %>%
dplyr::filter(time == input$ntime) %>%
dplyr::select(c("s.num", "i.num", "r.num")) %>%
dplyr::mutate(endtime = input$obstime - input$ntime,
newinf.prob = input$newinf.prob,
newact.rate = input$newact.rate)
wrap_icm <- function(newinf.prob, newact.rate, s.num, i.num, r.num, endtime){
newparam <- param.icm(inf.prob = newinf.prob, act.rate = newact.rate, rec.rate = 0.01)
newinit <- init.icm(s.num = as.numeric(s.num),
i.num = as.numeric(i.num),
r.num = as.numeric(r.num)) # as.numeric for stupid corner case
newcontrol <- control.icm(type = "SIR", nsims = 1, nsteps = as.numeric(endtime))
# out
mod <- icm(newparam, newinit, newcontrol)
return(mod)
}
# mitigation
mit.icm <- furrr::future_pmap(new_init, wrap_icm)
mitdat <- lapply(mit.icm, function(x){ret <- as.data.frame(x); ret[, colnames(ret) != "sim"]} )
mitdat <- mitdat %>%
dplyr::bind_rows(., .id = "sim") %>%
dplyr::mutate(time = input$ntime + time)
fulldat <- rbind.data.frame(unmitdat, mitdat)
df.mean <- fulldat %>%
dplyr::group_by(time) %>%
dplyr::summarise(
s.num = mean(s.num),
i.num = mean(i.num),
r.num = mean(r.num),
)
# plot
ggplot() +
geom_line(data = fulldat, mapping = aes(time, s.num, group = sim), alpha = 0.25,
lwd = 0.5, color = "#238b45") +
geom_line(data = df.mean, mapping = aes(time, s.num), color = "#238b45", lwd = 1.2) +
geom_line(data = fulldat, mapping = aes(time, i.num, group = sim), alpha = 0.25,
lwd = 0.55, color = "#cb181d") +
geom_line(data = df.mean, mapping = aes(time, i.num), color = "#cb181d", lwd = 1.2) +
geom_line(data = fulldat, mapping = aes(time, r.num, group = sim), alpha = 0.25,
lwd = 0.55, color = "#54278f") +
geom_line(data = df.mean, mapping = aes(time, r.num), color = "#54278f", lwd = 1.2) +
geom_vline(data = fulldat, aes(xintercept = input$ntime), color = "#000000", linetype = "dashed", size = 1.5, alpha = 0.8) +
xlab("Time") + ylab("Num.") + ggtitle("Stochastic SIR Model Runs with Intervention (Black)") +
theme_minimal() +
theme(
plot.title = element_text(family = "Helvetica", face = "bold", vjust = 0.5, hjust = 0.5, size = 22),
axis.title = element_text(family = "Helvetica", face = "bold", hjust = 0.5, vjust = 0.5, size = 18),
axis.text = element_text(family = "Helvetica", hjust = 0.5, vjust = 0.5, size = 17),
panel.background = element_rect(fill = "transparent"),
plot.background = element_rect(fill = "transparent"),
axis.line = element_line(color = "#000000", size = 1.2),
legend.position = "none")
}) # end of progress bar
})