I am using INLA for a 2D SPDE example with several thousand (x,y) coordinates. It works, for a certain combination of predictors, which convinced me that I thought I understood how inla.stack() works. Now I have made a change to the formula I use that gives me an error in inla.stack() that has me confused. Clearly, I am doing something wrong, but I can't see what it is. I have distilled the example down to a simple reproducible example below.
# First, define some toy data.
library("INLA")
library("sf")
# Build dummy data (content irrelevant)
N <- 100
set.seed(1234)
x1 <- rnorm(N,mean=2,sd=1)
x2 <- rnorm(N,mean=3,sd=1)
east <- sample(1:N,size=N)
north <- sample(1:N,size=N)
y <- 2.0*x1 + 3.0*x2 + rnorm(N,mean=0,sd=0.5)
df <- data.frame(x1=x1,x2=x2,y=y,east=east,north=north)
points_spdf <- as_Spatial(st_as_sf(df,coords=c("east","north")))
boundary_sp <- as(st_polygon(list(matrix(c(0,100,100,0,0,0,0,100,100,0),ncol=2,byrow=FALSE))),"Spatial")
# Mesh
MaxEdge <- 5
mesh <- inla.mesh.2d(points_spdf,
boundary=boundary_sp,
max.edge=c(1,5)*MaxEdge,
cutoff=MaxEdge/2,
offset=c(1,5))
plot(mesh)
points(df$east,df$north,pch=21,bg=2)
# Define projector matrices
A1 <- inla.spde.make.A(mesh,loc=points_spdf)
# Define the SPDE. Entirely fictitious
spde1 <- inla.spde2.pcmatern(mesh,
prior.range = c(10, 0.05),
prior.sigma = c(0.5, 0.05))
# Define the spatial field
w1.index <- inla.spde.make.index('w',n.spde=spde1$n.spde)
#--------------------------------------------------------------------------
# The following block works
#--------------------------------------------------------------------------
## Define the predictors
Xm <- model.matrix(~ x1 + x2,data=df)
Xm <- as.data.frame(Xm)
Xm_nointercept <- dplyr::select(Xm,-"(Intercept)") # Drop the intercept
## Build the stack
Nsub <- nrow(df)
StackFit <- inla.stack(
tag = "Fit",
data = list(y=df$y),
A = list(1,1,A1),
effects = list(
Intercept = rep(1,Nsub), # Manual intercept
Xm = Xm_nointercept, # Covariates without the intercept (model matrix)
w = w1.index)) # Weights
## Specify the model formula in terms of the response, covariates, and spatial correlated term
str <- paste0("y ~ -1 + Intercept + `",
paste(colnames(Xm_nointercept),collapse="`+`"),
"`",
"+f(w, model = spde1)")
fm <- as.formula(str)
## Run the model in INLA - this works
m_inla <- inla(formula = fm,
family = "Gamma",
data=inla.stack.data(StackFit),
control.compute = list(dic = TRUE, waic = TRUE),
control.predictor = list(A = inla.stack.A(StackFit)),
verbose = FALSE, debug = FALSE)
#--------------------------------------------------------------------------
# The following block does not work
#--------------------------------------------------------------------------
## Define the predictors
Xm <- model.matrix(~ x1*x2,data=df) # Note the interaction
Xm <- as.data.frame(Xm)
Xm_nointercept <- dplyr::select(Xm,-"(Intercept)")
## Build the stack
Nsub <- nrow(df)
StackFit <- inla.stack(
tag = "Fit",
data = list(y=df$y),
A = list(1,1,A1),
effects = list(
Intercept = rep(1,Nsub), # Manual intercept
Xm = Xm_nointercept, # Covariates without the intercept (model matrix)
# Random effects (there are none)
w = w1.index)) # Weights
# Fails with the following message:
#
# Error in match.names(clabs, names(xi)) :
# names do not match previous names
> End of pasted code
In summary, if I exclude an interaction in my formula, I can generate a stack as expected, and the INLA model fits too. I have progressively added predictors and the model has improved with each addition. As I now suspect an interaction, I have added that interaction between two continuous explanatory variables. The inla.stack() call fails.
I have clearly done something wrong, but can't see it. It is clearly associated with the additional term in the model matric ("x1:x2" in the example above), but that looks ok to me.
I would be grateful for any pointers.