Spot-check page for the FAOSTAT flag audit

This page checks out/map-2022.png and out/reporting-lag.png, built from the same out/stocks.csv.gz and the same raw archive. It answers one question: does the map faithfully represent the source, and where would I notice if it did not. The assertions in src/build_table.py and src/draw_map.py are the record; this page recomputes them in the browser, it does not replace them. Every number below is computed from the embedded data at load. Nothing is pre-aggregated, so every count clicks through to the rows behind it.

0

Provenance and self-check

Each row recomputes a quantity from the embedded data and compares it with the canonical value in out/numbers.json. Red is the point of the table.
1

The filter funnel

A real country in the defunct list, a fourth name in the composite-item stage, a blank-value row whose flag is not M, an off-diagonal cell in the unit crosstab, or China's four parts failing to sum to the composite row.

Sequential counts: a row removed as an aggregate is not counted again as a composite item. The standalone column is how many rows each rule matches on its own, and the two differ where rules overlap. Click a stage to read the rows it removed.

Whole file

Selected year

Element by unit: this must be diagonal

Element 5112 is filed in thousands of head. If the mapping were not one to one, the times-1000 scaling would hit the wrong rows and throw no error.

China 351 against its four parts

The composite row and the sum of mainland, Hong Kong, Macao and Taiwan for the selected year. A non-zero difference means the composite is not what the filter assumes it is.

2

Rows as filed: country and species lookup

A 1000 An row whose filed value already looks like a head count, a flag outside A E I X, two rows with the same area, item and year, or a value and a head that do not stand in the right ratio.

The kept table, exactly as it sits in out/stocks.csv.gz. Value as filed and head after normalisation are always shown side by side, because hiding the filed value is how the thousands trap becomes invisible. Click an area to open its card in panel 3.

3

Drawn against source

A geometry whose name has nothing to do with the FAO area it matched. That is the view that would have caught Taiwan being drawn with the Dominican Republic's data, and it is the first row of the table when you sort by name similarity.

One row per geometry per species, read from out/map-2022-drawn.csv, which draw_map.py writes as it paints. The join key is the M49 code, so a wrong key produces a perfectly consistent picture of the wrong country: the flag will agree with the source row it matched, and the only thing out of place is the name. That is why the check that matters here is name similarity and distinct areas drawn, not flag agreement.

(a) Matched pairs, least similar name first

Similarity is a plain trigram overlap between the Natural Earth name and the FAO area name. Legitimate pairs score low too (Natural Earth "China" against FAO "China, mainland"), so the list is read, not thresholded.

(b) FAO areas with no geometry

Must be empty. On the broken build it holds China, Taiwan Province of.

(d) M49 keys carried by more than one geometry

Must be empty apart from the sentinel. Two geometries on one key means one country is about to be painted with another's data.

(c) Geometries with no FAO area

These render grey on every panel. The sentinel rows are geometries Natural Earth does not give a UN code at all; two of them are given one by hand in draw_map.py.

Drawn flag against source flag, all geometry-species rows

4

Reconciliation to the FAO's own World row

A non-zero difference in a species that used to reconcile at zero, which would mean a filter stage started removing a real country or an aggregate leaked in.

The country sum from the kept table against FAOSTAT's published World row, which the pipeline never uses as an input. The World row is a comparison, never a denominator. Click any cell for the areas with a series but no row in that year.

5

Flag composition over time

Any series drawn across 2014 to 2015 without the rule, and the recomputed lag numbers failing to match the shipped out/reporting-lag.csv to the decimal.

The FAO reclassified its own estimated and imputed labels between 2014 and 2015. Across that break the estimated share falls from about 24 per cent to 8 and the imputed share rises from 3 to 38, which reads as a collapse in data quality and is a change of vocabulary. The rule is drawn on every axis on this page for that reason.

Reporting lag, both denominators

lag_panel.py computes the per-country official share over whatever species each country happens to report; the adversarial review asked for it restricted to countries reporting all five. The two series differ and neither is picked silently here. Recomputed values are shown beside the shipped CSV; any disagreement is flagged.

6

One country, all years

A switch from official to imputed, an imputed value that is an exact copy of the previous year, a series that jumps in value across the 2015 rule, or a country whose rows exist but whose geometry block says no geometry.

What the map painted for this country

Switches from official to imputed

The ratio is the imputed value over the last official one. A ratio of exactly 1.000 would mean the value was carried forward, which is not what the FAO does here.

Every core row for this country

7

Where the imputation is

A top imputed row whose country card shows an official figure for the same year, an X row that is not one of the nine, or the cumulative share failing to reach 100.
8

Missing species and non-reporting areas

A large producer missing a species it certainly farms, a gap country appearing in the never-reported list, or the grey count on a panel failing to equal the two lists plus the territories.

Areas by species

Per species: which kind of blank

Natural Earth features that are not FAO reporting areas at all

Grey on every panel in every year. They are not gaps in reporting; there is no FAOSTAT area behind them.