Builds a prediction surface over the extent of the training data (or over a
grid you supply), predicts in chunks, and returns an sf layer.
Usage
predict_surface(
object,
grid = NULL,
cell_size = NULL,
n_cells = 10000L,
boundary = NULL,
covariates = NULL,
chunk_size = 5000L,
se = FALSE,
...
)Arguments
- object
A
spatial_fit(e.g. fromfit_gwr_model()orfit_bayesian_spatial_model()).- grid
Optional
sfPOINT layer to predict onto. WhenNULL, a regular grid is built over the training extent. Must have at least one row. It is brought into the fit's CRS first: a CRS-less grid is given the interpretation the training data got (the assumption recorded on the fit), with a warning, and then reprojected. Otherwise a CRS-less grid can land thousands of kilometres from the covariates and every cell takes the same nearest feature. A grid still without a CRS after that is treated asboundaryis: taken as EPSG:4326 and reprojected when its coordinates look like lon/lat, otherwise stamped with the fit's CRS, with a warning either way. A grid of polygons (create_grid_polygons()output, say) is reduced to one representative point per cell, ascoerce_to_points()does, so covariates are taken at the location predicted for;boundarythen keeps the cells whose point falls inside it.- cell_size
Grid resolution in CRS units. Ignored when
gridis supplied; whenNULL, derived fromn_cells. A value that would produce more than 5,000,000 cells is refused, naming the implied count and the CRS units. The usual cause is a value in the wrong unit. The grid is centred on the training bounding box and covers it: when the extent is not a whole number of cells, it overhangs the box by less than one cell, split evenly between the two sides. Acell_sizewider than the extent yields a single centred cell.- n_cells
Approximate cell count used to derive
cell_size. Default 10000. Must be a single positive finite number and at most 5,000,000; anything else is an error. Also ignored whengridis supplied. The grid you pass is used verbatim.- boundary
Optional polygonal
sf/sfc; grid points outside it are dropped. Put through the same CRS replay and reprojection asgrid. One still without a CRS after the replay is taken as EPSG:4326 and reprojected when its coordinates look like lon/lat, and is otherwise stamped with the fit's CRS, with a warning either way.- covariates
Optional
sflayer carrying the model's predictors. Required when the model has predictors andgriddoes not already contain them. Values are taken from the nearest feature. Aligned to the fit's CRS asgridis, with the same warning when it has no CRS.- chunk_size
Rows per prediction call. Default 5000. A pure performance knob: rows do not interact, and for a
bayesian_fitthe GP boundary is held at its fitted value whatever the chunk holds; seepredict.bayesian_fit.- se
Logical; also return a standard-error/posterior-SD column where the backend supports it. Default FALSE. For a
bayesian_fitthis is the SD of the posterior drawspredict()returns, and those are of the expected value by default (type = "epred"): the uncertainty of the mean surface, not of a new observation, which also carries the observation noise. For the predictive SD, the one that goes with prediction intervals andcv_bayes()'s calibration, passtype = "predict"as well.- ...
Passed to
predict(), e.g.type = "predict"for abayesian_fit. Notdraws, which this function sets itself and refuses here.
Value
An sf POINT layer with a .pred column (and
.pred_se when se = TRUE and available; one a supplied
grid already carried, from an earlier surface, is removed
otherwise). For an
auto-generated grid the resolution is attached as attribute
"cell_size". For a user-supplied grid it is only whatever
"cell_size" attribute that object already carried. That is usually
NULL, and NULL for certain if the grid had to be
re-projected, since st_transform() does not preserve custom
attributes. The resolution of a grid you built is not this function's to
infer.
Details
predict() on a spatial_fit requires newdata to be
constructed by hand, which makes the most common downstream task (produce
a map) more work than it should be. This wraps the grid construction,
covariate join, chunking and CRS handling.
Prediction over a grid is embarrassingly parallel in the sense that rows do
not interact, so it is chunked: for bayesian_fit the posterior draw
matrix is n_draws x n_newdata, which will exhaust memory on a fine
grid long before the fit itself would.
See also
Other prediction:
area_of_applicability()
Examples
# Any spatial_fit works here; a forest keeps the example free of the
# optional GWR/Stan backends.
if (requireNamespace("ranger", quietly = TRUE)) {
library(sf)
set.seed(1)
n <- 120
pts <- st_as_sf(
data.frame(x = 5e5 + runif(n, 0, 1000), y = 5e6 + runif(n, 0, 1000),
elev = rnorm(n)),
coords = c("x", "y"), crs = 32632
)
pts$price <- 10 + 0.01 * (st_coordinates(pts)[, 1] - 5e5) +
2 * pts$elev + rnorm(n)
fit <- fit_rf_model(pts, "price", "elev", num_trees = 100, seed = 1)
surf <- predict_surface(fit, n_cells = 500, covariates = pts)
print(surf[".pred"]) # one prediction per grid cell, as an sf layer
# Check where that surface is extrapolating before mapping it. The grid
# took its covariates from the nearest observation, so here nothing is
# outside; a grid with its own covariate raster is where this bites.
area_of_applicability(surf, model = fit)
}
#> Simple feature collection with 529 features and 1 field
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: 500026.7 ymin: 5000038 xmax: 500979 ymax: 5000990
#> Projected CRS: WGS 84 / UTM zone 32N
#> First 10 features:
#> .pred geometry
#> 1 11.53496 POINT (500026.7 5000038)
#> 2 11.71447 POINT (500070 5000038)
#> 3 11.71447 POINT (500113.3 5000038)
#> 4 12.06628 POINT (500156.6 5000038)
#> 5 12.06628 POINT (500199.9 5000038)
#> 6 12.06628 POINT (500243.2 5000038)
#> 7 13.07745 POINT (500286.5 5000038)
#> 8 13.07745 POINT (500329.7 5000038)
#> 9 13.07745 POINT (500373 5000038)
#> 10 11.63669 POINT (500416.3 5000038)
#> Area of applicability (Meyer & Pebesma 2021)
#>
#> predictors : 1 (elev)
#> weighted : no (all predictors count equally)
#> training : 120 points
#> reference : nearest other training point (no folds supplied)
#> normaliser : 1.1283 (mean pairwise distance)
#> threshold : 0.0480 (outlier-removed max of training DI)
#>
#> 529 of 529 prediction points inside the AOA (100.0%)