--- title: "Estimating causal effects under spatial confounding and interference" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Estimating causal effects under spatial confounding and interference} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4) ``` ## The problem In spatial observational studies two phenomena often occur together: * **Spatial confounding (SC):** an *unmeasured* spatial variable `U(s)` drives both the treatment `Z` and the outcome `Y`, so conditioning on the measured covariates `X` alone does not close the backdoor path. * **Spatial interference (SI):** a unit's outcome depends on its *neighbours'* treatment, summarised through a neighbourhood-exposure mapping `E_i = Σ_j G_ij Z_j`. Methods that address only one of the two are biased when both are present. This package implements two estimators that handle them **simultaneously**. ```{r setup} library(spaci) ``` ## Simulate data `simulate_spatial_causal()` draws data in which `U(s)` is an exponential Gaussian random field, treatment depends on `U(s)`, and the outcome depends on both `U(s)` and neighbourhood exposure. The true ATT is 2. ```{r simulate} sim <- simulate_spatial_causal(n = 250, delta_u = 2.0, tau_exp = 0.1, seed = 1) str(sim, max.level = 1) ``` ## Estimate the ATT with every method ```{r estimate} res <- spatial_ate(sim$Y, sim$Z, sim$X, sim$coords, tau = 0.1, seed = 1) res ``` The naive propensity score ignores both SC and SI and is the most biased; `iDAPS` and `recoverU+` adjust for both and sit closest to the true ATT of 2. ## Visualising the comparison `plot_ate()` draws a forest plot of the estimates and their confidence intervals, with a reference line at zero and (optionally) the true effect. ```{r forest, fig.alt = "Forest plot of ATT estimates by method"} plot_ate(res, true_att = sim$true_att) ``` ## iDAPS in detail `idaps()` matches on the composite distance and reports the data-driven weights `(π₁, π₂, π₃)` on the propensity-score, spatial and interference components. ```{r idaps} fit <- idaps(sim$Y, sim$Z, sim$X, sim$coords, tau = 0.1, seed = 1) fit fit$weights ``` ## recoverU+ in detail `recoverUplus()` recovers the spatial confounder from the residual Matérn field and augments the doubly robust estimator with it and the exposure term. The recovered confounder is returned for inspection. ```{r recoverU} fp <- recoverUplus(sim$Y, sim$Z, sim$X, sim$coords, tau = 0.1) fp head(fp$extras$Uhat) ``` ## A small simulation study Averaging over repeated data sets recovers the bias/MSE ordering reported in the paper (`recoverU+` and `iDAPS` beat the naive comparator). ```{r montecarlo, eval = FALSE} methods <- c("Naive PS", "DAPS", "iDAPS", "recoverU", "recoverU+") nsim <- 200; true <- 2 store <- matrix(NA, nsim, length(methods), dimnames = list(NULL, methods)) for (s in seq_len(nsim)) { d <- simulate_spatial_causal(n = 250, delta_u = 2.0, tau_exp = 0.1) store[s, ] <- spatial_ate(d$Y, d$Z, d$X, d$coords, seed = s)$ATT } data.frame(Method = methods, Bias = round(colMeans(store - true, na.rm = TRUE), 3), MSE = round(colMeans((store - true)^2, na.rm = TRUE), 3)) ```