NEWS
SpatialML 1.8.2 (2026-07-06)
Packaging
- Added the
.Rbuildignore file so that top-level development artefacts
(the RStudio project file, the technical notes document, local tool
settings and cran-comments.md) are excluded from the source tarball.
The 1.8.1 release notes stated this exclusion was already in place,
but the file itself was missing; R CMD check --as-cran consequently
reported NOTEs about hidden and non-standard top-level files. Both
NOTEs are now resolved.
- Added
cran-comments.md (not shipped in the tarball) documenting the
test environments and the resubmission context.
DESCRIPTION metadata
- Added the maintainer's ORCID iD to
Authors@R.
- Simplified the roles of Stefanos Georganos to
"aut" (the previous
c("aut", "ctb") was redundant).
- Added
Language: en-GB, matching the British spelling used
throughout the documentation.
Documentation
- The
\donttest{} examples of grf() and predict.grf() now set
nthreads = 1 explicitly. This was already CRAN-compliant (ranger
defaults to two threads) and is purely a defensive clarification.
SpatialML 1.8.1
CRAN Resubmission
- Prepared the package for CRAN resubmission after archival. The known
CRAN archival issue was an Rd cross-reference NOTE for unanchored
external links to
ranger; all such references now use
\link[ranger]{ranger}.
- Version and date updated to 1.8.1 / 2026-06-09.
- Top-level development artefacts are excluded from
R CMD build
through .Rbuildignore.
- Removed "active development" wording from help pages to better match
CRAN's publication-quality expectation.
Dependency Reduction
- The package now depends only on
R in Depends: and imports
ranger, stats, graphics and utils.
- Removed the runtime dependencies on
caret and randomForest.
The two affected functions, rf.mtry.optim() and grf.bw(), are now
implemented directly with ranger and base R helpers.
- Replaced broad namespace exports/imports with explicit
export(), S3method() and importFrom() declarations.
grf() Robustness
grf() no longer repeatedly refits local forests when ranger
returns a NaN out-of-bag prediction for the focal observation.
The default fallback is now a leave-one-out local refit: the focal row
is removed from the local training subset and predicted out-of-sample.
This preserves finite local diagnostics without noisy console output.
- Added
oob.fallback = c("loo", "inbag") to grf(). The default
"loo" uses the new leave-one-out fallback; "inbag" reproduces the
older in-sample fallback behaviour.
- The focal observation is now forced to be the first row of each local
subset before reading
ranger's first training prediction. This avoids
incorrect focal OOB extraction when two or more observations share the
same coordinates.
- Degenerate zero-distance local kernels now receive equal weights
instead of producing non-finite bi-square weights.
- The local-fit loop no longer rebuilds a full copy of
dframe on every
iteration. Local neighbourhoods are indexed by row position, reducing
memory traffic for medium-sized data sets.
- Added validation for
coords, bw, ntree, kernel and formula
inputs, plus clearer fixed-bandwidth diagnostics when too few
neighbours are available.
grf() now returns an object of class "grf" so predict() dispatches
to predict.grf().
LocalModelSummary now reports AIC and AICc for both OOB and
predicted residuals.
Bandwidth and mtry Selection
grf.bw() no longer uses caret::postResample(). Its Mixed and
Low.Local diagnostics are computed by an internal base R helper
equivalent to squared correlation.
grf.bw() returns Best.BW = NA_real_ with an informative warning
when every evaluated bandwidth produces a non-finite local R-squared,
instead of returning numeric(0).
grf.bw() gains verbose = TRUE, allowing bandwidth-search progress
messages to be suppressed in tests, vignettes and batch scripts.
grf.bw() now caps an over-large mtry at the number of predictors
and uses a one-predictor-safe default.
rf.mtry.optim() gains the arguments num.trees, cv.repeats,
num.threads and verbose, and supports three evaluation strategies
via cv.method: "oob" (default), "cv", "repeatedcv".
rf.mtry.optim() no longer returns a caret train object. The new
return value is a list with best.mtry, results, cv.method,
num.trees and call. Code that read out$bestTune$mtry should now
read out$best.mtry.
Documentation, Examples and Tests
- Added a
tests/testthat/ test suite (testthat 3rd edition) covering
the public API of every exported function.
- Added a vignette,
vignettes/SpatialML.Rmd, with a complete workflow:
mtry tuning, bandwidth search, GRF fit, local-importance plotting
and prediction at new locations.
- The vignette now uses the
knitr::knitr engine with markdown
output, avoiding the RStudio/Quarto/Pandoc probe path during local
package checks.
- The
\donttest{} examples in grf.Rd, grf.bw.Rd,
predict.grf.Rd and rf.mtry.optim.Rd now use small, single-threaded
examples suitable for CRAN checks. Heavier Income demonstrations are
kept in \dontrun{} blocks.
- The maintainer's website (https://stamatisgeoai.eu/) is linked from
the package help page and vignette in addition to
DESCRIPTION.
SpatialML 1.7.0
CRAN compliance
- Fixed the missing package anchors in Rd cross-references that triggered
the CRAN archival on 2025-11-28: every
\link{ranger} is now
\link[ranger]{ranger} (in grf.Rd, grf.bw.Rd, predict.grf.Rd and
SpatialML-package.Rd).
- Moved the heavy run-time dependencies (
ranger, caret,
randomForest) from Depends to Imports in line with current CRAN
best practice. Depends now contains only the minimum R version.
- Replaced
exportPattern("^[[:alpha:]]+") in NAMESPACE with explicit
export() statements; removed the unused import(randomForest) in
favour of a narrow importFrom().
- Added explicit
stats:: and graphics:: namespacing to all internal
calls (predict, formula, terms, setNames, dist, sd,
rnorm, rpois, runif, plot).
- Added a package-level help page (
?SpatialML).
- Switched URLs and DOIs in the documentation to the canonical
\doi{...} macro.
Bug fixes
grf(): pre-allocation of the local-forest list previously read
as.list(rep(NA, length(ntrees))), producing a one-element list
because ntrees is a scalar; fixed to vector("list", Obs).
grf(): replaced subset(DataSetSorted, DNeighbour <= bw) with
bracket indexing to avoid the standard CRAN check NOTE about
non-standard evaluation.
grf(): the function now returns an object of class "grf" so that
predict(obj, ...) dispatches correctly to predict.grf() without
the user having to call the S3 method directly.
random.test.data(): when dep.var.dis = "normal" the dependent
variable is now drawn with rnorm() (was incorrectly drawn with
runif()).
random.test.data(): fixed the operator-precedence bug
for (i in 1:vars.no - 1) (which evaluated to 0:(vars.no - 1)); the
predictor matrix is now filled vectorised and column-named
X1, X2, ....
predict.grf(): replaced object[[1]] by object$Global.Model;
validates that object$Forests exists and that x.var.name /
y.var.name match columns of new.data; ... is now propagated to
both global and local predict() calls.
rf.mtry.optim(): caret::trainControl() arguments are now passed by
name (cv.method was previously matched positionally and could land
in the wrong slot).
New features and improvements
grf(), grf.bw(), random.test.data(): added match.arg()-based
validation for the kernel and dep.var.dis arguments and explicit
validation of coords, bw, ntree, dataset and step.
grf(): improved diagnostic stop messages when the fixed bandwidth
yields too few neighbours.
grf(): returned LocalModelSummary now also reports AIC and AICc
for both OOB and predicted residuals.
rf.mtry.optim(): new plot.it = TRUE argument lets the user disable
plotting when running non-interactively or in vignettes.
- Removed every hard-coded
set.seed() from inside the package
functions (CRAN policy). Reproducibility is now under user control via
a set.seed() call before each function.
Documentation
- Fixed typos: "Radmom" -> "Random", "lcoal" -> "local",
"Neightbours" -> "Neighbours", "tradition" -> "traditional".
grf.Rd: the \value{} block was renamed LocalModelSummary to
match the actual returned name (was incorrectly lModelSummary).
grf.bw.Rd: the worked example used weighted = TRUE (a
non-existent argument); replaced with geo.weighted = TRUE.
predict.grf.Rd: examples now call predict() (which dispatches via
the new "grf" class) instead of the explicit predict.grf().
- Expanded the Description field of every Rd file with the bi-square
weighting equation and a step-by-step description of the algorithm.