When trying different mesh parameters, I noticed that slight changes in the 'max.edge' parameter of the 'inla.mesh.2d()' function lead to drastic changes in some of the fixed effects output.
More specifically, changing "max.edge" from 0.03 to 0.035 essentially reverses the direction of some fixed effects (all other mesh parameters kept constant). The hyperparameter estimates appear to be fairly similar.
I'm very much at a loss as to what might be causing this. From what I have read, it seems that the results should not be too sensitive to the mesh resolution. So I think my questions are:
The code
-----------------------------------------------------------------------
deg <- a raster stack, containing 20 rasters with 120m pixel resolution
load("BG_raw_spdf.RData")) a SpatialPointsDataFrame, containing the covariates
annRain <- yearly rainfall for the time period
studyArea <- shapefile for the study area
### ----------------------------------------------------------------------------
time <- 1:nlayers(deg)
# Compute the overall slope of degradation, accounting for rainfall in a given year
slowfun <- function(y) {
NA
} else {
m = lm(y ~ time + annRain$mean); summary(m)$coefficients[2] # get time
}
}
deg_rate <- calc(deg, slowfun)
### Basic INLA model predicting rate from various covariates:
### ----------------------------------------------------------------------------
## Add the rate to the raw_spdf:
deg_rate_spdf <- as(deg_rate, "SpatialPointsDataFrame")
deg_rate_spdf <- deg_rate_spdf[!
is.na(deg_rate_spdf@data$layer), ]
xy_raw <- apply(round(coordinates(raw_spdf), 6), 1, paste, collapse = "_")
xy_rate <- apply(round(coordinates(deg_rate_spdf), 6), 1, paste, collapse = "_")
raw_spdf <- raw_spdf[order(xy_raw), ]
deg_rate_spdf <- deg_rate_spdf[xy_rate %in% xy_raw, ]
deg_rate_spdf <- deg_rate_spdf[order(xy_rate[xy_rate %in% xy_raw]), ]
raw_spdf$deg_rate <- deg_rate_spdf$layer * 10 # Small decimal numbers will use more memory to get to integer. Also easier to read, and index is arbitrary anyways
## Transform and scale covariates:
raw_spdf$lpop <- log(raw_spdf$pop + 1) # log(x+1) for right skewed data containing zeros
raw_spdf$ltlu <- log(raw_spdf$tlu + 1)
raw_spdf$pop_s <- c(scale(raw_spdf$lpop))
raw_spdf$rain_s <- c(scale(raw_spdf$rain))
raw_spdf$tlu_s <- c(scale(raw_spdf$ltlu))
## Make a mesh:
boundary.loc <- as(raw_spdf, "SpatialPoints")
boundary <- list(
list(inla.nonconvex.hull(coordinates(boundary.loc), 0.335),
as.inla.mesh.segment(studyArea)),
inla.nonconvex.hull(coordinates(boundary.loc), 0.61))
## Build the mesh:
mesh <- inla.mesh.2d(boundary=boundary,
max.edge=c(0.035, 0.175),
min.angle=c(30, 21),
max.n=c(48000, 16000), ## Safeguard against large meshes.
max.n.strict=c(128000, 128000), ## Don't build a huge mesh!
cutoff=0.007, ## Filter away adjacent points.
offset=c(0.335, 0.61)) ## Offset for extra boundaries, if needed.
# and the spde:
A = inla.spde.make.A(mesh=mesh, loc=data.matrix(coordinates(raw_spdf))) # Combine actual points with mesh
# covariates:
Xcov = data.frame(intercept=1,
pop_s = raw_spdf$pop_s,
rain_s = raw_spdf$rain_s,
tlu_s = raw_spdf$tlu_s,
CA1 = (raw_spdf$CA == 1) * 1, # CCRO
CA2 = (raw_spdf$CA == 2) * 1, # NP
CA3 = (raw_spdf$CA == 3) * 1) # WMA
Xcov = as.matrix(Xcov)
colnames(Xcov)
stck <- inla.stack(tag='est', # stack is INLA data structure
data=list(deg_rate=raw_spdf$deg_rate),
effects=list(
s=1:mesh$n, # spatial random effect
Xcov=Xcov),
A = list(A, 1)
## define the model:
# - sd(raw_spdf@coords[, 2])/10
# - 0.5*diff(range(raw_spdf@coords[, 2]))
spde = inla.spde2.pcmatern(mesh,
prior.range = c(1.6, 0.5),
prior.sigma = c(0.08, 0.1))
formula = deg_rate ~ -1 + Xcov +
f(s, model=spde) # spatial random effect
## make some linear combinations, for effect plots:
pop_lc <- inla.make.lincombs(Xcov1 = rep(1, 100),
Xcov2 = seq(min(raw_spdf$pop_s), max(raw_spdf$pop_s), len = 100))
names(pop_lc) <- paste0("pop", 1:100)
rain_lc <- inla.make.lincombs(Xcov1 = rep(1, 100),
Xcov3 = seq(min(raw_spdf$rain_s), max(raw_spdf$rain_s), len = 100))
names(rain_lc) <- paste0("rain", 1:100)
tlu_lc <- inla.make.lincombs(Xcov1 = rep(1, 100),
Xcov4 = seq(min(raw_spdf$tlu_s), max(raw_spdf$tlu_s), len = 100))
names(tlu_lc) <- paste0("tlu", 1:100)
CA_lc <- inla.make.lincombs(Xcov1 = rep(1, 4),
Xcov5 = c(0,1,0,0),
Xcov6 = c(0,0,1,0),
Xcov7 = c(0,0,0,1))
names(CA_lc) <- paste0("CA", 1:4)
all_lc <- c(pop_lc, rain_lc, tlu_lc, CA_lc)
res <- inla(formula, data=inla.stack.data(stck),
control.predictor=list(A = inla.stack.A(stck), compute=TRUE),
family = family,
lincomb = all_lc,
control.compute = list(cpo = TRUE),
control.inla = list(int.strategy='eb'), # empirical bayes (cheap computation for testing)
verbose = TRUE)
summary(res)
CPO model fit: