8. Maintainer Contact
- Lead Author & Maintainer: Ahmed Sattar Jabbar
- Email: [email protected]
- ORCID: 0009-0006-4614-735X
- GitHub Repository: amjed-droid/spconform
Welcome to the spconform help and troubleshooting guide. Whether you are fitting spatial conformal prediction intervals for the first time, diagnosing empirical coverage, or interfacing custom machine learning models, this guide provides answers to common questions, error diagnoses, model integration recipes, and guidelines for reporting issues.
| Need | Recommended Channel | Details |
|---|---|---|
| Bug Reports & Crashes | GitHub Issues | Provide a minimal reproducible example
(reprex) and sessionInfo(). |
| Model Advice & Theory | GitHub Issues (Question) | Questions on spatial exchangeability, choice of kernel, or sample size. |
| Feature Requests | GitHub Issues (Enhancement) | Propose new diagnostic metrics, weight kernels, or interface integrations. |
| Academic Inquiries | Direct Email | Reach maintainer Ahmed Sattar Jabbar at
[email protected]. |
Not necessarily. Conformal prediction guarantees valid marginal coverage in expectation: \[P\left(Y_{n+1} \in \widehat{C}(S_{n+1})\right) \ge 1 - \alpha\] For any finite test evaluation set of size \(m\), the observed empirical coverage follows a Binomial distribution \(\text{Binom}(m, 1 - \alpha)\) with standard error: \[\text{SE} = \sqrt{\frac{\alpha(1 - \alpha)}{m}}\] For example, with \(m = 100\) and nominal coverage \(90\%\) (\(\alpha = 0.10\)), the standard error is \(\sqrt{0.1 \times 0.9 / 100} = 0.03\) (\(3\%\)). An observed coverage between \(84\%\) and \(96\%\) falls well within normal \(95\%\) binomial sampling variation. You can compute the exact binomial confidence interval via:
scp_geostatistical() or
scp_areal()?scp_geostatistical() when observations have
continuous coordinates \((x, y)\) or
\((\text{lon}, \text{lat})\), such as
weather stations, air quality sensors, or soil core samples.scp_areal() when data are aggregated over discrete
spatial units (counties, municipalities, census tracts, or lattice grid
cells) where relationships are defined by an adjacency matrix \(W\).scp_geostatistical(), weights decay as \(w_i = \exp(-\|s_0 - s_i\|^2 / (2h^2))\).
bandwidth = NULL) employs the median
pairwise distance heuristic, which provides a robust balance for
isotropic spatial domains.k_neighbors): In spconform 0.1.2+,
for large calibration datasets (\(N >
1000\)), setting e.g. k_neighbors = 50 restricts
kernel weighting to the 50 closest calibration stations, accelerating
computation up to 50x while preserving asymptotic validity.spconform support spatio-temporal data?Yes. Supply t_train and t0
alongside coordinates in scp_geostatistical():
out <- scp_geostatistical(
s_train = s_train, y_train = y_train, s0 = s_test,
pred_fun = my_st_predictor,
t_train = t_train, t0 = t_test,
temporal_bandwidth = 7, # e.g. 7 days
alpha = 0.1
)diagnose())The diagnose() function conducts five audits on spatial
prediction intervals:
coverage: Fraction of true values
falling within \([L(s_0), U(s_0)]\).
Should be \(\ge 1 - \alpha\).mean_width vs
median_width: If the mean width is substantially
larger than the median, spatial outliers or high-uncertainty boundary
clusters are inflating interval widths.A strictly proper scoring rule balancing interval sharpness and miscoverage penalties: \[\text{WIS}_\alpha(l, u, y) = (u - l) + \frac{2}{\alpha}(l - y)\mathbf{1}(y < l) + \frac{2}{\alpha}(y - u)\mathbf{1}(y > u)\] Lower scores indicate superior predictive performance (narrower intervals with minimal violations).
Partitions the 2D spatial bounding box into \(n \times n\) quadrants (default \(4 \times 4 = 16\)). * Inspect whether any specific quadrant suffers severe localized under-coverage (e.g. coverage \(< 75\%\)). * Local deficits often highlight unobserved spatial covariates or sharp topographical transitions.
Examines whether intervals near the edge of the spatial domain
experience degraded coverage due to spatial extrapolation.
diagnose() partitions test points into
Interior vs. Boundary units.
Computes Moran’s \(I\) on absolute conformal residuals: * \(I \approx 0\) (\(p > 0.05\)): Nonconformity scores are spatially independent; local exchangeability holds well. * \(I > 0\) (\(p < 0.05\)): Prediction errors cluster spatially, indicating unmodeled spatial autocorrelation in the underlying point predictor.
pred_fun)spconform is strictly model-agnostic.
The pred_fun must have the signature:
function(s_train, y_train, s_new) and return a plain 1D
numeric vector of length nrow(s_new).
ranger)mgcv::gam)gstat)library(sp)
library(gstat)
pred_kriging <- function(s_train, y_train, s_new) {
sp_tr <- SpatialPointsDataFrame(coords = s_train, data = data.frame(y = y_train))
sp_te <- SpatialPoints(coords = s_new)
vgm_mod <- fit.variogram(variogram(y ~ 1, sp_tr), vgm("Exp"))
krig_out <- krige(y ~ 1, sp_tr, sp_te, model = vgm_mod, debug.level = 0)
krig_out$var1.pred
}This section provides an exhaustive guide to diagnosing and resolving
statistical, computational, and dimensional errors encountered across
scp_geostatistical(), scp_areal(), and
diagnose().
s_train and s0 must have the same number of coordinate columnsCause: The number of spatial coordinate
dimensions differs between training and query locations (for example,
passing 2D coordinates (x, y) in s_train but
3D (x, y, t) in s0).
Fix: Verify column counts prior to execution:
NA,
NaN, Inf)s_train cannot contain NA or non-finite values
or y_train contains missing valuesCause: Sensor dropouts, unrecorded responses, or missing spatial coordinates in training or target sets.
Fix: Synchronize and filter rows simultaneously
before passing data to spconform:
pred_fun) Return Types &
Single-Row Dropspred_fun must return a numeric vector of length nrow(s_new)Cause 1 (Type Mismatch): Your model’s
predict() method returns a matrix with 1
column, a data.frame, or an object with custom attributes
rather than an atomic numeric vector.
Fix 1: Always wrap the return value in
as.numeric():
Cause 2 (Single-Row Dimension Drop): Subsetting
s_new[i, ] inside pred_fun drops a 1-row
matrix to a vector, causing downstream matrix multiplications or feature
extractors to fail.
Fix 2: Always include drop = FALSE
in internal subsetting operations:
Cause: Mixing unprojected geographic coordinates (degrees of longitude and latitude) with planar coordinates (UTM meters), or passing coordinates where axes have wildly disparate scales. In unprojected coordinates, Euclidean distance fails to account for earth curvature.
Fix: Reproject coordinates to a conformal planar projection (e.g. UTM or EPSG:3857) prior to calibration:
adjacency must be a square numeric matrixCause: Passing a non-square matrix
(nrow(adjacency) != ncol(adjacency)) or an adjacency list
rather than a binary/weighted contiguity matrix.
Fix: Validate matrix dimensions:
Effective neighbourhood weight vanishingly small; falling back to unweighted quantileCause: An areal unit has no graph neighbors in the training set (e.g. an isolated island, enclaved district, or disconnected graph component with degree zero).
Fix: Audit graph connectivity. Identify isolated units and bridge graph components or adjust contiguity criteria:
split (e.g. split = 0.5 instead of
0.8), or choose an \(\alpha\) commensurate with sample size
(e.g. \(\alpha = 0.05\) or \(0.10\)).y_true must have the same length as object$predCause: Passing the entire response vector
y instead of the held-out evaluation subset corresponding
to s0.
Fix: Align evaluation indices:
s_test is required for spatial stratification and boundary auditsCause: Calling
diagnose(out, y_true = y_test) without providing query
coordinates s_test. Without coordinates,
diagnose() cannot compute spatial quadrant partitions,
convex hull boundaries, or Moran’s \(I\).
Fix: Always provide s_test:
Cause: The multi-panel diagnostic plot
(diagnose()) renders 4 to 6 visual audits simultaneously,
requiring adequate display geometry.
Fix: Open an expanded graphic window before plotting, or extract numerical diagnostics without plotting:
reprex)If you encounter unexpected behavior, please create a self-contained reproducible example:
library(spconform)
# 1. Synthetic reproducible dataset
set.seed(42)
n_tr <- 80
n_te <- 20
s_train <- matrix(runif(n_tr * 2), ncol = 2)
y_train <- sin(3 * s_train[, 1]) + rnorm(n_tr, sd = 0.2)
s_test <- matrix(runif(n_te * 2), ncol = 2)
y_test <- sin(3 * s_test[, 1]) + rnorm(n_te, sd = 0.2)
# 2. Simple baseline predictor
pfun <- function(s_tr, y_tr, s_new) {
rep(mean(y_tr), nrow(s_new))
}
# 3. Execution triggering the issue
out <- scp_geostatistical(s_train, y_train, s_test, pfun, alpha = 0.1)
cov <- coverage_report(out, y_test)
print(cov)
# 4. Environment details
sessionInfo()If you use spconform in academic research, please cite:
@Manual{spconform2026,
title = {spconform: Conformal Prediction for Spatially and Spatio-Temporally Dependent Data in R},
author = {Ahmed Sattar Jabbar},
year = {2026},
note = {R package version 0.1.2},
url = {https://CRAN.R-project.org/package=spconform},
doi = {10.32614/CRAN.package.spconform}
}diagnose())pred_fun)reprex)