params <-
list(EVAL = TRUE)
## ----echo = FALSE----------------------------------------------------------------------------
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
message = FALSE,
warning = FALSE,
eval = if (isTRUE(exists("params"))) params$EVAL else FALSE
)
## ----setup, include=FALSE--------------------------------------------------------------------
knitr::opts_chunk$set(
echo = TRUE,
dpi = 100,
fig.asp = 0.8,
fig.width = 6,
out.width = "60%",
fig.align = "center"
)
library(mvgam)
library(ggplot2)
theme_set(theme_bw(base_size = 12, base_family = "serif"))
## --------------------------------------------------------------------------------------------
load(url("https://github.com/atsa-es/MARSS/raw/master/data/lakeWAplankton.rda"))
## --------------------------------------------------------------------------------------------
outcomes <- c("Greens", "Bluegreens", "Diatoms", "Unicells", "Other.algae")
## --------------------------------------------------------------------------------------------
# loop across each plankton group to create the long datframe
plankton_data <- do.call(
rbind,
lapply(outcomes, function(x) {
# create a group-specific dataframe with counts labelled 'y'
# and the group name in the 'series' variable
data.frame(
year = lakeWAplanktonTrans[, "Year"],
month = lakeWAplanktonTrans[, "Month"],
y = lakeWAplanktonTrans[, x],
series = x,
temp = lakeWAplanktonTrans[, "Temp"]
)
})
) %>%
# change the 'series' label to a factor
dplyr::mutate(series = factor(series)) %>%
# filter to only include some years in the data
dplyr::filter(year >= 1965 & year < 1975) %>%
dplyr::arrange(year, month) %>%
dplyr::group_by(series) %>%
# z-score the counts so they are approximately standard normal
dplyr::mutate(y = as.vector(scale(y))) %>%
# add the time indicator
dplyr::mutate(time = dplyr::row_number()) %>%
dplyr::ungroup()
## --------------------------------------------------------------------------------------------
head(plankton_data)
## --------------------------------------------------------------------------------------------
dplyr::glimpse(plankton_data)
## --------------------------------------------------------------------------------------------
plot_mvgam_series(data = plankton_data, series = "all")
## --------------------------------------------------------------------------------------------
plankton_data %>%
dplyr::filter(series == "Other.algae") %>%
ggplot(aes(x = time, y = temp)) +
geom_line(size = 1.1) +
geom_line(aes(y = y), col = "white", size = 1.3) +
geom_line(aes(y = y), col = "darkred", size = 1.1) +
ylab("z-score") +
xlab("Time") +
ggtitle("Temperature (black) vs Other algae (red)")
## --------------------------------------------------------------------------------------------
plankton_data %>%
dplyr::filter(series == "Diatoms") %>%
ggplot(aes(x = time, y = temp)) +
geom_line(size = 1.1) +
geom_line(aes(y = y), col = "white", size = 1.3) +
geom_line(aes(y = y), col = "darkred", size = 1.1) +
ylab("z-score") +
xlab("Time") +
ggtitle("Temperature (black) vs Diatoms (red)")
## --------------------------------------------------------------------------------------------
plankton_train <- plankton_data %>%
dplyr::filter(time <= 112)
plankton_test <- plankton_data %>%
dplyr::filter(time > 112)
## ----notrend_mod, include = FALSE, results='hide'--------------------------------------------
notrend_mod <- mvgam(
y ~
te(temp, month, k = c(4, 4)) +
te(temp, month, k = c(4, 4), by = series) -
1,
family = gaussian(),
data = plankton_train,
newdata = plankton_test,
trend_model = "None"
)
## ----eval=FALSE------------------------------------------------------------------------------
# notrend_mod <- mvgam(
# y ~
# # tensor of temp and month to capture
# # "global" seasonality
# te(temp, month, k = c(4, 4)) +
#
# # series-specific deviation tensor products
# te(temp, month, k = c(4, 4), by = series) - 1,
# family = gaussian(),
# data = plankton_train,
# newdata = plankton_test,
# trend_model = "None"
# )
## --------------------------------------------------------------------------------------------
plot_mvgam_smooth(notrend_mod, smooth = 1)
## --------------------------------------------------------------------------------------------
plot_mvgam_smooth(notrend_mod, smooth = 2)
## --------------------------------------------------------------------------------------------
plot_mvgam_smooth(notrend_mod, smooth = 3)
## --------------------------------------------------------------------------------------------
plot(notrend_mod, type = "forecast", series = 1)
## --------------------------------------------------------------------------------------------
plot(notrend_mod, type = "forecast", series = 2)
## --------------------------------------------------------------------------------------------
plot(notrend_mod, type = "forecast", series = 3)
## --------------------------------------------------------------------------------------------
plot(notrend_mod, type = "residuals", series = 1)
## --------------------------------------------------------------------------------------------
plot(notrend_mod, type = "residuals", series = 3)
## --------------------------------------------------------------------------------------------
priors <- get_mvgam_priors(
# observation formula, which has no terms in it
y ~ -1,
# process model formula, which includes the smooth functions
trend_formula = ~ te(temp, month, k = c(4, 4)) +
te(temp, month, k = c(4, 4), by = trend) -
1,
# VAR1 model with uncorrelated process errors
trend_model = VAR(),
family = gaussian(),
data = plankton_train
)
## --------------------------------------------------------------------------------------------
priors[, 3]
## --------------------------------------------------------------------------------------------
priors[, 4]
## --------------------------------------------------------------------------------------------
priors <- c(
prior(normal(0.5, 0.1), class = sigma_obs, lb = 0.2),
prior(normal(0.5, 0.25), class = sigma)
)
## ----var_mod, include = FALSE, results='hide'------------------------------------------------
var_mod <- mvgam(
y ~ -1,
trend_formula = ~
# tensor of temp and month should capture
# seasonality
te(temp, month, k = c(4, 4)) +
# need to use 'trend' rather than series
# here
te(temp, month, k = c(4, 4), by = trend) -
1
,
family = gaussian(),
data = plankton_train,
newdata = plankton_test,
trend_model = VAR(),
priors = priors,
adapt_delta = 0.99,
burnin = 1000
)
## ----eval=FALSE------------------------------------------------------------------------------
# var_mod <- mvgam(
# # observation formula, which is empty
# y ~ -1,
#
# # process model formula, which includes the smooth functions
# trend_formula = ~ te(temp, month, k = c(4, 4)) +
# te(temp, month, k = c(4, 4), by = trend) - 1,
#
# # VAR1 model with uncorrelated process errors
# trend_model = VAR(),
# family = gaussian(),
# data = plankton_train,
# newdata = plankton_test,
#
# # include the updated priors
# priors = priors,
# silent = 2
# )
## --------------------------------------------------------------------------------------------
summary(var_mod, include_betas = FALSE)
## --------------------------------------------------------------------------------------------
plot(var_mod, "smooths", trend_effects = TRUE)
## ----warning=FALSE, message=FALSE------------------------------------------------------------
A_pars <- matrix(NA, nrow = 5, ncol = 5)
for (i in 1:5) {
for (j in 1:5) {
A_pars[i, j] <- paste0("A[", i, ",", j, "]")
}
}
mcmc_plot(var_mod, variable = as.vector(t(A_pars)), type = "hist")
## ----warning=FALSE, message=FALSE------------------------------------------------------------
Sigma_pars <- matrix(NA, nrow = 5, ncol = 5)
for (i in 1:5) {
for (j in 1:5) {
Sigma_pars[i, j] <- paste0("Sigma[", i, ",", j, "]")
}
}
mcmc_plot(var_mod, variable = as.vector(t(Sigma_pars)), type = "hist")
## ----warning=FALSE, message=FALSE------------------------------------------------------------
mcmc_plot(var_mod, variable = "sigma_obs", regex = TRUE, type = "hist")
## --------------------------------------------------------------------------------------------
priors <- c(
prior(normal(0.5, 0.1), class = sigma_obs, lb = 0.2),
prior(normal(0.5, 0.25), class = sigma)
)
## ----varcor_mod, include = FALSE, results='hide'---------------------------------------------
varcor_mod <- mvgam(
y ~ -1,
trend_formula = ~
# tensor of temp and month should capture
# seasonality
te(temp, month, k = c(4, 4)) +
# need to use 'trend' rather than series
# here
te(temp, month, k = c(4, 4), by = trend) -
1
,
family = gaussian(),
data = plankton_train,
newdata = plankton_test,
trend_model = VAR(cor = TRUE),
burnin = 1000,
adapt_delta = 0.99,
priors = priors
)
## ----eval=FALSE------------------------------------------------------------------------------
# varcor_mod <- mvgam(
# # observation formula, which remains empty
# y ~ -1,
#
# # process model formula, which includes the smooth functions
# trend_formula = ~ te(temp, month, k = c(4, 4)) +
# te(temp, month, k = c(4, 4), by = trend) - 1,
#
# # VAR1 model with correlated process errors
# trend_model = VAR(cor = TRUE),
# family = gaussian(),
# data = plankton_train,
# newdata = plankton_test,
#
# # include the updated priors
# priors = priors,
# silent = 2
# )
## ----warning=FALSE, message=FALSE------------------------------------------------------------
Sigma_pars <- matrix(NA, nrow = 5, ncol = 5)
for (i in 1:5) {
for (j in 1:5) {
Sigma_pars[i, j] <- paste0("Sigma[", i, ",", j, "]")
}
}
mcmc_plot(varcor_mod, variable = as.vector(t(Sigma_pars)), type = "hist")
## --------------------------------------------------------------------------------------------
Sigma_post <- as.matrix(varcor_mod, variable = "Sigma", regex = TRUE)
median_correlations <- cov2cor(matrix(
apply(Sigma_post, 2, median),
nrow = 5,
ncol = 5
))
rownames(median_correlations) <- colnames(median_correlations) <- levels(
plankton_train$series
)
round(median_correlations, 2)
## --------------------------------------------------------------------------------------------
irfs <- irf(varcor_mod, h = 12)
## --------------------------------------------------------------------------------------------
summary(irfs)
## --------------------------------------------------------------------------------------------
plot(irfs, series = 3)
## --------------------------------------------------------------------------------------------
fevds <- fevd(varcor_mod, h = 12)
plot(fevds)
## --------------------------------------------------------------------------------------------
# create forecast objects for each model
fcvar <- forecast(var_mod)
fcvarcor <- forecast(varcor_mod)
# plot the difference in variogram scores; a negative value means the VAR1cor model is better, while a positive value means the VAR1 model is better
diff_scores <- score(fcvarcor, score = "variogram")$all_series$score -
score(fcvar, score = "variogram")$all_series$score
plot(
diff_scores,
pch = 16,
cex = 1.25,
col = "darkred",
ylim = c(
-1 * max(abs(diff_scores), na.rm = TRUE),
max(abs(diff_scores), na.rm = TRUE)
),
bty = "l",
xlab = "Forecast horizon",
ylab = expression(variogram[VAR1cor] ~ -~ variogram[VAR1])
)
abline(h = 0, lty = "dashed")
## --------------------------------------------------------------------------------------------
# plot the difference in energy scores; a negative value means the VAR1cor model is better, while a positive value means the VAR1 model is better
diff_scores <- score(fcvarcor, score = "energy")$all_series$score -
score(fcvar, score = "energy")$all_series$score
plot(
diff_scores,
pch = 16,
cex = 1.25,
col = "darkred",
ylim = c(
-1 * max(abs(diff_scores), na.rm = TRUE),
max(abs(diff_scores), na.rm = TRUE)
),
bty = "l",
xlab = "Forecast horizon",
ylab = expression(energy[VAR1cor] ~ -~ energy[VAR1])
)
abline(h = 0, lty = "dashed")
## --------------------------------------------------------------------------------------------
description <- how_to_cite(varcor_mod)
## ----eval = FALSE----------------------------------------------------------------------------
# description
## ----echo=FALSE------------------------------------------------------------------------------
cat("Methods text skeleton\n")
cat(insight::format_message(description$methods_text))
## ----echo=FALSE------------------------------------------------------------------------------
cat("\nPrimary references\n")
for (i in seq_along(description$citations)) {
cat(insight::format_message(description$citations[[i]]))
cat('\n')
}
cat("\nOther useful references\n")
for (i in seq_along(description$other_citations)) {
cat(insight::format_message(description$other_citations[[i]]))
cat('\n')
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.