Chapter 14 Resources for the User
14.1 Introduction
Section 14.2 lists the R
packages that we have used in the different chapters.
Section 14.3 shows a few examples of custom functions we have developed to facilitate some repetitive calculations; details are available in the GitHub link associated with the book. A user must source these files before running the code in each chapter. Section 14.4 presents often used R-INLA
items, pulled into one place for the user.
14.2 Packages used in the book
package | version | source |
---|---|---|
astsa | 1.13 | CRAN (R 4.1.0) |
dlm | 1.1-5 | CRAN (R 4.1.0) |
gridExtra | 2.3 | CRAN (R 4.1.0) |
gtools | 3.8.2 | CRAN (R 4.1.0) |
INLA | 21.02.23 | local |
kableExtra | 1.3.4 | CRAN (R 4.1.0) |
lubridate | 1.7.10 | CRAN (R 4.1.0) |
mapview | 2.9.0 | CRAN (R 4.1.0) |
marima | 2.2 | CRAN (R 4.1.0) |
Matrix | 1.5-1 | CRAN (R 4.1.2) |
matrixcalc | 1.0-5 | CRAN (R 4.1.0) |
mvtnorm | 1.1-1 | CRAN (R 4.1.0) |
quantmod | 0.4.20 | CRAN (R 4.1.2) |
raster | 3.4-10 | CRAN (R 4.1.0) |
readxl | 1.3.1 | CRAN (R 4.1.0) |
sf | 0.9-8 | CRAN (R 4.1.0) |
spdep | 1.1-8 | CRAN (R 4.1.0) |
tables | 0.9.6 | CRAN (R 4.1.0) |
tidyverse | 1.3.1 | CRAN (R 4.1.0) |
tmap | 3.3-1 | CRAN (R 4.1.0) |
vars | 1.5-6 | CRAN (R 4.1.0) |
14.3 Custom functions used in the book
We show different custom functions that we have developed for the user. They are grouped by functionality. The user must source the file containing these functions before running the code, as we show in the beginning of each chapter in the book. All codes and datasets used in the book can be accessed from https://github.com/ramanbala/dynamic-time-series-models-R-INLA.
Basic plotting functions
<-
multiline.plot function(plot.data,
title = "",
xlab = "",
ylab = "",
line.type = "solid",
line.size = 1,
line.color = "auto") {
<-
cpalette c("#000000",
"#56B4E9",
"#009E73",
"#0072B2",
"#D55E00",
"#CC79A7")
<- c("black", "blue", "green", "blue", "red", "purple")
cname <- plot.data %>%
mp pivot_longer(-time, names_to = "key", values_to = "dat")
<- unique(mp$key)
u $key <- factor(mp$key, levels = u)
mplevels(mp$key) <- u
<- mp %>%
mp.auto.color ggplot(aes(x = time, y = dat, color = key)) +
geom_line(size = line.size, linetype = line.type) +
labs(x = xlab, y = ylab, colour = "") +
ggtitle(title)
<- mp %>%
mp.custom.color ggplot(aes(x = time, y = dat, color = key)) +
geom_line(size = line.size, linetype = line.type) +
scale_color_manual(values = cpalette[match(line.color, cname)]) +
labs(x = xlab, y = ylab, colour = "") +
ggtitle(title)
ifelse(line.color == "auto", return(mp.auto.color),
return(mp.custom.color))
}
Functions for forecast evaluation
<- function(yhold,
mae
yfore,text = NA,
round.digit = 3) {
<- yhold - yfore
efore <- mean(abs(efore))
mae if (is.na(text)) {
return(paste("MAE is", round(mae, round.digit), sep = " "))
else {
} return(paste(text, round(mae, round.digit), sep = " "))
} }
<- function(yhold,
mape
yfore,text = NA,
round.digit = 3) {
<- yhold - yfore
efore <- mean(abs(efore / yhold))
mape if (is.na(text)) {
return(paste("MAPE is", round(mape * 100, round.digit), sep = " "))
else {
} return(paste(text, round(mape * 100, round.digit), sep = " "))
} }
Function for model comparison
# Model Selection Criteria - DIC, WAIC, PSBF and PIT
<- function(inla.result, plot.PIT = FALSE,
model.selection.criteria
n.train) {<- inla.result$dic$dic
dic <- inla.result$waic$waic
waic <- inla.result$cpo$cpo
cpo <- sum(log(cpo[1:n.train]))
psbf <- inla.result$cpo$pit
PIT <- cbind(DIC=dic, WAIC = waic, PsBF = psbf)
msc if(isTRUE(plot.PIT)){
<- hist(PIT, plot = F)
pit.hist return(list(msc = msc, hist=plot(pit.hist, main ="")))
else{
} return(msc = msc)
}
}
Function for the filtering algorithm in DLM
<-
filt.inla function(data.series,
model = "rw1",
ar.order = 0,
trend = "no",
alpha = "no") {
<- proc.time()
pt ### model formula
<- expand.grid(
eg model = c("rw1", "ar"),
trend = c("yes", "no"),
alpha = c("yes", "no")
)<- apply(eg, 2, as.character)
eg <- paste0(c(model, trend, alpha), collapse = ".")
choice
<- filt <- vector("list", length(data.series))
dat for (k in 1:length(data.series)) {
<- data.series[1:k]
dat[[k]]
}
<- function(df, ar.order) {
get.filter <- trnd <- 1:length(df)
id <- cbind.data.frame(data.series = df, trnd, id)
inla.dat <- as.numeric(ar.order)
ar.order <- switch(
formula
choice,"rw1.no.no" = as.formula(
paste0("data.series~-1+", "f(id, model='rw1', constr=FALSE)")
),"rw1.yes.no" = as.formula(
paste0(
"data.series~-1+trnd+",
"f(id, model='rw1', constr=FALSE)"
)
),"rw1.no.yes" = as.formula(
paste0("data.series~ 1+", "f(id, model='rw1', constr=FALSE)")
),"rw1.yes.yes" = as.formula(
paste0("data.series~ 1+trnd+", "f(id, model='rw1', constr=FALSE)")
),"ar.no.no" = as.formula(
paste0("data.series~ -1+", "f(id, model='ar', order = ar.order)")
),"ar.yes.no" = as.formula(
paste0(
"data.series~ -1+trnd+",
"f(id, model='ar', order = ar.order)"
)
),"ar.no.yes" = as.formula(
paste0("data.series~ 1+", "f(id, model='ar', order = ar.order)")
),"ar.yes.yes" = as.formula(
paste0(
"data.series~ 1+trnd+",
"f(id, model='ar', order = ar.order)"
)
),
)<- inla(
model.inla
formula,family = "gaussian",
data = inla.dat,
control.predictor = list(compute = TRUE),
control.compute = list(
dic = T,
config = TRUE,
cpo = TRUE
),verbose = T
)<- tail(model.inla$summary.random$id, 1)
filt return(filt = filt)
}#### model execution
require(doParallel)
require(foreach)
<- detectCores()
cores if (cores > 2) {
registerDoParallel(cores = detectCores() - 1)
}
if (ar.order > 1) {
<-
filt.all foreach (
d = (2 + ar.order):length(data.series),
.packages = c('tidyverse', 'INLA'),
.verbose = T
%dopar% {
) get.filter(dat[[d]], ar.order = ar.order)
}else{
} <-
filt.all foreach (
d = 2:length(data.series),
.packages = c('tidyverse', 'INLA'),
.verbose = T
%dopar% {
) get.filter(dat[[d]], ar.order = ar.order)
}
}<- bind_rows(filt.all)
filt.all.bind # filt.est <- c(NA, filt.all$mean)
<- proc.time() - pt
inla.time return(list(filt.all.bind = filt.all.bind, time.taken = inla.time))
}
14.3.1 rgeneric()
function for DLM-VAR model
<-
inla.rgeneric.VAR_1 function(cmd = c("graph",
"Q",
"mu",
"initial",
"log.norm.const",
"log.prior",
"quit"),
theta = NULL)
{<- function() {
interpret.theta <- k * k * p
n.phi <- k
n.prec <- n.phi + n.prec
n.tot <-
phi.VAR sapply(theta[as.integer(1:n.phi)], function(x) {
x
})# W matrix precisions
<-
wprec sapply(theta[as.integer((n.phi + 1):(n.phi + n.prec))],
function(x) {
exp(x)
})<- c(phi.VAR, wprec)
param <- diag(1, n.prec)
W <- 1 / sqrt(wprec)
st.dev <-
st.dev.mat matrix(st.dev, ncol = 1) %*% matrix(st.dev, nrow = 1)
<- W * st.dev.mat
W <- solve(W)
PREC return(list(
param = param,
VACOV = W,
PREC = PREC,
phi.vec = c(phi.VAR)
,n.phi = n.phi,
n.prec = n.prec
))
}#Precision matrix
<- function() {
Q <- interpret.theta()
param <- matrix(param$phi.vec, nrow = k)
phi.mat <- param$PREC
sigma.w.inv <- t(phi.mat) %*% sigma.w.inv %*% phi.mat
A <- -t(phi.mat) %*% sigma.w.inv
B <- sigma.w.inv
C # Construct mid-block:
<- matrix(0, nrow = 2, ncol = 2 * n)
zero.mat # Define the matrix block:
<- cbind(t(B), A + C, B)
mat # Initializing column id and matrix list:
<- list()
col.id <- list()
mat.list 1]] <- 1:(3 * k)
col.id[[1]] <- zero.mat
mat.list[[1]][, col.id[[1]]] <- mat
mat.list[[for (id in 2:(n - 2)) {
<- col.id[[id - 1]][1] + k
start.id <- start.id + (3 * k - 1)
end.d <- start.id:end.d
col.id[[id]] <- zero.mat
mat.list[[id]] <- mat
mat.list[[id]][, col.id[[id]]]
}<- do.call(rbind, mat.list)
mid.block <- 0.1
tau.val <- tau.val * diag(1, k)
diffuse.prec # Construct first and last row blocks and then join with mid block:
<-
first.row.block cbind(A + diffuse.prec, B, matrix(0, nrow = k, ncol = (k * n - k ^ 2)))
<-
last.row.block cbind(matrix(0, nrow = k, ncol = k * n - k ^ 2), t(B), C)
<-
toep.block.mat rbind(first.row.block, mid.block, last.row.block)
# Changing to a sparse Matrix:
<- Matrix(toep.block.mat, sparse = TRUE)
prec.mat return(prec.mat)
}# Graph function: Essentially Q matrix
= function() {
graph return (inla.as.sparse(Q()))
}#Mean of model
<- function() {
mu return(numeric(0))
}# Log normal constant:
<- function() {
log.norm.const <- Q()
Q <-
log.det.val ::determinant(Q, logarithm = TRUE)$modulus
Matrix<- (-k * n / 2) * log(2 * pi) + 0.5 * log.det.val
val return (val)
}<- function() {
log.prior <- interpret.theta()
param <- param$param
pars <- k
k <- param$n.phi + param$n.prec
total.par # Normal prior for phi's:
<- theta[1:param$n.phi]
theta.phi <-
phi.prior sum(sapply(theta.phi, function(x)
dnorm(
x,mean = 0,
sd = 1,
log = TRUE
)))<-
theta.prec $n.phi + 1):(param$n.phi + param$n.prec)]
theta[(param<-
prec.prior sum(sapply(theta.prec, function(x)
dgamma(
x,shape = 1,
scale = 1,
log = TRUE
)))<- sum(theta.prec) # This is for precision terms
prec.jacob <- phi.prior + prec.prior + prec.jacob
prior.val return (prior.val)
}= function() {
initial <- c(0.1, 0.1, 0.1, 0.1)
phi.init <- rep(1, k)
prec.init <- c(phi.init, prec.init)
init return (init)
}if (as.integer(R.version$major) > 3) {
if (!length(theta))
<- initial()
theta else {
} if (is.null(theta)) {
<- initial()
theta
}
}<- do.call(match.arg(cmd), args = list())
val return (val)
}
14.4 Often used R-INLA
items
Control options
Control options in the inla()
function allow us to specify choices about the estimation process and output reporting. In Table 14.1, we list (in alphabetical order) a set of control options that are most relevant for dynamic time series modeling, along with their descriptions. Each control option has a manual page that can be accessed in the usual way, e.g., ?control.compute, with detailed information about the option. In addition, the list of options for each control argument and their default values can be obtained with functions inla.set.control.default()
, where CONTROL refers to the control argument. For example, for the argument control.compute, the list of options and default values can be obtained with inla.set.control.compute.default()
. More details on these, as well as other inla()
control options, can be seen on the R-INLA
website.
Options | Descriptions | Used in Chapter |
---|---|---|
control.compute | Specify what to actually compute during model fitting | Ch. 5-7 |
control.family | Specify model likelihood | Ch. 3-12 |
control.fixed | Options on fixed effects in a model | Ch. 3-4 |
control.group | Defines the order of the model, as in AR(p) | Ch. 3, 8 |
control.inla | Options on how the method is used in model fitting | Ch. 3, 12 |
control.lincomb | Options on how to compute linear combinations | Ch. 12 |
control.link | Ch. 12 | |
control.predictor | Options on computing the linear predictor | Ch. 3-12 |
Options for computing marginals
Often used options for computing various marginal distributions are shown in Table 14.2. We have used some of these options in various sections in the book.
Function | Description |
---|---|
inla.dmarginal | Compute the density function |
inla.pmarginal | Compute the cumulative probability function |
inla.qmarginal | Compute a quantile |
inla.rmarginal | Draw a random sample |
inla.hpdmarginal | Compute the highest posterior density (HPD) credible interval |
inla.smarginal | Spline smoothing of the posterior marginal |
inla.emarginal | Compute the expected value of a function |
inla.mmarginal | Compute the posterior mode |
inla.tmarginal | Transform a marginal using a function |
inla.zmarginal | Compute summary statistics |
Random effect specifications
R-INLA
allows several specifications for handling random effects under different situations. Table 14.3 shows a collection of available effects from which a user may choose a suitable
specification.
Name | Description |
---|---|
iid | Independent and identically distributed Gaussian random effect |
z | Classical specification of random effects |
generic0 | Generic specification (type 0) |
generic1 | Generic specification (type 1) |
generic2 | Generic specification (type 2) |
generic3 | Generic specification (type 3) |
rw1 | Random walk of order 1 |
rw2 | Random walk of order 2 |
crw2 | Continuous random walk of order 2 |
seasonal | Seasonal variation with a given periodicity |
ar1 | Autoregressive model of order 1 |
ar | Autoregressive model of arbitrary order |
iid1d | Correlated random effects of dimension 1 |
iid2d | Correlated random effects of dimension |
iid3d | Correlated random effects of dimension 3 |
iid4d | Correlated random effects of dimension 4 |
iid5d | Correlated random effects of dimension 5 |
Prior specifications
Table 14.4 shows a list of priors available in R-INLA
. This table
is similar to Table 5.2 in Gómez-Rubio (2020). These specifications enable a user to set priors for latent effects or hyperparameters. More details are available on the R-INLA
website.
Prior | Description | Parameters |
---|---|---|
normal | Gaussian prior | mean, precision |
gaussian | Gaussian prior | mean, precision |
loggamma | log-Gamma prior | shape, rate |
logtnormal | Truncated (positive) Gaussian prior | mean, precision |
logtgaussian | Truncated (positive) Gaussian prior | mean, precision |
flat | Flat (improper) prior on \(\theta\) | |
logflat | Flat (improper prior) on \(\exp(\theta)\) | |
logiflat | Flat (improper prior) on \(\exp(-\theta)\) | |
mvnorm | Multivarite Normal prior | |
dirichlet | Dirichlet prior | \(\alpha\) |
betacorrelation | Beta prior for correlation | \(a,~b\) |
logitbeta | Beta prior, logit-scale | \(a,~ b\) |
jeffreystdf | Jeffreys prior | |
table | User defined prior | |
expression | User defined prior |
private communication with Hvard Rue (https://www.r-inla.org/contact-us)↩︎
https://groups.google.com/g/r-inla-discussion-group/c/0dlvlVyiIRQ↩︎
https://archive.ics.uci.edu/ml/datasets/Metro+Interstate+Traffic+Volume↩︎
https://rdrr.io/GitHub/inbo/INLA/f/vignettes/multinomial.Rmd↩︎
https://www.kaggle.com/juliajemals/bike-sharing-washington-dc.↩︎
private communication with Hvard Rue (https://www.r-inla.org/contact-us)↩︎