The goal of spatialsample is to provide functions and classes for spatial resampling to use with rsample. Keeping the data used to train a spatial model (what we call a training or analysis set) separate from the data used to evaluate that model (what we call a testing or assessment set) provides a more realistic view of how well it will perform when extrapolating to new locations.

When resampling spatial data, we often want to introduce some distance between analysis and assessment data; one of the most common methods for introducing this distance is to “buffer” the assessment set, removing all points within a given distance from the analysis set to enforce a minimum space between data sets. This vignette walks through how to buffer your assessment folds with spatialsample, as well as some considerations about how those buffers are calculated.

## Exclusion buffers

By default, most spatial cross-validation methods in spatialsample don’t automatically create buffer zones. Take for instance spatial_block_cv(), which creates a number of “blocks” in a grid and assigns data to folds based on the block its centroid falls in:

set.seed(123)
blocks <- spatial_block_cv(boston_canopy, v = 5)

autoplot(blocks)

If we look at the individual folds, we can see that the assessment data directly borders the analysis data for each given fold:

purrr::walk(blocks$splits, function(x) print(autoplot(x))) This is a downside of standard blocking cross-validation approaches; while it does introduce some spatial separation between the analysis and assessment sets for data at the middle of the block, data towards the edges may not be separated at all. Applying an exclusion buffer around each assessment fold lets us change that. To create these exclusion buffers while using any cross-validation function in spatialsample, we can use a standardized buffer argument: set.seed(123) blocks <- spatial_block_cv(boston_canopy, v = 5, buffer = 1500) Now when we plot the folds separately, we can see that a strip of data around each assessment block has been assigned to neither the analysis or assessment fold. Instead, it’s been removed entirely in order to provide some distance between the two sets: purrr::walk(blocks$splits, function(x) print(autoplot(x)))

By default, buffer is assumed to be in the same units as your data, as determined by the data’s coordinate reference system. To apply buffers of other units, use the units package to explicitly specify what units your buffer is in.

For instance, boston_canopy uses units of US feet for distance. To specify a buffer in meters instead, we can use:

set.seed(123)
blocks <- spatial_block_cv(
boston_canopy,
v = 5,
buffer = units::as_units(1500, "m")
)

purrr::walk(blocks$splits, function(x) print(autoplot(x))) Note that, when you’re using non-point data, the distance between observations is calculated as the shortest distance between any points in two observations. For instance, buffers on polygon data will exclude data based on the edge-to-edge distance between observations, rather than centroid to centroid. One special case, however, is when buffer is set to 0. In this case, spatialsample won’t apply a buffer at all. While polygons that share an edge are within 0 distance of each other, when calculated from edge-to-edge, we think that setting buffer = 0 would intuitively apply zero (that is, no) buffer. If you want to be sure to only capture adjacent polygons in a buffer, set buffer to a tiny, non-zero value: set.seed(123) blocks <- spatial_block_cv( boston_canopy, v = 5, buffer = 2e-200 ) purrr::walk(blocks$splits, function(x) print(autoplot(x)))

In addition to exclusion buffers, spatialsample also provides a way to add an inclusion buffer (or as we call it, an “inclusion radius”) around your assessment set. Simply set the radius argument in any spatial cross-validation function to your desired distance, and any data within that inclusion radius will be added to the assessment set:

set.seed(123)
blocks <- spatial_block_cv(
boston_canopy,
v = 5,
purrr::walk(blocks$splits, function(x) print(autoplot(x))) This argument is handled the same way as buffer, with the same caveats: • Unless units are specified explicitly, radius is assumed to be in the same units as your data’s coordinate reference system. • Distances are calculated between the closest parts of observations. • Values of zero do not apply a radius. Both radius and buffer can be specified at the same time. This makes it possible to implement, for instance, leave-one-disc-out cross-validation using spatialsample: set.seed(123) blocks <- spatial_buffer_vfold_cv( boston_canopy, v = nrow(boston_canopy), radius = 1500, buffer = 1500 ) purrr::walk(blocks$splits, function(x) print(autoplot(x)))