Nothing
## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
if (utils::packageVersion("scoringutils") < "2.0.0") {
stop("The 'scoringutils' package version 2.0.0 or higher is required. Please update it.")
}
if (!requireNamespace("ggplot2", quietly = TRUE)) {
stop("The vignette requires the 'ggplot2' package. Please install it to build the vignette.")
}
## ----warning=FALSE, message=FALSE---------------------------------------------
library(NobBS)
library(dplyr)
library(ggplot2)
library(scoringutils)
data(denguedat)
# Helper function to run nowcasting
run_nowcast <- function(data, now, win_size, specs) {
NobBS(data, now, units = "1 week", onset_date = "onset_week",
report_date = "report_week", moving_window = win_size, specs = specs)
}
quantiles <- c(0.025,seq(0.05,0.95,0.05),0.975)
q_len <- length(quantiles)
q_cols <- paste0('q_',quantiles)
# Poisson model specs
specs_poisson <- list(
dist=c("Poisson"),
quantiles=quantiles
)
#NB model specs
specs_nb = list(
dist=c("NB"),
quantiles=quantiles
)
# Initialize lists to store nowcasts
nowcasts_pois <- list() # Nowcasts using poisson model
nowcasts_nb <- list() # Nowcasts using negtive-binomial model
test_dates <- seq(as.Date("1994-08-29"),as.Date("1994-09-26"),by=7)
win_size <- 8
for (t in seq_along(test_dates)) {
now <- test_dates[t]
denguedat1 <- denguedat[denguedat$onset_week<=now,]
nowcasts_pois[[t]] <- run_nowcast(denguedat1, now, win_size, specs_poisson)
nowcasts_nb[[t]] <- run_nowcast(denguedat1, now, win_size, specs_nb)
}
## ----plot_estimates, fig.width=7, fig.height=4--------------------------------
plot_estimates <- function(nowcast1, nowcast2, cases_per_date, now) {
# Ensure input data is valid
if (is.null(nowcast1$estimates) || is.null(nowcast2$estimates)) {
stop("Nowcast estimates are missing.")
}
# Extract estimates and credible intervals for nowcast without DoW effect
onset_dates1 <- nowcast1$estimates$onset_date
estimates1 <- nowcast1$estimates$estimate
lower1 <- nowcast1$estimates$q_0.025 # 2.5% quantile (lower bound of 95% CI)
upper1 <- nowcast1$estimates$q_0.975 # 97.5% quantile (upper bound of 95% CI)
# Extract estimates and credible intervals for nowcast with DoW effect
onset_dates2 <- nowcast2$estimates$onset_date
estimates2 <- nowcast2$estimates$estimate
lower2 <- nowcast2$estimates$q_0.025
upper2 <- nowcast2$estimates$q_0.975
# Extract eventual case counts
case_dates <- cases_per_date$onset_week
case_counts <- cases_per_date$count
# Calculate plot range
min_val <- min(c(lower1, lower2, case_counts), na.rm = TRUE)
max_val <- max(c(upper1, upper2, case_counts), na.rm = TRUE) * 1.35
# Create the plot
plot(
onset_dates1, estimates1, col = 'blue', type = 'l',
xlab = 'Onset Date', ylab = 'Cases',
ylim = c(min_val, max_val), lwd = 2,
main = paste0('Incidence Estimates for ', now)
)
lines(onset_dates2, estimates2, col = 'red', lwd = 2)
# Add 95% PI shaded regions for both nowcasts
polygon(c(onset_dates1, rev(onset_dates1)), c(lower1, rev(upper1)),
col = rgb(0, 0, 1, 0.2), border = NA)
polygon(c(onset_dates2, rev(onset_dates2)), c(lower2, rev(upper2)),
col = rgb(1, 0, 0, 0.2), border = NA)
# Add true case counts as points
points(case_dates, case_counts, col = 'black', pch = 20)
# Add a legend
legend(
'topleft',
legend = c('Estimates Poisson model',
'Estimates negative binomial model',
'95% PI (Poisson model)',
'95% PI (negative binomial model)',
'Eventual cases'),
col = c('blue', 'red', rgb(0, 0, 1, 0.2), rgb(1, 0, 0, 0.2), 'black'),
lty = c(1, 1, NA, NA, NA), lwd = c(2, 2, NA, NA, NA),
pch = c(NA, NA, 15, 15, 20),
pt.cex = c(NA, NA, 1.5, 1.5, 1),
cex = 0.9
)
}
cases_per_week <- denguedat %>% group_by(onset_week) %>% summarize(count=n())
for (t in seq_along(test_dates)) {
now <- test_dates[t]
nowcast_pois <- nowcasts_pois[[t]]
nowcast_nb <- nowcasts_nb[[t]]
cases_per_week1 <- cases_per_week[cases_per_week$onset_week <= now, ]
plot_estimates(nowcast_pois, nowcast_nb, cases_per_week1, now)
}
## ----quantile_estimates, warning=FALSE, message=FALSE-------------------------
data <- data.frame(onset_week=as.Date(character()),
now=as.Date(character()),
horizon=numeric(),
quantile_level=numeric(),
predicted=numeric(),
observed=numeric(),
model=character())
cases_per_week <- denguedat %>% group_by(onset_week) %>% summarize(count=n())
horizons <- c(-2,-1,0)
for (t in seq_along(test_dates)) {
now <- test_dates[t]
nowcast_pois <- nowcasts_pois[[t]]
nowcast_nb <- nowcasts_nb[[t]]
for(h in horizons) {
date <- now + h*7
true_value <- cases_per_week[cases_per_week$onset_week==date,]$count
q_est_pois <- unname(unlist(nowcast_pois$estimates[nowcast_pois$estimates$onset_date==date,q_cols]))
q_est_nb <- unname(unlist(nowcast_nb$estimates[nowcast_nb$estimates$onset_date==date,q_cols]))
data_est <- data.frame(onset_week=rep(date,q_len*2),
now=rep(now,q_len*2),
horizon=rep(h,q_len*2),
quantile_level=rep(quantiles,2),
predicted=c(q_est_pois,q_est_nb),
observed=rep(true_value,q_len*2),
model=c(rep('Pois_model',q_len),rep('NB_model',q_len)))
data <- rbind(data,data_est)
}
}
print(head(data))
print(tail(data))
## ----warning=FALSE------------------------------------------------------------
nowcasts <- data %>%
scoringutils::as_forecast_quantile()
scores <- scoringutils::score(nowcasts,
get_metrics(nowcasts,select=c("wis","overprediction","underprediction","dispersion")))
print(head(scores))
## ----fig.width=7, fig.height=4------------------------------------------------
scores_per_horizon <- scores %>%
summarise_scores(by = c("horizon", "model"))
print(scores_per_horizon)
plot_wis(scores_per_horizon) +
facet_wrap(~ horizon, scales ='free') +
ggtitle('WIS per Horizon')
## ----fig.width=7, fig.height=4------------------------------------------------
scores_per_now_date <- scores %>%
summarise_scores(by = c("now", "model"))
print(scores_per_now_date)
plot_wis(scores_per_now_date) +
facet_wrap(~ now, scales ='free') +
ggtitle('WIS per Nowcasting Date')
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.