Queremos obter a melhor predição para as seguintes curvas ao longo dos dias de casos acumulados, novos casos e crescimento de novos casos, como no exemplo a seguir.
## Setup
my_pars <- c(9000,42,4)
f0 <- d0f(1:80, my_pars)
f1 <- d1f(1:80, my_pars)
f2 <- d2f(1:80, my_pars)
## Plot
data.frame(Dias = rep(1:80,3),
var = rep(factor(c("Acumulados", "Novos casos", "Cresc. Novos Casos"),
levels=c("Acumulados", "Novos casos", "Cresc. Novos Casos")),
each=80),
Valor = c(f0,f1,f2)) %>%
ggplot(aes(Dias,Valor)) +
geom_line() +
geom_vline(xintercept = 42, linetype=2, alpha=.3) +
facet_grid(var~., scales="free_y")
Seja \(f(t)\) a curva acumulada de casos, podemos modelar por uma curva logística
\[ f(t ; \boldsymbol \Phi) = \frac{\phi_1}{1 + \exp\left\{\frac{\phi_2 - t}{\phi_3}\right\}}, \]
com \(\phi_1\) sendo o número máximo de casos ao longo do tempo, \(\phi_2\) o tempo \(t\) em que atingimos este número máximo e \(1/\phi_3\) sua velocidade de crescimento. No exemplo acima, \(\phi_1=9000\), \(\phi_2 = 42\) e \(\phi_3 = 4\).
Consequentemente, o número de novos casos por dia e seu crescimento são modelados pela primeira e segunda derivada de \(f(t)\), respectivamente.
Assim, dado que estamos antes do pico \(\phi_2\) e que temos dados de casos acumulados observados, qual a melhor maneira de estimar esses três parâmetros de forma a obter uma boa estimativa de \(\phi_2\)?
Gostaríamos os parâmetros fossem bons o suficientes para que as três curvas fossem bem ajustadas. Com isso, sejam
vamos minimizar a função a seguir em relação \(\Phi\):
\[ S(\Phi ; \,w_1,w_2,w_3) = w_1\sum_t \big(f(t;\Phi) - d_0(t)\big)^2 + w_2\sum_t \big(f^\prime(t ;\Phi) - d_1(t)\big)^2 + w_3\sum_t \big(f^{\prime \prime}(t;\Phi) - d_2(t)\big)^2, \]
sendo \(w_1,w_2,w_3\) pesos pré-definidos (ou não). A princípio, propõe-se que \(w_1\) seja o maior peso de todos para que a curva se ajuste melhor nos casos observados.
df <- CSSEGISandData() %>%
filter(Country.Region %in% c("China", "Korea, South", "Brazil"),
casosAcumulados > 0) %>%
group_by(Country.Region) %>%
mutate(d1 = c(0, diff(casosAcumulados)),
d2 = c(0, diff(d1)))
dd_korea <- df %>%
filter(Country.Region=="Korea, South") %>%
mutate(days = seq_along(data))
opt_korea = opt(data = dd_korea,
chute = c(10000,30,1),
pesos = c(0.01,0.01,5),
log=TRUE)
opt_korea[["plot"]]
O ajuste para China não é tão fácil quanto o da Coreia e precisamos de chutes iniciais melhores. Vejamos os dados observados
dd_china <- df %>%
filter(Country.Region=="China") %>%
mutate(days = seq_along(data))
visu(dd_china)
Com o gráfico acima, temos uma noção do chute dos parâmetros: \(\phi_1 = 83000\) e \(\phi_2=22\). Com isso, temos o resultado abaixo.
chute_china = c(max(dd_china[["casosAcumulados"]]),
22,
4) ## chute completamente aleatório
opt_china = opt(data=dd_china,chute = chute_china, pesos=c(1,2,4))
opt_china[["plot"]]
opt_china[["pars"]]
## [1] 82007.542170 18.951704 4.657499
O Brasil é o caso mais difícil pq não sabemos em que pé estamos.
dd_br <- df %>%
filter(Country.Region=="Brazil") %>%
mutate(days = seq_along(data))
visu(dd_br)
Note que a curva de casos acumulados e novos casos não tem nenhuma indicação de que vai começar a desacelerar. Portanto, precisamos limitar os parâmetros conforme conhecimentos prévios e observações de cenários em outros países. Os chutes iniciais são bem ruins a princípio: \(\phi_1 = 180000\) e \(\phi_2 = 60\).
chute_br = c(220000,#10*max(dd_br$casosAcumulados),
60,
4) ## chute completamente aleatório
opt_br = opt(data=dd_br,chute = chute_br, pesos=c(1,2,4), lim_inf = c(0,44,0))
opt_br[["plot"]]
Dados os chutes iniciais e os dados que temos, a data esperada de pico em 2020-05-06, com um total de casos estimados em 220000 (muito perto do chute inicial).
dd_pred = opt_br[["pred"]]
dd_pred[["days"]] = rep(seq_along(unique(dd_pred[["data"]])),3)
futuro = 30
dias_fut = seq(from=max(dd_pred[["days"]])+1,
to=max(dd_pred[["days"]])+futuro)
dd_append = data.frame(data = rep(rep(dd_pred[["data"]][1],futuro),3), ## inicializando
var = rep(unique(dd_pred[["var"]]),each=futuro),
observado = 0,
estimado = c(d0f(dias_fut, opt_br[["pars"]]),
d1f(dias_fut, opt_br[["pars"]]),
d2f(dias_fut, opt_br[["pars"]])
),
days = rep(dias_fut,3))
dd_append[["data"]] = dd_br[["data"]][1] + dias_fut
dd_pred[["Dado"]] = "Observado"
dd_append[["Dado"]] = "Predito"
pred_br = rbind(dd_pred,dd_append)
pred_br %>%
as.data.frame() %>%
ggplot(aes(data,observado,col=Dado)) +
geom_point(alpha=.3) +
geom_line(aes(y=estimado)) +
facet_grid(var~., scales="free_y")
Analisando os dados do estado de SP segundo o ministério da saúde
dd_sp <- brMinisterioSaude()
dd_sp <- dd_sp %>%
filter(estado=="SP") %>%
mutate(days = seq_along(data),
date = as.Date(as.character(date), format="%d-%m-%y"),
casosAcumulados = as.numeric(casosAcumulados),
d1 =obitosAcumulados,
d2 = diff(c(0,d1))) %>%
rename(data=date)
visu(dd_sp)
Note que a curva de casos acumulados e novos casos também não tem nenhuma indicação de que vai começar a desacelerar. Portanto, precisamos limitar os parâmetros conforme conhecimentos prévios e observações de cenários em outros países. Os chutes iniciais são proporcionais à população do estado e e no observado no gráfico acima.
chute_sp = c(120000,#10*max(dd_br$casosAcumulados),
120,
4) ## chute completamente aleatório
opt_sp = opt(data=dd_sp,chute = chute_sp, pesos=c(1,5,3), lim_inf = c(110000,80,0))
opt_sp[["plot"]]
Dados os chutes iniciais e os dados que temos, a data esperada de pico em 2020-05-14, com um total de casos estimados em 120000 (muito perto do chute inicial).
dd_pred = opt_sp[["pred"]]
dd_pred[["days"]] = rep(seq_along(unique(dd_pred[["data"]])),3)
futuro = 30
dias_fut = seq(from=max(dd_pred[["days"]])+1,
to=max(dd_pred[["days"]])+futuro)
dd_append = data.frame(data = rep(rep(dd_pred[["data"]][1],futuro),3), ## inicializando
var = rep(unique(dd_pred[["var"]]),each=futuro),
observado = 0,
estimado = c(d0f(dias_fut, opt_sp[["pars"]]),
d1f(dias_fut, opt_sp[["pars"]]),
d2f(dias_fut, opt_sp[["pars"]])
),
days = rep(dias_fut,3))
dd_append[["data"]] = dd_sp[["data"]][1] + dias_fut
dd_pred[["Dado"]] = "Observado"
dd_append[["Dado"]] = "Predito"
pred_sp = rbind(dd_pred,dd_append)
pred_sp %>%
as.data.frame() %>%
ggplot(aes(data,observado,col=Dado)) +
geom_point(alpha=.3) +
geom_line(aes(y=estimado)) +
facet_grid(var~., scales="free_y")
Todas as estimativas acima precisam ser melhoradas!