Year-aware bridge from numeric reporting area_code values used by
FAOSTAT/FABIO-derived WHEP data to periodized WHEP polity_code values.
Format
A tibble with one row per area-code/polity-period mapping. Key columns:
area_code: Numeric FAOSTAT/FABIO reporting area code.area_name: Reporting area name.area_iso3c: Reporting-area ISO3-like code where available.legacy_polity_prefix,legacy_polity_name: The ISO3-like stem ("ARM","ROCE","REUR") and legacy label this package vendors fromregions_full.csv, kept for older callers and used at build time only as a candidate prefix for polity inference. Neither is an identity: not one stem is a politiespolity_code, so a join to polities on it comes back empty. Readpolity_codefor the polity this row resolves to. Until #711 the pair shipped asreporting_polity_code/reporting_polity_name, the package's own names for a real periodized polity (see whep_polity_columns), which is exactly the trap #687 removed from regions_full.polity_area_code: Numeric area code retained for WHEP matrix workflows.polity_code,polity_name: Matched WHEP polity, orNAfor statistical composites that are not real polities.polity_start_year,polity_end_year: Validity interval for the matched polity, on the same convention as polities:polity_end_yearis exclusive at a succession, so the period coverspolity_start_year:(polity_end_year - 1), and inclusive at the open end, so an interval nothing succeeds covers its own terminal year.add_polity_code()resolves a year on that reading, widened further to the inclusivemap_year_endbelow where the upstream map declares a reported year past the territorial span.mapping_source: How the area-to-polity decision was reached."upstream_map"for the publishedwhep-politiesFAOSTAT area map, which is the authority for the years FAOSTAT reports;"prefix_outside_map"for a period of a mapped area lying outside every span the map declares, kept so sources reported under their own historical borders still resolve;"fabio_row_fold"where FABIO collapses the area into its Rest-of-World bucket;"prefix_fallback"where the map covers the area not at all and the mapping is inferred from the polity-code prefix;"whep_bucket_aggregate"for a row that answers for an aggregation bucket rather than for a reporting area, described below.map_year_start,map_year_end: Inclusive reporting years the upstream map assigns to this area-polity pair,NAunlessmapping_sourceis"upstream_map".map_match_route: Upstream's record of how it decided the row ("iso-equal","registry","manual-route","manual-replace","manual-span"),NAunlessmapping_sourceis"upstream_map".applies_from_year: First year the row answers for, when that is later thanpolity_start_year.NAon every row that answers for a reporting area, whose lower bound is the polity's own start – a row that exists must resolve, so area 276 answersSDN-2011-2025from 2011 even though upstream begins reporting the area in 2012. It is non-NAonly on a"whep_bucket_aggregate"row, where it is the first year the bucket actually sums more than one reporting area.mapping_status: Whether a polity was found, not how much to trust it."matched"when a live polity resolved;"manual"when the decision was curated by hand, either by upstream (amanual-*map_match_route) or by this package's own area-prefix overrides;"unmapped"when no real polity is available, which is FAOSTAT area 351 "China" alone, deliberately left unmapped so it cannot double-count its own components; and"not_a_reporting_area"for a territory that carries no FAOSTAT/FABIO area at all, which hasNAin botharea_codeandpolity_area_codeand so can never be joined to reported data.mapping_note: Explanation for manual, unmapped and non-reporting rows.
Source
Derived from polities,
~/whep-polities/data/final/faostat_area_polity_map.csv and
inst/extdata/harmonization/regions_full.csv.
Keying on (area_code, year) is keying on the polity
This is a contract, asserted by the test suite over the full reporting
era, not an accident of the current snapshot: every (area_code, year) that
resolves at all resolves to exactly one polity_code, over 17,184
resolving pairs and 306 polities. A join that
carries both columns is therefore already polity-correct, whether or not it
names a polity, and the territorial identity is recoverable from the numeric
code rather than lost by it.
The one enumerated exception is FAOSTAT area 7 (Angola) in 1975, where
ANG-1905-1975 records no successor upstream and so is widened by a year
into AGO-1975-2025's first year. Resolution still returns AGO-1975-2025
there, but by row order rather than by the data. See #683.
polity_area_code is a bucket, and does not carry the contract
polity_area_code is the key rows are aggregated on for the matrix
workflows, and several area_code values can share one. Where a bucket has
one member, or its members agree, (polity_area_code, year) recovers the
polity too. Over 1961-2025 exactly one bucket does not: 206, which holds
Sudan (former) 206, Sudan 276 and South Sudan 277 and answers with three
polities in all 65 reported years. See #414. To say which territory a row
belongs to, read this table's own polity_code, or resolve through
add_polity_code(); do not infer it from the bucket. In a WHEP output the
same answer is reporting_polity_code, materialised from this table's
polity_code. This table carries no column of that name, and
legacy_polity_prefix is not a substitute for one (#711).
A bucket that sums two territories gets a polity that means both
Every other row here answers for a reporting area, because that is what
upstream's map is about. Bucket 206 from 2012 is the one place that is not
enough: FAOSTAT reports area 206 through 2011 and areas 276/277 from 2012,
WHEP sums the two successors back into bucket 206, and the bucket's own code
had nothing later than SUD-1956-2011 to answer with – a polity that ended
at the secession, reported out_of_span on every post-2011 row (#414).
Upstream now publishes the entity that means the sum, F206-2011-2025
"Sudan and South Sudan (combined reporting)", aggregate, with a constructed
polygon, on the same F<area> naming as F237-1954-1975 (Vietnam) and
F249-1918-1990 (Yemen). It has no map row, correctly: as a claim about the
reporting area it would be false. data-raw/table_mappings.R therefore adds
one row per bucket that genuinely sums several territories and has no
aggregate label of its own, deriving both the bucket-years and the polity
from the two upstream tables rather than naming either by hand (#860).
The row answers from applies_from_year (2012), not from the polity's own
2011 start: at 2011 bucket 206 is still area 206 reporting alone, and
upstream's map decides that year. So (206, 2011) stays SUD-1956-2011 and
only the years the bucket really is a two-territory sum move.
The shape is unusual and deliberate: this aggregate is live at the same
time as its own members, since areas 276 and 277 keep reporting
separately. That is not a defect – BLX-1850-1999 coexists with BEL and
LUX for 149 years – and it makes bucket 206 the first bucket key carrying
three live polities at once.
A bucket resolves here only because it is also an area
There is one key column, area_code, and callers hand it two kinds of
code: a raw FAOSTAT reporting area, and a polity_area_code aggregation
bucket – which is what reporting_polity_code is resolved from on every
summed row. Nothing in a row says which of the two it answers for, and that
works only because the bucket key space is a subset of the area key
space: every polity_area_code is also an area_code here, in all three
Rest-of-World modes. A bucket code that were not a reporting area would
match no row, so the fold would keep its area label through the member
fallback and lose reporting_polity_code to NA without complaint. The
subset property is asserted by the test suite rather than assumed.
A row may legitimately answer in both spaces, which is why the two are
not split. (238, ETH-1952-1993) is the case: as a bucket row it dates
bucket 238, which sums FAOSTAT area 62 Ethiopia PDR for 1961-1992; as an
area row it dates FAOSTAT area 238 itself for a historical source reported
under its own year's borders, which is how 149 historical-trade rows resolve
at 1961. Marking it for one space would move the other. See #742.
(206, F206-2011-2025) is the one row written for the bucket, and it
answers in the area space too: raw FAOSTAT area 206 for 2012 onwards
resolves to it. Nothing is misattributed by that, because FAOSTAT emits no
area-206 row after 2011 – the claim is unexercised rather than false – but
it is the first row for which the two spaces could be told apart at all,
which is the column #742 asks for and this table still does not carry.
Confidence is the pair, not mapping_status alone
"matched" covers outcomes of very different confidence – a curated hit in
upstream's published FAOSTAT map, a prefix-inferred period outside every span
that map declares, a prefix guess for an area the map does not cover, and the
FABIO Rest-of-World fold. mapping_source is the column that separates
them, and it is non-NA on every row, so read the two together rather than
filtering on mapping_status == "matched" and assuming a curated decision:
dplyr::count(polity_area_crosswalk, mapping_status, mapping_source)Curated rows are mapping_source == "upstream_map"; everything a prefix
decided is "prefix_outside_map" or "prefix_fallback". Prefix inference
never overrides the map where the map speaks: a prefix-derived period whose
years overlap any span the map declares for that area is dropped at build
time, so the two branches cannot disagree about a reported year.
The row space is reporting areas, not polities
This table is not an index of polities, and reading a missing
polity_code as a coverage gap is the mistake #875 records. The builder
starts from the reporting areas of regions_full.csv and asks which polity
each one names; a polity therefore has a row only if some reporting area
names it. 176 of the 735 live polities have none, because no FAOSTAT or
FABIO area was ever reported under their territory – 121 national, 33
colonial, 8 aggregate and the rest smaller units. The 559 that remain are
exactly the distinct non-NA polity_code values here.
Absence is structural rather than accidental, and the test suite asserts it:
not one of the absent aggregate polities carries a legacy_polity_prefix
any reporting area carries, so the row space has no slot to put them in.
A polity absent from here is reached by the label route instead –
resolve_polity_label() over polity_label_aliases, which maps the label a
historical source writes straight to a polity and needs no area code. That
is how five of the eight absent aggregates resolve –
GCT-1919-1956 Gold Coast and British Togoland, MASG-1946-1963,
SYL-1944-1953 (all scoped to the fao1952 yearbook),
PAPNG-1920-1949 (mitchell) and AOI-1936-1941 (any source) – all of
them pre-FAOSTAT combined reporting units that never had an area code.
Two more (EGYSUD-1934-1956, CODRU-1922-1960) are upstream
composed-union identities held for footnote series that fold a colony into
its metropole, and upstream has registered no label for them yet, so they
are reachable from neither route by design rather than by omission.
No absence here can NA an area_code on a polycell, either:
build_polycell_support() excludes polity_type == "aggregate" by type
before any lookup runs, so an aggregate emits no polycell to carry one.
F206-2011-2025 used to be the one absence that was a real gap, and it is
filled: it now has a row, keyed on the bucket rather than on a reporting
area, so polity_bucket_coverage() classifies bucket 206 "aggregate" from
2012 instead of "predecessor". See the bucket section above; #742's
key_role column, which would mark a row as answering in only one of the
two key spaces, is still open and is not what applies_from_year does.
