Creates cross-validation folds that respect data dependency structure. When spatial, temporal, or clustered dependencies are detected, random CV is disabled and appropriate blocking strategies are enforced.
Usage
borg_cv(
data,
diagnosis = NULL,
v = 5,
coords = NULL,
time = NULL,
groups = NULL,
target = NULL,
env = NULL,
dist_mat = NULL,
prediction_points = NULL,
block_size = NULL,
embargo = NULL,
buffer = NULL,
strategy = NULL,
repeats = 1L,
seed = NULL,
output = c("list", "rsample", "caret", "mlr3"),
allow_random = FALSE,
verbose = FALSE
)Arguments
- data
A data frame to create CV folds for.
- diagnosis
A
BorgDiagnosisobject fromborg_diagnose. If NULL, diagnosis is performed automatically.- v
Integer. Number of folds. Default: 5.
- coords
Character vector of length 2 specifying coordinate column names. Required for spatial blocking if diagnosis is NULL.
- time
Character string specifying the time column name. Required for temporal blocking if diagnosis is NULL.
- groups
Character string specifying the grouping column name. Required for group CV if diagnosis is NULL.
- target
Character string specifying the response variable column name.
- env
Environmental covariates for environmental blocking. A
SpatRaster, data frame, or matrix with one row per observation. Required whenstrategy = "environmental_block"or"spatial_plus".- dist_mat
A distance matrix or
distobject for custom blocking. Must be ann x nmatrix matchingnrow(data). Required whenstrategy = "custom_block".- prediction_points
Data frame, matrix,
SpatVector, orsfobject with coordinates of prediction locations. Required whenstrategy = "knndm"or"nndm", which match cross-validation fold geometry to the prediction task.- block_size
Numeric. For spatial blocking, the minimum block size. If NULL, automatically determined from diagnosis. Should be larger than the autocorrelation range.
- embargo
Integer. For temporal blocking, minimum gap between train and test. If NULL, automatically determined from diagnosis.
- buffer
Numeric. Spatial buffer distance (in coordinate units). Training points within this distance of any test-fold point are removed to reduce autocorrelation leakage. Default: NULL (no buffer).
- strategy
Character. Override the auto-detected CV strategy. Use
"temporal_expanding"for expanding window (forward-chaining) or"temporal_sliding"for fixed-size sliding window. Default: NULL (auto-detect from diagnosis).- repeats
Integer. Number of times to repeat CV fold generation with different random seeds. Default: 1 (no repetition).
- seed
Integer or NULL. Random seed for stochastic fold generators. When
NULL(default), a fixed internal seed is used so single runs are reproducible. Withrepeats > 1, successive repeats derive distinct seeds from this value.- output
Character. Output format: "list" (default), "rsample", "caret", "mlr3".
- allow_random
Logical. If TRUE, allows random CV even when dependencies detected. Default: FALSE. Setting to TRUE requires explicit acknowledgment.
- verbose
Logical. If TRUE, print diagnostic messages. Default: FALSE.
Value
Depending on output:
- "list"
A list with elements:
folds(list of train/test index vectors),n(number of observations),diagnosis(the BorgDiagnosis used),strategy(CV strategy name),params(parameters used).- "rsample"
An
rsamplersetobject compatible with tidymodels.- "caret"
A
trainControlobject for caret.- "mlr3"
An
mlr3Resamplingobject.
Details
The Enforcement Principle
Unlike traditional CV helpers, borg_cv enforces valid evaluation:
If spatial autocorrelation is detected, random CV is disabled
If temporal autocorrelation is detected, random CV is disabled
If clustered structure is detected, random CV is disabled
To use random CV on dependent data, you must set
allow_random = TRUEand provide justification (this is logged).
Spatial Blocking
When spatial dependencies are detected, data are partitioned into spatial blocks using k-means clustering on coordinates. Block size is set to exceed the estimated autocorrelation range. This ensures train and test sets are spatially separated.
Temporal Blocking
When temporal dependencies are detected, data are split chronologically with an embargo period between train and test sets. This prevents information from future observations leaking into training.
Group CV
When clustered structure is detected, entire groups (clusters) are held out together. No group appears in both train and test within a fold.
Distance Matching (kNNDM and NNDM)
With strategy = "knndm" or "nndm" and prediction_points,
folds are shaped so the distribution of test-to-train nearest-neighbour
distances matches the prediction-to-sample nearest-neighbour distribution.
"knndm" (Linnenbrink et al. 2024) produces v folds and scales
to large samples; "nndm" (Mila et al. 2022) is the leave-one-out
form, growing an exclusion radius around each held-out point until the two
distance distributions align, subject to retaining at least
min_train (default 0.5) of the data per fold. NNDM builds an
n x n distance matrix and is best suited to samples up to a few
thousand points; prefer "knndm" beyond that.
Examples
# Spatial data with autocorrelation
set.seed(42)
spatial_data <- data.frame(
x = runif(200, 0, 100),
y = runif(200, 0, 100),
response = rnorm(200)
)
# Diagnose and create CV
cv <- borg_cv(spatial_data, coords = c("x", "y"), target = "response")
str(cv$folds) # List of train/test indices
# Clustered data
clustered_data <- data.frame(
site = rep(1:20, each = 10),
value = rep(rnorm(20, sd = 2), each = 10) + rnorm(200, sd = 0.5)
)
cv <- borg_cv(clustered_data, groups = "site", target = "value")
cv$strategy # "group_fold"
# Get rsample-compatible output for tidymodels
# \donttest{
cv_rsample <- borg_cv(spatial_data, coords = c("x", "y"), output = "rsample")
# }