
Spatialize a polity-level nitrogen total to crops and grid cells.
Source:R/n_balance_spatialize.R
spatialize_country_n_to_crops.RdPromotes a single polity-total nitrogen input (one row per year,
area_code, for one fertiliser type) to the crop level by the same
harvested-area-share logic used by
build_crop_soil_n2o_extension() (year/area_code-matched, weighted by
each crop's share of harvested cropland area), then optionally further to
the grid level by distributing each polity-crop total across cells in
proportion to the cell's share of that polity-crop's total crop-pattern
area (type_ha * harvest_fraction, summed over LUH2 cropland classes;
the exact formula used by make_lpjml_covariate()'s crop_pattern
weighting). A polity-crop with no crop-pattern hectares (crop absent from
the static pattern raster, or its pattern area sums to zero in the polity)
is instead spread uniformly across the polity's cropland cells, weighted by
each cell's cropland area, so the grid output still re-aggregates to the
polity total. Such reallocations emit a warning naming the affected crops
and the reallocated nitrogen.
Both grid weights carry a polity share of the cell, because a border cell's
cropland belongs to more than one polity. That share is a polycell's
land_area_ha over the cell's total land_area_ha, the share of the cell's
land build_polycell_support() measures geodesically. The transitional
alternative is polity_frac, the subcell-count share build_cell_polity()
carries, which is quantised to 1/36 of a cell.
The share is of the cell's land, never land_area_ha / cell_area_ha:
what it splits is already land-only (LUH2 cropland hectares), so dividing by
the whole cell would remove the inland water and ice a second time. And it
is a share, never an absolute area: crop_pattern_ha * land_area_ha
would weight every cell a second time by its own size and is no partition of
the cell at all.
Because the cell weights are renormalised within each polity-crop-year, either key redistributes the polity total and neither can change it. Swapping the key moves where the nitrogen lands, never how much of it there is.
Arguments
- country_totals
A tibble with
year,area_code,n_t: the polity-level nitrogen total for one fertiliser type.A tibble with
year,area_code,item_cbs_code,area_share: harvested-area-weighted crop shares within each country-year, e.g. frombuild_crop_soil_n2o_extension()'s internal crop-area-share helper.- cell_polity
The cell-to-polity support (
lon,lat,area_code,cell_area_haand thesplitkey column). Only required whenresolutionincludes"grid". Rows are keyed onarea_code:build_polycell_support()keys onpolity_codeand does not derive the reporting vocabulary (DA-23), andpolity_area_crosswalkfolds distinct polities into onearea_codeor leaves itNA, so a support must be converted to one row per cell andarea_codebefore it is passed here. That conversion is refused rather than performed silently. The share denominator is the land of the rows supplied, so a caller that simply drops the unkeyable polycells renormalises the survivors onto the whole cell and hands them hectares that are not theirs, invisibly, because the shares still sum to 1. Keep that land in the denominator instead, under a bucket nocountry_totalsrow can join: it then dilutes nobody's share and receives no nitrogen.- resolution
Which resolution(s) to return:
"polity_crop"(default,year/area_code/item_cbs_codetotals only) or"grid"(also distributes tolon/latgrid cells; requirescrop_patternsandtype_croplandindata).- split
Which polity share of the cell weights each grid cell:
"auto"(default) takesland_area_hawhen the support carries it andpolity_fracotherwise;"land_area_ha"and"polity_frac"demand that key and abort when it is absent. The resolved key is recorded in themethod_polity_splitoutput column, so a table's split is readable from the table. Read only atresolution = "grid"; the"polity_crop"output splits nothing across cells.- polity_validity
What to do with a row whose
(area_code, year)resolves to a polity that did not exist in that year (the cell-polity crosswalk has no year dimension, so an early-20th-century cell is labelled with its present-day territory)."keep"(default) keeps every row, which is the historical behaviour, and warns naming the rows, years and area codes involved."flag"keeps them and adds the per-row logicalreporting_polity_out_of_span, marking exactly which rows are stand-ins."drop"removes them. All three warn; only"drop"changes the numbers. Seepolity_coverage_gaps(), which reports the same rows for an already-built table.- data
Optional named list of pre-loaded grid inputs, used only when
resolution = "grid":crop_patterns(lon,lat,item_prod_code,harvest_fraction) andtype_cropland(lon,lat,year,luh2_type,type_ha), each falling back to a lazy parquet read fromSys.getenv("WHEP_CROP_PATTERNS_PATH")/Sys.getenv("WHEP_TYPE_CROPLAND_PATH")when absent.item_cbs_codeincrop_shares/country_totalsis matched to theitem_prod_codecolumn ofcrop_patternsvia items_prod_full (the same crosswalkbuild_crop_land_extension()uses).
Value
A tibble. For resolution = "polity_crop": year, area_code,
item_cbs_code, n_t. For resolution = "grid": lon, lat,
area_code, year, item_cbs_code, n_t and method_polity_split.
Either gains reporting_polity_out_of_span when
polity_validity = "flag"; this output carries no reporting-polity
columns, so the flag is attached directly rather than derived from them.
Examples
spatialize_country_n_to_crops(
country_totals = tibble::tribble(
~year, ~area_code, ~n_t,
2010L, 10L, 100
),
crop_shares = tibble::tribble(
~year, ~area_code, ~item_cbs_code, ~area_share,
2010L, 10L, 2511L, 0.7,
2010L, 10L, 2513L, 0.3
),
cell_polity = NULL,
resolution = "polity_crop"
)
#> # A tibble: 2 × 4
#> year area_code item_cbs_code n_t
#> <int> <int> <int> <dbl>
#> 1 2010 10 2511 70
#> 2 2010 10 2513 30