xrspatial.dasymetric.disaggregate#

xrspatial.dasymetric.disaggregate(zones: DataArray, values: dict | Series, weight: DataArray, method: str = 'weighted', nodata_zone: int | None = None, class_breaks: tuple | None = None, density_caps: list | None = None, name: str = 'disaggregate') DataArray[source]#

Redistribute zone-level values onto a raster using ancillary weights.

This is the spatial inverse of stats(): given aggregate values per zone (e.g. population per census tract) and a weight surface (e.g. land cover), disaggregate distributes each zone’s total across its pixels proportionally to their weights.

Parameters:
  • zones (xr.DataArray) – 2-D integer raster identifying zone membership for each pixel.

  • values (dict or pd.Series) – Mapping of zone_id -> value to redistribute.

  • weight (xr.DataArray) – 2-D float raster of ancillary weights (e.g. land-cover suitability). Negative weights are clamped to zero.

  • method (str, default 'weighted') –

    Redistribution method:

    • 'binary' – binarize weights (nonzero -> 1), split equally.

    • 'weighted' – proportional: pixel = zone_value * pixel_weight / zone_weight_sum.

    • 'limiting_variable' – three-class dasymetric with per-class density caps (numpy-only).

  • nodata_zone (int or None, default None) – Zone ID to treat as no-data (output NaN).

  • class_breaks (tuple of float or None, default None) – Only used when method='limiting_variable'. Thresholds that split weight values into classes. For example (0.0,) creates two classes: zero-weight and nonzero-weight. Defaults to (0.0,) if None.

  • density_caps (list of float or None, default None) – Only used when method='limiting_variable'. Maximum density (value per pixel) for each class. Must have len(class_breaks)+1 entries. If None, the first class (zero-weight pixels) gets cap 0 and all others get unlimited capacity.

  • name (str, default 'disaggregate') – Name for the output DataArray.

Returns:

Float raster with the same shape, coordinates, and attributes as zones. The sum of output pixels within each zone equals the input zone value (conservation property), except where all weights are zero (result is NaN).

Return type:

xr.DataArray

Examples

>>> import numpy as np, xarray as xr
>>> from xrspatial import disaggregate
>>> zones = xr.DataArray(np.array([[1, 1], [2, 2]]), dims=['y', 'x'])
>>> weight = xr.DataArray(np.array([[1.0, 3.0], [2.0, 2.0]]), dims=['y', 'x'])
>>> result = disaggregate(zones, {1: 100, 2: 50}, weight)
>>> result.values
array([[25., 75.],
       [25., 25.]])