Skip to contents

Year-aware bridge from numeric reporting area_code values used by FAOSTAT/FABIO-derived WHEP data to periodized WHEP polity_code values.

Usage

polity_area_crosswalk

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 from regions_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 polities polity_code, so a join to polities on it comes back empty. Read polity_code for the polity this row resolves to. Until #711 the pair shipped as reporting_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, or NA for 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_year is exclusive at a succession, so the period covers polity_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 inclusive map_year_end below 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 published whep-polities FAOSTAT 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, NA unless mapping_source is "upstream_map".

  • map_match_route: Upstream's record of how it decided the row ("iso-equal", "registry", "manual-route", "manual-replace", "manual-span"), NA unless mapping_source is "upstream_map".

  • applies_from_year: First year the row answers for, when that is later than polity_start_year. NA on 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 answers SDN-2011-2025 from 2011 even though upstream begins reporting the area in 2012. It is non-NA only 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 (a manual-* 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 has NA in both area_code and polity_area_code and 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.