borg_cv(strategy = "group_fold") now assigns groups to folds by their
label rather than by position. Numeric group identifiers whose values were
not 1:n_groups (e.g. site codes) previously produced empty test folds and
full-data training sets.spatial_block, environmental_block,
leave_location_out, llto, knndm, custom_block, random) now accept a
seed argument threaded from borg_cv(seed = ) and borg_repeated_cv()
instead of a hardcoded internal seed. Repeated CV now produces genuinely
distinct fold sets across repeats for every strategy.borg_block_size() now varies the folds with the candidate block size (the
block size drives the number of spatial clusters), so the reported optimum
reflects the data rather than the search grid.v test blocks yield up to v - 1 usable folds.borg_conformal(method = "split") refits the model on the complement of the
calibration set so the nonconformity scores are genuinely out-of-sample, and
uses the conformal order statistic (type = 1) for the quantile. Split
intervals now reach their nominal coverage.borg_di() / borg_aoa() follow Meyer & Pebesma (2021): the dissimilarity
index is normalized by the mean pairwise training distance, and the
applicability threshold is the outlier-adjusted maximum (Q75 + 1.5 * IQR) of
the cross-validated training DI.borg_cv() now threads the CRS to the buffer,
and borg_block_size() / borg_check_residuals() accept a crs argument.borg_willmott() computes the refined index d1 with the correct
denominator; borg_local_moran() uses conditional permutation for its
pseudo p-values.borg_conformal, borg_aoa, borg_willmott, borg_calibration,
borg_bootstrap, borg_debias).plot() and autoplot() for borg_result now offer the same set of plot
types (split, risk, spatial, temporal, groups).borg_cv(strategy = "nndm", prediction_points = ...) implements the
leave-one-out NNDM scheme of Mila et al. (2022): each held-out point grows an
exclusion radius until the test-to-train nearest-neighbour distance
distribution matches the prediction-to-sample distribution, retaining at
least half the data per fold. Complements the existing "knndm" k-fold form."knndm" and "nndm" now shares one
internal helper.borg_clustered_sample() draws parent-offspring clustered point samples
over a bounding box, coordinate frame, sf polygon, or SpatVector. Useful
for simulations and for reproducing the spatial dependence that random CV
understates.borg_aoa(normalize = TRUE) adds a di_norm column rescaling the
dissimilarity index by the AOA threshold, so di_norm = 1 marks the
applicability boundary and values are comparable across models.show(BorgRisk) now prints actionable suggested fixes for each detected riskas.data.frame(BorgRisk) includes a suggested_fix columnborg_assimilate() are labeled with the auto-fix callautoplot(BorgRisk): Lollipop chart with fix annotations, point size encodes affected indicesautoplot(borg_result, type = "temporal"): New temporal split visualization with look-ahead violation detectionautoplot(borg_result, type = "groups"): New group assignment bar chart with overlap highlightingautoplot(BorgDiagnosis): Richer panel with detection threshold gauge barstidyterra::geom_spatvector() for native SpatVector rendering when availablesf objects preserve geometry directly (no coordinate extraction + reconstruction round-trip)tidyterra to SuggestsThis release replaces custom functions with standard R S3 methods for a more idiomatic interface.
plot(BorgRisk): Visualize risk assessment resultsplot(borg_result): Visualize CV fold splitsplot(borg_comparison): Compare random vs blocked CV resultssummary(BorgDiagnosis): Generate methods section text for publicationssummary(BorgRisk): Summarize detected riskssummary(borg_result): Generate methods text from borg() outputsummary(borg_comparison): Detailed comparison summaryborg_certificate(): Create structured validation certificateborg_export(): Write certificate to YAML/JSON fileborg_plot() - use plot() insteadborg_report() - use summary(), borg_certificate(), or borg_export()plot_split, plot_risk, etc.)borg_methods_text)BORG-guarded versions of common CV functions that block random CV when dependencies detected:
borg_vfold_cv(): Wraps rsample::vfold_cv() with dependency checking
auto_block = TRUE automatically switches to appropriate blocked CVallow_override = TRUE allows proceeding with warningborg_group_vfold_cv(): Wraps rsample::group_vfold_cv() with additional checks
borg_initial_split(): Wraps rsample::initial_split()
time specifiedborg_trainControl(): Wraps caret::trainControl()
borg_register_hooks(): Register validation hooks on framework functionsborg_unregister_hooks(): Remove registered hooksborg_compare_cv(): Run random vs blocked CV on the same data to empirically demonstrate metric inflation
borg_methods_text(): Generate copy-paste methods section text for manuscripts
borg_certificate(): Create structured validation certificates
borg_export(): Export certificates to YAML or JSON format
borg() entry point with two modes:
Diagnosis mode: borg(data, coords=, time=, groups=) returns diagnosis + CV folds
Validation mode: borg(data, train_idx=, test_idx=) validates existing splits
temporal_col → time, group_col → groups, spatial_cols → coordsBORG now detects data dependency structure and enforces appropriate cross-validation strategies. Random CV is blocked when dependencies are detected.
borg_diagnose(): Automatically detects data dependency structure
BorgDiagnosis S4 class: Structured diagnosis results with slots for:
dependency_type: "none", "spatial", "temporal", "clustered", "mixed"severity: "none", "moderate", "severe"recommended_cv: appropriate CV strategyinflation_estimate: estimated AUC/RMSE bias from random CVborg_cv(): Generates valid CV schemes based on diagnosis
Spatial blocking: k-means clustering with block size > autocorrelation range
Temporal blocking: chronological splits with embargo periods
Group CV: leave-group-out with balanced fold assignment
Mixed strategies: spatial-temporal, spatial-group, temporal-group
Random CV disabled when dependencies detected (requires explicit allow_random = TRUE)
Output formats: list, rsample, caret, mlr3
plot_split(): Visualize train/test split distribution with temporal or group structureplot_risk(): Display risk assessment results as horizontal bar chartplot_temporal(): Timeline visualization with gap analysis and look-ahead detectionplot_spatial(): Spatial split visualization with convex hullsplot_groups(): Group-based split visualization with leakage highlightingborg_inspect() to support fitted model objects:
lm and glm models (checks data used in fitting)ranger random forest modelsxgboost modelslightgbm modelsparsnip model fitsworkflow objects (tidymodels)audit_predictions(): Validate prediction vectors against expected indicescv_leakage_report(): Generate detailed cross-validation leakage reportsaudit_importance(): Detect feature importance computed on test data (SHAP, permutation)tune_results inspection for tidymodels tuning objectsborg_auto_check() to enable/disable automatic validationborg_options() to query current configurationborg.auto_check, borg.strict, borg.verboseInitial release.
borg_guard(): Creates a validation context for train/test splits with
support for temporal, spatial, and grouped structuresborg_validate(): Comprehensive workflow validation including:
borg_inspect(): Inspects preprocessing objects for data leakage:
caret preProcess objects
caret trainControl objects
tidymodels recipe objects
prcomp PCA objects
rsample resampling objects
borg_assimilate(): Assimilates leaky pipelines into compliance (auto-fix)BorgRisk S4 class for structured risk assessment reportspreProcess, trainControl, train objectsrecipe, rsplit, vfold_cv, rset objects