Specify a conditional autoregressive (CAR) spatial random effect. Supports both intrinsic CAR (ICAR) and proper CAR variants.
Arguments
- adjacency
Adjacency matrix (sparse or dense). A symmetric matrix where entry (i,j) is 1 if areas i and j are neighbors, 0 otherwise.
- level
Level at which spatial structure applies:
"group": Spatial effect at the grouping variable level (e.g., sites). Requiresgroup_varto be specified."obs": Spatial effect at the observation level.
- group_var
Name of the grouping variable in data (required if
level = "group").- proper
Logical; if FALSE (default), uses Intrinsic CAR (ICAR) with rho = 1 fixed. If TRUE, uses proper CAR with rho estimated. See Details.
Logical; if TRUE (default), spatial effect enters both numerator and denominator linear predictors identically.
- parameterization
Parameterization of the spatial random effect. Either
"standard"(default) or"collapsed"to marginalize the spatial variance for improved mixing in sparse-graph regimes.
Details
The CAR model specifies that:
$$\phi_i | \phi_{-i} \sim N\left(\rho \frac{\sum_{j \sim i} \phi_j}{n_i}, \frac{\sigma^2}{n_i}\right)$$
where \(n_i\) is the number of neighbors of area i and \(j \sim i\) denotes that j is a neighbor of i.
This leads to a precision matrix: $$Q = \tau (D - \rho W)$$
where D is the diagonal matrix of neighbor counts and W is the adjacency matrix.
ICAR (proper = FALSE, default)
Sets rho = 1 (fixed)
Improper prior (rank-deficient Q)
Requires sum-to-zero constraint for identifiability
Simpler: one fewer parameter to estimate
Standard choice for disease mapping
Equivalent to RW1 on a graph
Proper CAR (proper = TRUE)
Estimates rho in (0, 1) from data
Proper prior (integrates to 1)
rho measures spatial autocorrelation strength
rho -> 0: approaches independence (IID)
rho -> 1: approaches ICAR
More flexible but additional parameter to estimate
Prior: rho ~ Beta(1, 1) (uniform on (0, 1))
See also
spatial_bym2() for decomposed spatial + IID effects,
spatial_gp() for continuous spatial effects
Examples
# Create adjacency matrix for 10 regions (chain structure)
adj <- matrix(0, 10, 10)
for (i in 1:9) {
adj[i, i+1] <- adj[i+1, i] <- 1
}
# ICAR (default, rho = 1 fixed)
icar <- spatial_car(adj, level = "group", group_var = "site")
print(icar)
#> tulpaRatio spatial specification
#> ===========================
#>
#> Type: ICAR (Intrinsic CAR)
#> Level: group
#> Spatial units: 10
#> Shared: Yes (enters both processes)
#> Group variable: site
#> (rho fixed at 1, sum-to-zero constraint applied)
# Proper CAR (rho estimated)
proper_car <- spatial_car(adj, level = "group", group_var = "site",
proper = TRUE)
print(proper_car)
#> tulpaRatio spatial specification
#> ===========================
#>
#> Type: Proper CAR
#> Level: group
#> Spatial units: 10
#> Shared: Yes (enters both processes)
#> Group variable: site
#> Rho bounds: [0, 1]
#> (spatial autocorrelation parameter, estimated from data)
# \donttest{
# Generate synthetic data with spatial structure
set.seed(123)
n_sites <- 10
n_per_site <- 5
df <- data.frame(
site = rep(1:n_sites, each = n_per_site),
x = rnorm(n_sites * n_per_site),
count = rpois(n_sites * n_per_site, 20),
effort = rgamma(n_sites * n_per_site, shape = 5, rate = 1)
)
# ICAR model (standard disease mapping approach)
fit_icar <- tratio(
count | effort ~ x,
data = df,
family = ratiod_poisson_gamma(),
spatial = spatial_car(adj, level = "group", group_var = "site"),
mode = "hmc",
control = list(iter = 200, warmup = 100, chains = 1)
)
#> Inference: Exact (Tier 1)
#> Backend: hmc
#> Fitting ratio model...
#> Family: poisson_gamma
#> Observations: 50
#> Iterations: 200 (warmup: 100)
#> Running NUTS sampler...
#> Parameters: 16
#> Iterations: 200 (warmup: 100)
#> Chains: 1 (cores: 1)
#> Spatial: icar (10 units)
# Proper CAR model (estimate spatial autocorrelation)
fit_car <- tratio(
count | effort ~ x,
data = df,
family = ratiod_poisson_gamma(),
spatial = spatial_car(adj, level = "group", group_var = "site",
proper = TRUE),
mode = "hmc",
control = list(iter = 200, warmup = 100, chains = 1)
)
#> Inference: Exact (Tier 1)
#> Backend: hmc
#> Fitting ratio model...
#> Family: poisson_gamma
#> Observations: 50
#> Iterations: 200 (warmup: 100)
#> Running NUTS sampler...
#> Parameters: 17
#> Iterations: 200 (warmup: 100)
#> Chains: 1 (cores: 1)
#> Spatial: car_proper (10 units)
# Extract rho from proper CAR
summary(fit_car) # Shows rho_spatial parameter
#> ratio model summary
#> ===================
#>
#> Inference: Exact (Tier 1) via hmc
#> Family: poisson_gamma
#>
#> Fixed effects (numerator):
#> parameter mean sd 2.5% 97.5% rhat ess_bulk
#> beta_num[1] 3.025 0.043 2.937 3.094 1.135 6
#> beta_num[2] -0.029 0.028 -0.086 0.022 1.015 51
#>
#> Fixed effects (denominator):
#> parameter mean sd 2.5% 97.5% rhat ess_bulk
#> beta_denom[1] 1.609 0.066 1.494 1.736 1.037 25
#> beta_denom[2] 0.002 0.070 -0.110 0.173 0.996 68
#>
#> Variance components:
#> parameter mean sd 2.5% 97.5% rhat ess_bulk
#> rho_spatial 0.483 0.296 0.059 0.936 1.019 19
#> shape 4.855 0.879 3.264 6.584 0.998 51
#> tau_spatial 194.159 99.607 46.585 408.022 1.376 37
#>
#> Diagnostics:
#> Divergences: 0
#> Avg. acceptance: 0.928
#> Chains: 1
#> Iterations: 200
#> Warmup: 100
# }