Reduces a raster to one summary row per zone, streaming the raster one
tile-row strip at a time so the whole grid never has to be resident. Zones
come either from a second raster aligned to the value grid (each pixel's zone
is that raster's value, the terra::zonal pattern) or from an sf
polygon layer (each pixel is assigned the polygon its centre falls in). The
per-zone running moments (count, sum, sum of squares, min, max) are folded in
memory as strips arrive, so peak memory is one strip plus the small per-zone
table regardless of raster size. This is the monoid fold tier of the
spatial toolbox: bounded memory, a single streaming pass, no spill.
Usage
zonal(
raster,
zones,
fun = "mean",
band = 1L,
zone_band = 1L,
zone_field = NULL,
na.rm = TRUE
)Arguments
- raster
A
vectra_raster(fromvec_open_raster()) or a path to a.vecraster holding the values to summarise.- zones
The zones to summarise within: a
vectra_raster/.vecpath aligned toraster(zone id per pixel), or ansf/sfcpolygon layer.- fun
One or more of
"mean","sum","count","min","max","sd". Each becomes a column in the result. Default"mean".- band
Band of the value
rasterto summarise (1-based). Default 1.- zone_band
Band of a raster
zonesholding the zone ids. Default 1.- zone_field
For an
sfzoneslayer, the column giving each polygon's zone id. DefaultNULLuses the polygon row index1:n.- na.rm
If
TRUE(default) skip nodata pixels; ifFALSElet a nodata pixel propagateNAto its zone's statistics.
Details
sd is derived from the streamed moments
(sqrt((sum2 - sum^2 / n) / (n - 1))), so it needs no second pass. With
na.rm = TRUE (the default) nodata pixels are skipped; with na.rm = FALSE
any nodata pixel in a zone makes that zone's sum/mean/min/max/sd
NA, matching the resident behaviour. count always reports the number of
non-nodata cells in the zone.
Polygon zones assign each pixel centre to a polygon natively on the GEOS C
API (the polygons parsed once into a spatial index, every strip's centres
located in C), so sf is touched only to read the polygons in; geographic
polygons with spherical geometry on (sf::sf_use_s2()) keep the sf
point-in-polygon path. Raster zones are fully sf-free. The zone raster
must share the value raster's dimensions and geotransform.
See also
rasterize() to build a value raster from streamed points,
vec_open_raster() to open the inputs.
Examples
# A value raster and an aligned 2x2-block zone raster on a 4x4 grid.
vals <- matrix(1:16, 4, 4, byrow = TRUE)
zone <- matrix(c(1, 1, 2, 2, 1, 1, 2, 2,
3, 3, 4, 4, 3, 3, 4, 4), 4, 4, byrow = TRUE)
fv <- tempfile(fileext = ".vec"); fz <- tempfile(fileext = ".vec")
vec_write_raster(vals, fv, dtype = "f64", extent = c(0, 0, 4, 4))
vec_write_raster(zone, fz, dtype = "f64", extent = c(0, 0, 4, 4))
zonal(fv, fz, fun = c("mean", "sum", "count"))
unlink(c(fv, fz))