
Assemble gridded nitrogen inputs from every WHEP N-input source.
Source:R/n_balance_inputs.R
build_n_inputs.RdCombines biological nitrogen fixation (calculate_bnf()), residue/root N
recycling (calculate_npp_carbon_nitrogen()), livestock manure
(build_livestock_nutrient_flows()), atmospheric deposition
(build_n_deposition()), urban/human-excreta N (build_urban_n()), soil
organic-matter mineralization (build_carbon_balance()'s
son_change_kgn_ha) and synthetic fertiliser (a country total
spatialized to crops and cells via spatialize_country_n_to_crops())
into one long-format tibble of nitrogen inputs to agricultural land.
fert_type values: "bnf", "recycling", "manure_solid",
"manure_liquid", "excreta", "deposition", "urban",
"som_mineralization", "synthetic" and "accum_loss". The last is a
documented gap (perennial-crop standing-biomass N accumulation from
Spain_Hist's N_balance.R): its source computation was not available for
this task, so it is never emitted, only reserved in the vocabulary.
Terms that are fundamentally per-cell or per-land-use rather than per-crop
are allocated over the agricultural land support, either supplied as
data$ag_land_support or derived by build_ag_land_support() from the
gridded inputs already present. Deposition uses both cropland and
grassland support. "urban", "som_mineralization", and manure already
assigned upstream to Cropland but lacking a crop use only local cropland
support, so manure is not reassigned to grassland after the manure engine's
capacity allocation. Forest and natural land are outside that support and
therefore outside the agricultural balance. Grassland is represented by CBS
3000; no intensive/extensive class is inferred.
Arguments
- years
Optional integer vector of calendar years to keep.
NULLkeeps every year the assembled inputs cover.- resolution
"grid"(default, per cell/crop/year/fert_type) or"polity"(summed toarea_code/item_cbs_code/year/fert_type).- synthetic_method
Synthetic-N crop allocation method,
"coello"or"area_share". WhenNULL(default), usesdata$synthetic_method %||% "coello"for backwards compatibility.- 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
Named list of pre-loaded, caller-supplied upstream inputs. Each of the following is required for its corresponding
fert_typeto be emitted (a missing one silently skips that source rather than erroring, since callers may only want a subset):bnf_input:calculate_bnf()'s required input tibble (lon,lat,area_code,year,item_prod_code,crop_npp_n_t,product_n_t,weed_npp_n_t,land_use,legumes_seeded,seeded_cover_crop_share,area_ha).npp_n_input:calculate_npp_carbon_nitrogen()'s required input tibble (lon,lat,area_code,year,item_prod_code,item_cbs_code,product_dm_t,residue_dm_t,root_dm_t, optionallyresidue_soil_dm_t).livestock_intake:build_livestock_nutrient_flows()'sintakeargument (theredistribute_feed()realised-intake contract), plusgridded(its land-surface layer) andresolution/methods(forwarded as-is).nhx,noy,cell_polity:build_n_deposition()'s inputs.deposition_scope: which of a polycell's territory the"deposition"term is credited with."territory"(default) is land plus inland water plus ice: nitrogen deposited on a lake or a glacier still drives indirect N2O and still reaches the eutrophication pathway, so the impact terms have to account for it."land"is the terrestrial surface alone, for purposes that want it, and it needs acell_politycarryingland_area_ha,inland_water_haandice_area_ha; asking for it without them aborts rather than silently returning the whole territory. Recorded inmethod_deposition_scope.ag_land_support: agricultural physical land support keyed bylon,lat,area_code,year,item_cbs_code, withland_use("cropland"or"grassland") and positivearea_ha. Optional: when absent it is derived natively bybuild_ag_land_support()fromcell_polity,type_croplandandcrop_patterns(plusstatesorgrassland_hafor the grassland side). Supply it to override that derivation with a better land surface. Cropland rows identify crop CBS items; all pasture/rangeland rows use CBS 3000.grassland_source,gridded_pasture,grassland_ha,states: forwarded tobuild_ag_land_support()when the support is derived.grassland_sourceselects itsgrasslandargument ("gridded_pasture"default,"luh2", or"none"for cropland-only support).urban_population,cropland_ha,cell_polity:build_urban_n()'s inputs.carbon_balance:build_carbon_balance()'s"grid"-resolution output (lon,lat,area_code,land_use,year,area_ha,son_change_kgn_ha); this driver requires it supplied directly, it is never computed here.primary_prod,fertilizer,crop_patterns,type_cropland,cell_polity: the synthetic-fertiliser assembly (country total fromfertilizer, thefaostat-fertilizer-nutrientspin, split to crops by the chosen crop-share method, then to cells bycrop_patterns/type_cropland).synthetic_method: how the synthetic-N country total is split across crops,"coello"(default; Coello 2025 rate-weighted, FAOSTAT- conserving) or"area_share"(harvested-area shares only).coello_rates: crop-specific synthetic-N rate table shaped like coello_synthetic_n (year,area_code,item_cbs_code,kg_n_ha); defaults towhep::coello_synthetic_n. Used only whensynthetic_method = "coello".gridded,resolution,methods: forwarded tobuild_livestock_nutrient_flows().resolutionis the manure engine's own axis, not this function's: it defaults to"subnational"atresolution = "grid"(cell-level nitrogen needs cell-level manure) and to"national"otherwise. A value supplied here is always honoured.
- example
If
TRUE, return a small fixture instead of assembling real data. Defaults toFALSE.
Value
A tibble. At resolution = "grid": lon, lat, area_code,
item_cbs_code, year, fert_type, n_input_t,
method_recycling_n, method_synthetic, method_deposition_scope. At
resolution = "polity": area_code, item_cbs_code, year,
fert_type, method_recycling_n, method_synthetic,
method_deposition_scope, n_input_t (summed over cells).
method_recycling_n records which residue basis the "recycling" term
used: "residue_soil_returned" when the upstream NPP input supplied
residue_soil_dm_t (residue N net of removal for feed/fuel/burning) or
"total_residue" when only gross residue N was available; it is NA for
every other fert_type. method_synthetic records the synthetic
crop-split basis ("coello" or "area_share") on "synthetic" rows and
is NA for every other fert_type. method_deposition_scope records
which of the polycell's territory the "deposition" term was credited
with ("territory" or "land") and is NA for every other fert_type.
Both grains also carry the polity columns below, plus
reporting_polity_out_of_span when polity_validity = "flag".
Details
polity_validity is forwarded to every builder this function calls that
offers it – build_ag_land_support(), build_n_deposition(),
build_urban_n() and spatialize_country_n_to_crops() – and then applied
to the assembled output, so one choice governs the whole assembly instead of
each builder deciding on its own key space (whep#727). Under "drop" the
support table loses those rows too, so a non-item input (deposition, urban,
SOM mineralization) whose own rows were supplied directly and therefore not
dropped can find no cropland support left to allocate over; that aborts in
the mass check rather than silently losing nitrogen.
Polity columns
Every area-keyed output carries the polity its area_code resolves to in
that row's year:
polity_area_code: The numeric key rows are AGGREGATED on, for the matrix workflows. It is a bucket, not an identity: usereporting_polity_codeto say which territory a row belongs to.reporting_polity_code: The polity itself, e.g.ESP-1846-1914. It is year-aware, so the samearea_coderesolves to different polities in different years, which is the point of the crosswalk.reporting_polity_name: Its name. It can differ from the area's own name where the area folds into an aggregate.reporting_polity_has_geometry: Whether the polity has a polygon in the WHEP polity database, for callers that need to map or intersect it.FALSEis a documented gap upstream, not an error.
Rows whose area_code resolves to no polity keep the columns with NA
rather than being dropped, so a gap is visible instead of silent.
Rows before the back-cast anchor year resolve to the polity live in that
anchor year rather than to the polity live in the row's own year, because
WHEP's pre-anchor series are back-cast onto the anchor-year territory. See
add_polity_code() for the reasoning. Where that polity is not live in the
row's own year – 41.5% of the pre-1961 (area, year) cells –
add_polity_code() says so as mapping_status == "backcast_anchor", and
polity_coverage_gaps() reports it as gap_kind == "backcast_anchor".
These columns do not say so either way.
A row whose year no mapped period covers is resolved to the NEAREST period of
the same area instead, so reporting_polity_code can name a polity that did
not exist in that row's year – FAOSTAT bucket 206 "Sudan (former)" keeps
reporting after SUD-1956-2011 ends, and its post-2011 rows carry that code.
These columns do not say so: add_polity_code() reports such a row as
mapping_status == "out_of_span", and that column is dropped here so that
adding it does not change the schema of every area-keyed output at once.
polity_coverage_gaps() reports the stand-in rows of a built table, and
options(whep.polity_mapping_status = "flag") (or "status") carries the
signal on the outputs themselves. Both are opt-in; the default is no extra
column.
Examples
build_n_inputs(example = TRUE)
#> # A tibble: 9 × 14
#> year area_code polity_area_code reporting_polity_code reporting_polity_name
#> <int> <int> <int> <chr> <chr>
#> 1 2020 1 1 ARM-1991-2025 Armenia
#> 2 2020 1 1 ARM-1991-2025 Armenia
#> 3 2020 1 1 ARM-1991-2025 Armenia
#> 4 2020 1 1 ARM-1991-2025 Armenia
#> 5 2020 1 1 ARM-1991-2025 Armenia
#> 6 2020 1 1 ARM-1991-2025 Armenia
#> 7 2020 1 1 ARM-1991-2025 Armenia
#> 8 2020 1 1 ARM-1991-2025 Armenia
#> 9 2020 1 1 ARM-1991-2025 Armenia
#> # ℹ 9 more variables: reporting_polity_has_geometry <lgl>, lon <dbl>,
#> # lat <dbl>, item_cbs_code <int>, fert_type <chr>, n_input_t <dbl>,
#> # method_recycling_n <chr>, method_synthetic <chr>,
#> # method_deposition_scope <chr>