
Build a per-crop physical land extension with FAO fallow-inclusive arable land.
Source:R/arable_permanent_land.R
build_fao_arable_fallow_extension.RdTurn per-crop harvested-derived physical area into a fallow-inclusive physical
land extension whose arable-crop total reconciles to FAO's physical
Arable land and whose perennial-crop total reconciles to FAO's physical
Permanent crops (get_arable_permanent_land()), per (area_code, year).
This is the FAO-land-base analogue of build_cropgrids_land_extension()(source = "cropgrids_fallow"). The existing method takes the fallow magnitude from
FAOSTAT "Temporary fallow" (item 6640, a sparse and, for many rain-fed
economies, absent series) applied to a single CROPGRIDS 2020 snapshot. Here
the fallow magnitude is the physical arable land that carried no harvest in
that specific year, FAO Arable land - sum(cropped arable physical), so a
drought year's resting cropland is charged to the crops whose rotation it
supports and the arable-crop footprint totals match FAO's land survey in every
year (see the Tunisia/Portugal motivation in get_arable_permanent_land()).
Reconciliation, per (area_code, year):
Arable crops (
items_prod_full$Herb_Woody != "Woody"): rotational fallowmax(0, arable_ha - S)(withSthe cropped arable physical total) is distributed withattribute_fallow_to_crops()usingfallow_weights, so the arable total reachesarable_ha. Where the cropped physical already exceedsarable_ha(heavy multi-cropping, or inflated fodder harvested area) there is no fallow to add and the arable crops are scaled down toarable_hainstead, the physical-container correction. Either way the arable total equals FAOarable_haby construction.Perennial crops (
Herb_Woody == "Woody") receive no fallow and are scaled so their total equals FAOpermanent_ha, preserving the within-group physical pattern. A positive target without a corresponding arable crop row or positive perennial base area cannot be reconciled without inventing a crop allocation;unsupported_targetdecides what happens to it (see the unsupported-target section).
This is the crop-side default of the land-balance footprint
(build_land_balance_footprint()).
Usage
build_fao_arable_fallow_extension(
harvested = NULL,
arable_permanent = NULL,
base_extension = NULL,
fallow_weights = NULL,
temporary_grassland = NULL,
items_prod_full = whep::items_prod_full,
temp_grassland_basis = c("modelled", "modelled_then_fao", "fao_official", "fao_all",
"none"),
fodder_gap = c("as_reported", "carry_forward", "drop"),
unsupported_target = c("unallocated", "zero", "drop", "abort")
)Arguments
- harvested
Tibble of harvested area with columns
year,area_code,item_cbs_code,harvested_ha. IfNULL, built fromget_primary_production()(unit == "ha"); passing a cached harvested table avoids that rebuild.- arable_permanent
Tibble of FAO physical land base with columns
area_code,year,arable_ha,permanent_ha. IfNULL,get_arable_permanent_land()is called for the years present inbase_extension.- base_extension
Tibble of cropped (fallow-excluding) per-crop physical area with columns
year,area_code,item_cbs_code,impact_u. IfNULL, built withbuild_cropgrids_land_extension()(source = "cropgrids")fromharvested.- fallow_weights
Tibble of
area_code,item_cbs_code,weightgiving the within-country fallow allocation weight, e.g. fromgridded_fallow_weights()(the recommended agro-climatic, rainfed-gated weight). IfNULL, fallow is distributed in proportion to each arable crop's cropped physical area (perennials always excluded). The cropped-area fallback is used independently for an area when it has no usable supplied weights, a non-finite or negative supplied weight, or a non-positive total.- temporary_grassland
Tibble of grassland occupation in the
build_grassland_land_extension()schema (area_code,year,item_cbs_code,impact_u); its CBS 3002 rows are the temporary grassland netted out of the arable target so ordinary crops plus CBS 3002 reconcile to FAO Arable land (see the temporary-grassland section). IfNULL(default) it is built withbuild_grassland_land_extension()(grassland_metric = "occupation")so netting still applies (correct but slow); supply the table to skip that rebuild, or pass one with no CBS 3002 rows to opt out.- items_prod_full
Crosswalk used to classify
item_cbs_codeas arable or perennial viaHerb_Woody. Defaults to items_prod_full.- temp_grassland_basis
Which measurement of temporary grassland is netted out of the arable target.
"modelled"(default) is the published behaviour: WHEP's own CBS 3002, which exists for 26 EU polities and stops in 2019."modelled_then_fao"keeps that and fills every other country-year from official FAO 6633."fao_official"uses official FAO 6633 everywhere,"fao_all"uses FAO 6633 on every observation-status flag (~81% of it is FAO-imputed), and"none"nets nothing, the behaviour before whep#349. See the netting-basis section.- fodder_gap
How the FAOSTAT fodder items (CBS
2000-2003) are treated where their sources have run out."as_reported"(default) is the published behaviour: no fodder from 2020, so ordinary crops absorb its land."carry_forward"extends each fodder series' last observed physical area over the rest of that country's panel."drop"removes fodder from the whole panel. See the fodder-gap section.- unsupported_target
What happens to a country-year whose positive FAO land target has no crop row of the matching kind to carry it.
"unallocated"(default) keeps the hectares as anitem_cbs_codeNArow,"zero"lets the unreconcilable target contribute no land,"drop"removes the whole affected country-year, and"abort"refuses to continue (the behaviour before whep#1026). See the unsupported-target section.
Value
A tibble with columns year, area_code, item_cbs_code,
impact_u (fallow-inclusive physical land in hectares), method_land
("fao_arable_fallow"), temp_grassland_netted_ha (hectares netted out of
that country-year's arable target, 0 where the netting term is
structurally absent), temp_grassland_source (the source that supplied
that netted term: "modelled_cbs_3002", "fao_6633_official",
"fao_6633_all", "absent" where the basis has no value for that
country-year, or "not_netted" under "none"),
method_temp_grassland (the temp_grassland_basis
in force), method_fodder (the fodder_gap in force) and
method_unsupported_target (the unsupported_target in force), and
fodder_coverage, which says per country-year whether the fodder input
was there before any fodder_gap treatment: "reported" (the base
carries fodder area that year), "lapsed" (it carries none, but did in an
earlier year of that country's panel – the 2020 break of whep#938, whose
land the other arable crops absorb under "as_reported", or which
"carry_forward" fills) or "not_reported" (none that year or before).
Under
unsupported_target = "unallocated" a row with item_cbs_code NA carries
the FAO land no crop can be named for.
Temporary grassland (no double-count)
FAO's Arable land total includes temporary meadows and pastures —
temporary grassland is part of cropland, not grassland. That land is also
reported separately as CBS 3002 (Temporary grassland) by
build_grassland_land_extension(), so summing both extensions naively would
count it twice. Pass that grassland occupation as temporary_grassland and
its CBS 3002 is netted out of the arable target before reconciling ordinary
crops, enforcing the invariant per (area_code, year)
ordinary crop occupation (incl. fallow) + CBS 3002 = FAO Arable land. The
land-balance footprint (build_land_balance_footprint()) does exactly this,
passing the grassland occupation it has already built. When
temporary_grassland is NULL (default) the grassland occupation extension
is built internally so netting still happens — correct but slow, since that
build reruns much of the pipeline; supply the table to avoid the rebuild.
Where modelled CBS 3002 exceeds FAO Arable land (survey vs.
fodder-reconstruction mismatch) the arable target is clamped at 0 and a
warning is emitted.
Netting basis, and the 2019/2020 seam
Modelled CBS 3002 comes from EU AgriDB alone — FAOSTAT production item 996
is in neither production pin, and the EU AgriDB fodder source runs
1961-2019 for all 28 of its region keys. So over 2001-2023 the netting term
exists for 26 EU polities and the years 2001-2019 only, and is
identically zero everywhere else. For those 26 polities the arable target
therefore steps from 96.4 Mha in 2019 to 103 Mha in 2020 while their own
FAO arable land falls, so ordinary arable crops there gain land with no
land-use change behind it. Measured over 2001-2023 on the real inputs, the
land the netting removes is 8.2-9.8 Mha a year to 2019 and exactly 0 from
2020. temp_grassland_basis exposes the alternatives measured in whep#937
and whep#354; "modelled" remains the default so this argument changes no
published number until a basis is chosen deliberately.
temp_grassland_netted_ha in the output, and
check_arable_composition(), make the switch-off visible either way.
temp_grassland_source says, per country-year, which source supplied the
netted term: "modelled_cbs_3002", "fao_6633_official" or
"fao_6633_all", or "absent" where the chosen basis has no value there,
so a country-year with no measurement never reads as one with no temporary
meadows. On the real 2001-2023 inputs under "modelled", 494 of the
4,549 country-years in the output are "modelled_cbs_3002" (26 polities,
2001-2019) and the other 4,055 are "absent", including all 787 from 2020.
Under the "fao_*" bases the column also separates a reported value that
nets 0 ha from a missing report: 103 country-years under "fao_official"
and 993 under "fao_all" have a value yet net nothing, and before this
column they read exactly like the country-years with no value at all.
FAO's own item 6633 "Temporary meadows and pastures" measures the same
concept, runs 2001-2023, and is what the "fao_*" bases read. It is not a
drop-in replacement: only ~19% of it is an official value, Greece and Poland
are imputed zeros throughout while WHEP models 2.10 and 4.78 Mha there, and
its scope is country-dependent — for Ireland, Sweden, the United Kingdom,
the Netherlands, Belgium, Luxembourg and Czechia it equals WHEP's CBS 3002
to the digit, while for Germany, Italy, Romania, Spain, Denmark, Austria and
Bulgaria it is 3-40 times larger and lands near the whole green-fodder
group. validation/temp_grassland_6633.R records that comparison.
Fodder gap
FAOSTAT's fodder tonnage (faostat-production-old, production only, no
harvested area at all) runs to 2013, whose rows .combine_fodder() drops,
so it effectively ends in 2012; EU AgriDB, the only other source, ends in
2019. Fodder harvested area is reconstructed from those two, so a build
reaching 2020 has no fodder at all from that year: measured over
2001-2023 on the real inputs, fodder is 9.2% of the reconciled arable land
extension in 2001 and 7.6% in 2019, then 0% from 2020, with ordinary
arable crops absorbing the difference (whep#938). A second, earlier
composition change sits inside the covered window: from 2013 the
FAOSTAT-derived fodder area disappears and the 2012 area is carried forward,
2.2 Mha in 2012 and 75.0 Mha from 2013, held flat to 2019. Production rows
say so in source ("DM_yield_estimate_carried_forward", whep#1027), but
this extension does not see source, and fodder is present on both sides
of 2013, so check_arable_composition() does not flag that year.
fodder_gap exposes the treatments; "as_reported" remains the default.
Whatever the treatment, fodder_coverage in the output marks every
country-year after the fodder input stops as "lapsed", and
check_series_jumps() with dropouts = TRUE flags each fodder series at
the year it stops.
Unsupported land targets
FAO reports positive land for some country-years in which the crop panel has nothing of the matching kind to carry it, so the reconciliation has no crop to attribute the land to. Over the full 1850-2023 span on the real default inputs there are 923 such country-years (whep#1026):
arable: 33 country-years, all Marshall Islands (
area_code127), 1991-2023, 500 ha of FAO Arable land each (16,500 ha in total) with no arable crop row at all – its only crop area is perennial.permanent crops: 890 country-years in 8 areas whose perennial base area is zero: Poland (173) 1850-1964, 27.72 Mha summed over years (up to 287,779 ha in a year); Nepal (149) 1850-1973, 2.40 Mha; Burkina Faso (233) 1850-1976, 1.35 Mha; Denmark (54) 1850-1984, 1.10 Mha; Saint Kitts and Nevis (188) 1850-1984, 0.67 Mha; Sweden (210) 1850-1965, 0.39 Mha; Chad (39) 1850-1984, 0.35 Mha; Mongolia (141) 1983-1985, 3,000 ha. 33.98 Mha summed over all 890 country-years.
Before whep#1026 this was an error, which made the function's own documented
span unreachable and blocked build_land_balance_footprint() entirely.
unsupported_target now selects the treatment, and none of them invents a
crop allocation:
"unallocated"(default) keeps the hectares in the ledger as one row per affected country-year withitem_cbs_codeNA– real reported land that no crop can be named for. Nothing is lost and the gap is visible."zero"treats the FAO total as the error: the unreconcilable target contributes no land, the rest of the country-year reconciles unchanged."drop"removes the whole affected(area_code, year), including the crop rows that were supported. For Poland that deletes 115 years of Polish arable land, so it is the most destructive option."abort"is the pre-whep#1026 behaviour and refuses to continue.
Only the NA-item rows separate "unallocated" from "zero"; every other
country-year is identical under all three continuing treatments. Restricted
to 2001-2023 the whole difference from "abort"'s (unreachable) output is
the 23 Marshall Islands rows, 11,500 ha.
Examples
harvested <- tibble::tribble(
~year, ~area_code, ~item_cbs_code, ~harvested_ha,
2020L, 1L, 2511L, 300, # wheat (arable)
2020L, 1L, 2560L, 100 # coconuts (perennial)
)
base_extension <- tibble::tribble(
~year, ~area_code, ~item_cbs_code, ~impact_u,
2020L, 1L, 2511L, 300,
2020L, 1L, 2560L, 100
)
arable_permanent <- tibble::tribble(
~area_code, ~year, ~arable_ha, ~permanent_ha,
1L, 2020L, 500, 100
)
items <- tibble::tribble(
~item_cbs_code, ~Herb_Woody,
2511L, "Herbaceous",
2560L, "Woody"
)
temporary_grassland <- tibble::tribble(
~area_code, ~year, ~item_cbs_code, ~impact_u,
1L, 2020L, 3002L, 100 # temporary grassland netted out of arable
)
build_fao_arable_fallow_extension(
harvested, arable_permanent, base_extension,
temporary_grassland = temporary_grassland,
items_prod_full = items
)
#> # A tibble: 2 × 11
#> year area_code item_cbs_code impact_u method_land method_temp_grassland
#> <int> <int> <int> <dbl> <chr> <chr>
#> 1 2020 1 2511 400 fao_arable_fallow modelled
#> 2 2020 1 2560 100 fao_arable_fallow modelled
#> # ℹ 5 more variables: method_fodder <chr>, method_unsupported_target <chr>,
#> # temp_grassland_netted_ha <dbl>, temp_grassland_source <chr>,
#> # fodder_coverage <chr>