Section 2: CAR models for spatial disease mapping

Author

Aritz Adin

Published

Aug 13, 2024

This lab session focuses on how to use the bigDM package to fit the scalable spatial model’s proposals described in Orozco-Acosta et al. (2021) using simulated mortality data from the municipalities of continental Spain.

The CAR_INLA() function

This function allows fitting (scalable) spatial Poisson mixed models to areal count data, where several conditional autoregressive (CAR) prior distributions can be specified for the spatial random effects.

Specifically, the linear predictor is modelled as

\[\begin{equation} \log r_{i} = \beta_0 + {\bf x}_{i}^{'}\mathbf{\beta} + \xi_i, \quad \mbox{for} \quad i=1,\ldots,I \end{equation}\]

where \(\beta_0\) is a global intercept, \({\bf x}_{i}^{'}=(x_{i1},\ldots,x_{ip})\) is a \(p\)-vector of standardized covariates in the \(i\)-th area, \(\mathbf{\beta}=(\beta_1,\ldots,\beta_p)^{'}\) is the \(p\)-vector of fixed effect coefficients, and \(\xi_i\) is a spatially structured random effect with a CAR prior distribution.

Main input arguments

What follows is a brief description of the main input arguments and functionalities of the CAR_INLA() function:

  • carto: object of class sf or SpatialPolygonsDataFrame that contains the data of analysis and its associated cartography file. This object must contain at least the target variables of interest specified in the arguments ID.area, O and E.

  • ID.area: character; name of the variable that contains the IDs of spatial areal units.

  • ID.group: character; name of the variable that contains the IDs of the spatial partition (grouping variable). Only required if model="partition".

  • O: character; name of the variable that contains the observed number of disease cases for each areal units.

  • E: character; name of the variable that contains either the expected number of disease cases or the population at risk for each areal unit.

  • X: a character vector containing the names of the covariates within the carto object to be included in the model as fixed effects, or a matrix object playing the role of the fixed effects design matrix. If X=NULL (default), only a global intercept is included in the model as fixed effect.

  • W: optional argument with the binary adjacency matrix of the spatial areal units. If NULL (default), this object is computed from the carto argument (two areas are considered as neighbours if they share a common border).

  • prior: one of either "Leroux" (default), "intrinsic", "BYM" or "BYM2", which specifies the prior distribution considered for the spatial random effect.

  • model: one of either "global" or "partition" (default), which specifies the Global model or one of the scalable model proposal’s (Disjoint model and k-order neighbourhood model, respectively).

  • k: numeric value with the neighbourhood order used for the partition model. Usually k=2 or 3 is enough to get good results. If k=0 (default) the Disjoint model is considered. Only required if model="partition".

  • compute.DIC: logical value; if TRUE (default) then approximate values of the Deviance Information Criterion (DIC) and Watanabe-Akaike Information Criterion (WAIC) are computed.

  • compute.fitted.values: logical value (default FALSE); if TRUE transforms the posterior marginal distribution of the linear predictor to the exponential scale (risks or rates).

  • inla.mode: one of either "classic" (default) or "compact", which specifies the approximation method used by INLA. See help(inla) for further details.

For further details, please refer to the reference manual and the vignettes accompanying this package.

Example 1: stomach cancer mortality data

The main input argument of the CAR_INLA() function must be an object of class sf (simple feature) or SpatialPolygonsDataFrame that contains the data of analysis and its associated cartography file. Standard .shp files (shapefiles) can be loaded as sf objects in R using the sf::st_read() function.

Note that bigDM includes the Carto_SpainMUN object with the polygons of Spanish municipalities and simulated colorectal cancer mortality data (modified in order to preserve the confidentiality of the original data).

library(bigDM)
library(INLA)
Cargando paquete requerido: Matrix
Cargando paquete requerido: sp
This is INLA_24.06.27 built 2024-06-27 02:36:04 UTC.
 - See www.r-inla.org/contact-us for how to get help.
 - List available models/likelihoods/etc with inla.list.models()
 - Use inla.doc(<NAME>) to access documentation
library(sf)
Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
library(tmap)

Adjuntando el paquete: 'tmap'
The following object is masked from 'package:datasets':

    rivers
tmap4 <- packageVersion("tmap") >= "3.99"

data("Carto_SpainMUN")
head(Carto_SpainMUN)
Simple feature collection with 6 features and 8 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 485318 ymin: 4727428 xmax: 543317 ymax: 4779153
Projected CRS: ETRS89 / UTM zone 30N
     ID                                    name           area    perimeter obs
1 01001                        Alegria-Dulantzi 19913794 [m^2] 34372.11 [m]   2
2 01002                                 Amurrio 96145595 [m^2] 63352.32 [m]  28
3 01003                                 Aramaio 73338806 [m^2] 41430.46 [m]   6
4 01004                              Artziniega 27506468 [m^2] 22605.22 [m]   3
5 01006                                 Arminon 10559721 [m^2] 17847.35 [m]   0
6 01008 Arrazua-Ubarrundia (San Martin de Ania) 57502811 [m^2] 64968.81 [m]   2
         exp       SMR     region                       geometry
1  3.0237149 0.6614380 Pais Vasco MULTIPOLYGON (((538259 4737...
2 20.8456682 1.3432047 Pais Vasco MULTIPOLYGON (((503520 4760...
3  3.7527301 1.5988360 Pais Vasco MULTIPOLYGON (((533286 4759...
4  3.2093191 0.9347777 Pais Vasco MULTIPOLYGON (((491260 4776...
5  0.4817391 0.0000000 Pais Vasco MULTIPOLYGON (((509851 4727...
6  1.9643891 1.0181282 Pais Vasco MULTIPOLYGON (((534678 4746...

Global model

We start by fitting the Global model described in Equation (1), where the entire neighbourhood graph of the areal units (municipalities) is considered to define the adjacency matrix \({\bf W}\).

The connect_subgraphs() function computes a fully connected graph and its associated adjacency matrix by merging disjoint connected subgraphs through its nearest polygon centroids.

## NOTE: Not necessary (shown for illustrative purposes only)
aux <- connect_subgraphs(Carto_SpainMUN, ID.area="ID")
Searching for isolated areas:
  1 region(s) with no links

Searching for disjoint connected subgraphs:
 No disjoint connected subgraphs

The function returns a list with the following two elements: * nb: the modified neighbours list * W: associated spatial adjacency matrix of class dgCMatrix

str(aux,1)
List of 2
 $ nb:List of 7907
  ..- attr(*, "class")= chr "nb"
  ..- attr(*, "region.id")= chr [1:7907] "1" "2" "3" "4" ...
  ..- attr(*, "call")= language spdep::poly2nb(pl = carto)
  ..- attr(*, "type")= chr "queen"
  ..- attr(*, "sym")= logi TRUE
  ..- attr(*, "ncomp")=List of 2
 $ W :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
summary(aux$nb)
Neighbour list object:
Number of regions: 7907 
Number of nonzero links: 47532 
Percentage nonzero weights: 0.07602608 
Average number of links: 6.011382 
Link number distribution:

   1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16 
  53  169  522 1149 1721 1631 1112  680  378  199  106   60   34   24   18   13 
  17   18   19   20   21   23   24   25   27   28   31   32   33   34   39 
  11    2    5    3    4    2    2    2    1    1    1    1    1    1    1 
53 least connected regions:
244 256 549 630 637 650 667 715 760 1000 1315 1479 1484 1528 1610 1696 1706 1837 1853 1876 1936 2061 2069 2070 2310 2324 2454 2492 2724 4287 4381 4466 4493 4502 4525 4905 5154 5155 5312 5614 6074 6075 6472 6477 6839 6855 6890 7293 7335 7502 7572 7700 7766 with 1 link
1 most connected region:
2196 with 39 links
aux$W[1:10,1:10]
10 x 10 sparse Matrix of class "dgCMatrix"
  [[ suppressing 10 column names '1', '2', '3' ... ]]
                      
1  . . . . . . . . . 1
2  . . . . . . . 1 . .
3  . . . . . . . . . .
4  . . . . . . . 1 . .
5  . . . . . . . . . .
6  . . . . . . . . . .
7  . . . . . . . . . .
8  . 1 . 1 . . . . . .
9  . . . . . . . . . .
10 1 . . . . . . . . .

The Global model with an iCAR/BYM2 prior distribution are fitted using the CAR_INLA() function as follows:

## Fit the models
iCAR.Global <- CAR_INLA(carto=Carto_SpainMUN, ID.area="ID", O="obs", E="exp",
                        model="global", prior="intrinsic", inla.mode="compact")
STEP 1: Pre-processing data
STEP 2: Fitting global model with INLA (this may take a while...)
summary(iCAR.Global)
Time used:
    Pre = 3.58, Running = 5.58, Post = 1.07, Total = 10.2 
Fixed effects:
              mean    sd 0.025quant 0.5quant 0.975quant   mode kld
(Intercept) -0.007 0.006     -0.019   -0.007      0.005 -0.007   0

Random effects:
  Name    Model
    ID.area Besags ICAR model

Model hyperparameters:
                       mean   sd 0.025quant 0.5quant 0.975quant  mode
Precision for ID.area 39.52 5.45      30.18    39.06      51.48 38.17

Deviance Information Criterion (DIC) ...............: 27428.92
Deviance Information Criterion (DIC, saturated) ....: 8362.65
Effective number of parameters .....................: 343.20

Watanabe-Akaike information criterion (WAIC) ...: 27429.69
Effective number of parameters .................: 302.42

Marginal log-Likelihood:  -19904.60 
CPO, PIT is computed 
Posterior summaries for the linear predictor and the fitted values are computed
(Posterior marginals needs also 'control.compute=list(return.marginals.predictor=TRUE)')
BYM2.Global <- CAR_INLA(carto=Carto_SpainMUN, ID.area="ID", O="obs", E="exp",
                        model="global", prior="BYM2", inla.mode="compact")
STEP 1: Pre-processing data
STEP 2: Fitting global model with INLA (this may take a while...)
summary(BYM2.Global)
Time used:
    Pre = 3.64, Running = 16, Post = 2.22, Total = 21.8 
Fixed effects:
              mean    sd 0.025quant 0.5quant 0.975quant   mode kld
(Intercept) -0.009 0.006     -0.021   -0.009      0.003 -0.009   0

Random effects:
  Name    Model
    ID.area BYM2 model

Model hyperparameters:
                        mean    sd 0.025quant 0.5quant 0.975quant   mode
Precision for ID.area 73.047 9.619     56.043   72.389     93.849 71.029
Phi for ID.area        0.831 0.071      0.668    0.841      0.942  0.862

Deviance Information Criterion (DIC) ...............: 27426.95
Deviance Information Criterion (DIC, saturated) ....: 8360.68
Effective number of parameters .....................: 377.77

Watanabe-Akaike information criterion (WAIC) ...: 27414.54
Effective number of parameters .................: 320.65

Marginal log-Likelihood:  -10466.87 
CPO, PIT is computed 
Posterior summaries for the linear predictor and the fitted values are computed
(Posterior marginals needs also 'control.compute=list(return.marginals.predictor=TRUE)')
## Model comparison
compare.DIC <- function(x){
  data.frame(mean.deviance=x$dic$mean.deviance, p.eff=x$dic$p.eff,
             DIC=x$dic$dic, WAIC=x$waic$waic,
             time=x$cpu.used["Total"])
}
do.call(rbind,lapply(list(iCAR=iCAR.Global, BYM2=BYM2.Global), compare.DIC))
     mean.deviance    p.eff      DIC     WAIC     time
iCAR      27085.72 343.2019 27428.92 27429.70 10.22991
BYM2      27049.18 377.7695 27426.95 27414.55 21.83418
plot(iCAR.Global$summary.linear.predictor$`0.5quant`,
     BYM2.Global$summary.linear.predictor$`0.5quant`,
     xlim=c(-0.5,0.5), ylim=c(-0.5,0.5),
     xlab="iCAR model", ylab="BYM2 model",
     main="Posterior median estimates")
lines(c(-1,1),c(-1,1))

Partition models

A natural choice for defining the partition of the entire spatial domain could be using administrative subdivisions, such as provinces or states. For our example data, the \(D=15\) Autonomous Regions of Spain are used as a partition of the \(n=7907\) municipalities (Carto_SpainMUN$region variable).

tmap_mode("plot")
tmap mode set to 'plot'
if(tmap4){
  tm_shape(Carto_SpainMUN) +
    tm_polygons(fill="region",
                fill.scale=tm_scale(values="brewer.set3"),
                fill.legend=tm_legend(frame=FALSE))
}else{
  tm_shape(Carto_SpainMUN) +
    tm_polygons(col="region") + 
    tm_layout(legend.outside=TRUE) 
}

The disjoint and k-order neighbourhood models with an iCAR prior distribution are fitted using the CAR_INLA() function as:

iCAR.k0 <- CAR_INLA(carto=Carto_SpainMUN, ID.area="ID", O="obs", E="exp",
                    model="partition", k=0, ID.group="region",
                    prior="intrinsic", inla.mode="compact")
STEP 1: Pre-processing data
STEP 2: Fitting partition (k=0) model with INLA 
+ Model 1 of 15 
+ Model 2 of 15 
+ Model 3 of 15 
+ Model 4 of 15 
+ Model 5 of 15 
+ Model 6 of 15 
+ Model 7 of 15 
+ Model 8 of 15 
+ Model 9 of 15 
+ Model 10 of 15 
+ Model 11 of 15 
+ Model 12 of 15 
+ Model 13 of 15 
+ Model 14 of 15 
+ Model 15 of 15 
STEP 3: Merging the results
iCAR.k0$cpu.used
 Running  Merging    Total 
25.63806 18.53000 44.16806 
iCAR.k1 <- CAR_INLA(carto=Carto_SpainMUN, ID.area="ID", O="obs", E="exp",
                    model="partition", k=1, ID.group="region",
                    prior="intrinsic", inla.mode="compact")
STEP 1: Pre-processing data
STEP 2: Fitting partition (k=1) model with INLA 
+ Model 1 of 15 
+ Model 2 of 15 
+ Model 3 of 15 
+ Model 4 of 15 
+ Model 5 of 15 
+ Model 6 of 15 
+ Model 7 of 15 
+ Model 8 of 15 
+ Model 9 of 15 
+ Model 10 of 15 
+ Model 11 of 15 
+ Model 12 of 15 
+ Model 13 of 15 
+ Model 14 of 15 
+ Model 15 of 15 
STEP 3: Merging the results
iCAR.k1$cpu.used
 Running  Merging    Total 
25.85957 24.04000 49.89957 
iCAR.k2 <- CAR_INLA(carto=Carto_SpainMUN, ID.area="ID", O="obs", E="exp",
                    model="partition", k=2, ID.group="region",
                    prior="intrinsic", inla.mode="compact")
STEP 1: Pre-processing data
STEP 2: Fitting partition (k=2) model with INLA 
+ Model 1 of 15 
+ Model 2 of 15 
+ Model 3 of 15 
+ Model 4 of 15 
+ Model 5 of 15 
+ Model 6 of 15 
+ Model 7 of 15 
+ Model 8 of 15 
+ Model 9 of 15 
+ Model 10 of 15 
+ Model 11 of 15 
+ Model 12 of 15 
+ Model 13 of 15 
+ Model 14 of 15 
+ Model 15 of 15 
STEP 3: Merging the results
iCAR.k2$cpu.used
 Running  Merging    Total 
27.95516 24.37000 52.32516 

Internally, the divide_carto() function is called to compute the overlapping set of regions \(\{D_1,\ldots,D_{15}\}\) according to the grouping variable ID.group="region". The neighbourhood order to add polygons at the border of the spatial subdomains is controlled by the k argument.

## Compute subdomains for k=0,1 and 2
carto.k0 <- divide_carto(carto=Carto_SpainMUN, ID.group="region", k=0)
carto.k1 <- divide_carto(carto=Carto_SpainMUN, ID.group="region", k=1)
carto.k2 <- divide_carto(carto=Carto_SpainMUN, ID.group="region", k=2)

## Plot the spatial polygons for the autonomous region of Castilla y Leon 
plot(carto.k2$`Castilla y Leon`$geometry, col="dodgerblue4", main="Castilla y Leon")
plot(carto.k1$`Castilla y Leon`$geometry, col="dodgerblue", add=TRUE)
plot(carto.k0$`Castilla y Leon`$geometry, col="lightgrey", add=TRUE)

Compare the results

library(RColorBrewer)

## Carto object of the Spanish provinces 
carto.CCAA <- aggregate(Carto_SpainMUN[,"geometry"],list(ID.group=st_drop_geometry(Carto_SpainMUN)$region), head)

## Model selection criteria
MODELS <- list(Global=iCAR.Global, k0=iCAR.k0, k1=iCAR.k1, k2=iCAR.k2)
do.call(rbind,lapply(MODELS, compare.DIC))
       mean.deviance    p.eff      DIC     WAIC     time
Global      27085.72 343.2019 27428.92 27429.70 10.22991
k0          27100.20 345.7313 27445.93 27443.42 44.16806
k1          27098.37 334.7532 27433.12 27433.87 49.89957
k2          27131.79 308.8768 27440.66 27446.55 52.32516
## Maps with posterior median estimates of log-risks
Carto_SpainMUN$Global <- iCAR.Global$summary.linear.predictor$`0.5quant`
Carto_SpainMUN$k0 <- iCAR.k0$summary.linear.predictor$`0.5quant`
Carto_SpainMUN$k1 <- iCAR.k1$summary.linear.predictor$`0.5quant`
Carto_SpainMUN$k2 <- iCAR.k2$summary.linear.predictor$`0.5quant`

paleta <- brewer.pal(8,"RdYlGn")[8:1]
values <- c(-Inf,log(c(0.83,0.91,0.95,1,1.05,1.10,1.20)),Inf)

if(tmap4){
  Map.risk <- tm_shape(Carto_SpainMUN) +
    tm_polygons(fill=c("Global","k0","k1","k2"), fill.free=FALSE, col_alpha=0,
                fill.scale=tm_scale(values=paleta, breaks=values, interval.closure="left", midpoint=0),
                fill.legend=tm_legend("log-risks", show=TRUE, reverse=TRUE,
                                      position=tm_pos_out("right","center"),
                                      frame=FALSE)) +
    tm_shape(carto.CCAA) + tm_borders(col="gray40") +
    tm_title("Posterior median estimates") + 
    tm_layout(panel.labels=c("Global model","Disjoint model","1st-order nb","2nd-order nb")) +
    tm_facets(nrow=2, ncol=2)
}else{
  Map.risk <- tm_shape(Carto_SpainMUN) + 
    tm_polygons(col=c("Global","k0","k1","k2"), palette=paleta, border.alpha=0,
                title="log-risks", legend.show=T, legend.reverse=T,
                style="fixed", breaks=values, interval.closure="left") + 
    tm_shape(carto.CCAA) + tm_borders(col="gray40") +
    tm_layout(main.title="Posterior median estimates", main.title.position="center",
              panel.labels=c("Global model","Disjoint model","1st-order nb","2nd-order nb"),
              legend.outside=T, legend.outside.position="right", legend.frame=F,
              legend.outside.size=0.2, outer.margins=c(0.02,0.01,0.02,0.01)) + 
    tm_facets(nrow=2, ncol=2)
}
  
tmap_mode("plot")
print(Map.risk)

## Maps with posterior exceedence probabilities
Carto_SpainMUN$Global <- 1-iCAR.Global$summary.linear.predictor$`0cdf`
Carto_SpainMUN$k0 <- 1-iCAR.k0$summary.linear.predictor$`0cdf`
Carto_SpainMUN$k1 <- 1-iCAR.k1$summary.linear.predictor$`0cdf`
Carto_SpainMUN$k2 <- 1-iCAR.k2$summary.linear.predictor$`0cdf`

paleta <- brewer.pal(6,"Blues")[-1]
values <- c(0,0.1,0.2,0.8,0.9,1)

if(tmap4){
  Map.prob <- tm_shape(Carto_SpainMUN) +
    tm_polygons(fill=c("Global","k0","k1","k2"), fill.free=FALSE, col_alpha=0,
                fill.scale=tm_scale(values=paleta, breaks=values, interval.closure="left",
                                    labels=c("[0-0.1)","[0.1-0.2)","[0.2-0.8)","[0.8-0.9)","[0.9-1]")),
                fill.legend=tm_legend("Prob", show=TRUE, reverse=TRUE, frame=FALSE,
                                      position=tm_pos_out("right","center"))) + 
    tm_shape(carto.CCAA) + tm_borders(col="gray40") +
    tm_title("Posterior exceedence probabilities") + 
    tm_layout(panel.labels=c("Global model","Disjoint model","1st-order nb","2nd-order nb")) +
    tm_facets(nrow=2, ncol=2)
}else{
  Map.prob <- tm_shape(Carto_SpainMUN) + 
    tm_polygons(col=c("Global","k0","k1","k2"), palette=paleta, border.alpha=0,
                title="Prob", legend.show=T, legend.reverse=T,
                style="fixed", breaks=values, interval.closure="left",
                labels=c("[0-0.1)","[0.1-0.2)","[0.2-0.8)","[0.8-0.9)","[0.9-1]")) +
    tm_shape(carto.CCAA) + tm_borders(col="gray40") + 
    tm_layout(main.title="Posterior exceedence probabilities", main.title.position="center",
              panel.labels=c("Global model","Disjoint model","1st-order nb","2nd-order nb"),
              legend.outside=T, legend.outside.position="right", legend.frame=F,
              legend.outside.size=0.2, outer.margins=c(0.02,0.01,0.02,0.01)) +
    tm_facets(nrow=2, ncol=2)
}

tmap_mode("plot")
print(Map.prob)

Example 2: ecological regression model

In this second example, we are going to fit a spatial model that incorporates both area-level CAR random effects and a set of explanatory variables, with the aim of comparing the regression coefficient estimates obtained from the global and partitioned models.

For this, we will use the data contained in the Data_MultiCancer object as follows:

## Define the data and the spatial covariates ##
data("Data_MultiCancer")
head(Data_MultiCancer)
     ID disease obs        exp       SMR
1 01001       1   3  6.6147794 0.4535299
2 01002       1  41 42.6337564 0.9616793
3 01003       1   4  7.4307781 0.5383016
4 01004       1   6  6.3549654 0.9441436
5 01006       1   0  0.9337634 0.0000000
6 01008       1   2  3.9404795 0.5075524
data <- Data_MultiCancer[Data_MultiCancer$disease==1,]
data$X1 <- Data_MultiCancer[Data_MultiCancer$disease==2,"SMR"]
data$X2 <- Data_MultiCancer[Data_MultiCancer$disease==3,"SMR"]
head(data)
     ID disease obs        exp       SMR        X1        X2
1 01001       1   3  6.6147794 0.4535299 1.3051895 0.7755112
2 01002       1  41 42.6337564 0.9616793 1.5158172 0.7053982
3 01003       1   4  7.4307781 0.5383016 1.0527138 1.3203218
4 01004       1   6  6.3549654 0.9441436 0.6153434 0.7681720
5 01006       1   0  0.9337634 0.0000000 0.0000000 0.0000000
6 01008       1   2  3.9404795 0.5075524 0.0000000 1.2496763
## Define the sf object ##
Carto_SpainMUN$obs <- NULL
Carto_SpainMUN$exp <- NULL
Carto_SpainMUN$SMR <- NULL

carto <- merge(Carto_SpainMUN,data,by="ID")
head(carto)
Simple feature collection with 6 features and 15 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 485318 ymin: 4727428 xmax: 543317 ymax: 4779153
Projected CRS: ETRS89 / UTM zone 30N
     ID                                    name           area    perimeter
1 01001                        Alegria-Dulantzi 19913794 [m^2] 34372.11 [m]
2 01002                                 Amurrio 96145595 [m^2] 63352.32 [m]
3 01003                                 Aramaio 73338806 [m^2] 41430.46 [m]
4 01004                              Artziniega 27506468 [m^2] 22605.22 [m]
5 01006                                 Arminon 10559721 [m^2] 17847.35 [m]
6 01008 Arrazua-Ubarrundia (San Martin de Ania) 57502811 [m^2] 64968.81 [m]
      region    Global        k0        k1        k2 disease obs        exp
1 Pais Vasco 0.6970881 0.6698504 0.7499087 0.7500293       1   3  6.6147794
2 Pais Vasco 0.8798865 0.8690947 0.8553925 0.8649642       1  41 42.6337564
3 Pais Vasco 0.8392771 0.8308351 0.8466912 0.8484672       1   4  7.4307781
4 Pais Vasco 0.7506202 0.7505333 0.7688731 0.7321796       1   6  6.3549654
5 Pais Vasco 0.6465866 0.5997220 0.6197513 0.6350914       1   0  0.9337634
6 Pais Vasco 0.7159123 0.7037665 0.7332383 0.7338377       1   2  3.9404795
        SMR        X1        X2                       geometry
1 0.4535299 1.3051895 0.7755112 MULTIPOLYGON (((538259 4737...
2 0.9616793 1.5158172 0.7053982 MULTIPOLYGON (((503520 4760...
3 0.5383016 1.0527138 1.3203218 MULTIPOLYGON (((533286 4759...
4 0.9441436 0.6153434 0.7681720 MULTIPOLYGON (((491260 4776...
5 0.0000000 0.0000000 0.0000000 MULTIPOLYGON (((509851 4727...
6 0.5075524 0.0000000 1.2496763 MULTIPOLYGON (((534678 4746...

A character vector with the covariate names or the design matrix of the fixed effects can be included through the X=... argument of the CAR_INLA() function:

iCAR.Global <- CAR_INLA(carto=carto, ID.area="ID",
                        O="obs", E="exp", X=c("X1","X2"),
                        model="global", prior="intrinsic", inla.mode="compact")
STEP 1: Pre-processing data
STEP 2: Fitting global model with INLA (this may take a while...)
iCAR.k1 <- CAR_INLA(carto=carto, ID.area="ID",
                    O="obs", E="exp", X=c("X1","X2"),
                    model="partition", k=1, ID.group="region",
                    prior="intrinsic", inla.mode="compact")
STEP 1: Pre-processing data
STEP 2: Fitting partition (k=1) model with INLA 
+ Model 1 of 15 
+ Model 2 of 15 
+ Model 3 of 15 
+ Model 4 of 15 
+ Model 5 of 15 
+ Model 6 of 15 
+ Model 7 of 15 
+ Model 8 of 15 
+ Model 9 of 15 
+ Model 10 of 15 
+ Model 11 of 15 
+ Model 12 of 15 
+ Model 13 of 15 
+ Model 14 of 15 
+ Model 15 of 15 
STEP 3: Merging the results

Local and global estimates of the fixed effects

Summary statistics of the posterior marginal estimates for the global model’s fixed effects:

iCAR.Global$summary.fixed
                    mean          sd   0.025quant     0.5quant  0.975quant
(Intercept) -0.143417331 0.006025269 -0.155265814 -0.143405447 -0.13163644
X1           0.021966349 0.009970495  0.002404134  0.021970185  0.04150673
X2           0.001724022 0.010214102 -0.018311516  0.001726322  0.02174646
                    mode          kld
(Intercept) -0.143405365 1.075428e-09
X1           0.021970205 8.797737e-11
X2           0.001726333 6.291000e-11

In partition models, local estimates of the fixed effects coefficients are obtained in each province:

x1 <- grep("^X1",rownames(iCAR.k1$summary.fixed.partition))
head(iCAR.k1$summary.fixed.partition[x1,1:6])
              mean         sd    0.025quant     0.5quant 0.975quant
X1.01  0.034967708 0.03128508 -0.0265777357  0.035035601 0.09612675
X1.02  0.062355268 0.03189968 -0.0002381752  0.062368230 0.12487502
X1.03 -0.147629820 0.08702608 -0.3210846348 -0.146677955 0.02040395
X1.04 -0.039189169 0.07361487 -0.1841461481 -0.039028967 0.10483976
X1.05  0.010256179 0.02927238 -0.0472522952  0.010292743 0.06755640
X1.06 -0.001779868 0.01857935 -0.0382307779 -0.001773629 0.03463554
              mode
X1.01  0.035035951
X1.02  0.062368323
X1.03 -0.146675963
X1.04 -0.039033375
X1.05  0.010292892
X1.06 -0.001773591
x2 <- grep("^X2",rownames(iCAR.k1$summary.fixed.partition))
head(iCAR.k1$summary.fixed.partition[x2,1:6])
              mean         sd  0.025quant     0.5quant  0.975quant         mode
X2.01  0.007462992 0.03193025 -0.05520724  0.007481908 0.070025571  0.007482009
X2.02 -0.063245366 0.03581039 -0.13351584 -0.063229525 0.006934882 -0.063229463
X2.03  0.063799000 0.07849492 -0.09182309  0.064345649 0.216300292  0.064343504
X2.04 -0.081429898 0.08112018 -0.24072841 -0.081386680 0.077626469 -0.081385550
X2.05 -0.006809512 0.02774534 -0.06128699 -0.006785615 0.047532025 -0.006785469
X2.06  0.008002147 0.01720290 -0.02573016  0.008001615 0.041737491  0.008001614
## Maps with posterior median estimates at each province
carto.CCAA <- aggregate(Carto_SpainMUN[,"geometry"],list(ID.group=st_drop_geometry(Carto_SpainMUN)$region), head)

carto.CCAA$X1 <- iCAR.k1$summary.fixed.partition$`0.5quant`[x1]
carto.CCAA$X2 <- iCAR.k1$summary.fixed.partition$`0.5quant`[x2]

paleta <- c(brewer.pal(3,"Reds")[3:2],brewer.pal(3,"Blues")[2:3])
values <- seq(-0.2,0.2,0.1)

if(tmap4){
  tm_shape(carto.CCAA) +
    tm_polygons(fill=c("X1","X2"), fill.free=FALSE,
                fill.scale=tm_scale(values=paleta, breaks=values, interval.closure="left"),
                fill.legend=tm_legend("", show=TRUE, reverse=TRUE, frame=FALSE,
                                      position=tm_pos_out("right","center"))) + 
    tm_title("Posterior median estimates") + 
    tm_layout(panel.labels=c("X1 covariate","X2 covariate")) +
    tm_facets(nrow=1, ncol=2)
}else{
  tm_shape(carto.CCAA) + 
  tm_polygons(col=c("X1","X2"), palette=paleta,
              title="", legend.show=T, legend.reverse=T,
              style="fixed", breaks=values, interval.closure="left") + 
  tm_layout(main.title="Posterior median estimates", main.title.position="center",
            legend.outside=T, legend.outside.position="right", legend.frame=F,
            panel.labels=c("X1 covariate","X2 covariate"),
            legend.outside.size=0.2, outer.margins=c(0.02,0.01,0.02,0.01)) + 
  tm_facets(nrow=1, ncol=2)
}

Global estimates can be also computed by combining the marginal estimates in each partition by applying the CMC algorithm:

rbind(Global=iCAR.Global$summary.fixed["X1",1:5],
      `k1-CMC`=iCAR.k1$summary.fixed["X1",1:5])
             mean          sd  0.025quant   0.5quant 0.975quant
Global 0.02196635 0.009970495 0.002404134 0.02197019 0.04150673
k1-CMC 0.01879867 0.009570760 0.000165514 0.01876862 0.03770261
rbind(Global=iCAR.Global$summary.fixed["X2",1:5],
      `k1-CMC`=iCAR.k1$summary.fixed["X2",1:5])
               mean          sd  0.025quant     0.5quant 0.975quant
Global  0.001724022 0.010214102 -0.01831152  0.001726322 0.02174646
k1-CMC -0.005782615 0.009685168 -0.02506193 -0.005673128 0.01288685