datasets.faostat¶
The FAOSTAT Detailed Trade Matrix: download, local Parquet store, bundled sample and metadata. See Data and licences for provenance and the ETL rules.
FAOSTAT Detailed Trade Matrix: download, local Parquet store, and queries.
The Detailed Trade Matrix (FAOSTAT domain TM) records bilateral trade in about 560 agricultural products for roughly 220 countries and territories from 1986. FAO publishes it as a single zip of about 420 MB (8.5 GB of CSV).
This module works in two steps:
build_storedownloads the zip once withpooch, checks its SHA-256 against the value pinned in this release, and converts it with DuckDB into a Parquet dataset partitioned by item. Amanifest.jsonwritten next to the data records the source URL, the SHA-256 actually used, the retrieval time, row counts and the library version.loadruns a DuckDB query over only the partitions you ask for and returns a flow frame. Queries take well under a second per item.
load_sample runs the same query over a small Parquet file that ships
with the package (wheat, maize and soya beans, 2010 to 2024), so the
examples and tests work offline.
Flow frames and labels
The store keeps FAOSTAT's own vocabulary, but load and
load_sample return the library's generic flow frame
(netviz_tools.FLOW_COLUMNS):
source: the exporting country;target: the importing country;time: the year;category: the FAOSTAT item (commodity);weight: the quantity, or the trade value withmeasure="value";unit:t,head,numberor1000 USD.
Every returned frame also carries a copy of LABELS in
flows.attrs["labels"] (with "weight": "Value" for trade values).
netviz_tools.build_graph copies it into G.graph["labels"], and the
plots use these display labels, so FAOSTAT charts say "Exporter" and
"Importer" without you having to type them.
Reporting perspective
Every trade flow can be reported twice: by the exporting country and by the
importing country. The two reports often differ, and some countries stop
reporting (the Russian Federation reports no exports after 2021). load
lets you choose:
"importer"(default): flows as reported by the importing country. More countries report imports than exports (for wheat in 2021, 155 against 99)."exporter": flows as reported by the exporting country."combined": the importer's report where one exists, otherwise the exporter's, decided per (exporter, importer, item, year).
The reporter parameter and the reported_by column of details=True
keep the FAOSTAT words "importer" and "exporter".
Data licence
FAOSTAT data are published under CC BY 4.0. Cite them as, for example:
"FAO. 2025. FAOSTAT: Detailed trade matrix. Accessed on 27 September 2026.
https://www.fao.org/faostat/en/#data/TM. Licence: CC-BY-4.0." Use
CITATION for the template.
Reporter
module-attribute
¶
Whose report of each flow to use. See the module documentation.
Measure
module-attribute
¶
"quantity" returns physical amounts (t, head or number);
"value" returns trade value in 1000 USD.
ENV_CACHE_DIR
module-attribute
¶
Environment variable that overrides the default cache directory.
CITATION
module-attribute
¶
CITATION: Final = "FAO. {year}. FAOSTAT: Detailed trade matrix. Accessed on {accessed}. https://www.fao.org/faostat/en/#data/TM. Licence: CC-BY-4.0."
Citation template required by the FAO database terms of use.
LABELS
module-attribute
¶
LABELS: Final[Mapping[str, str]] = {
"source": "Exporter",
"target": "Importer",
"time": "Year",
"category": "Item",
"weight": "Quantity",
"node": "Country",
"out": "Exports",
"in": "Imports",
}
Display labels for FAOSTAT trade flows, keyed by generic flow-frame term.
load and load_sample attach a copy to every frame as
flows.attrs["labels"] (with "weight": "Value" when
measure="value"); graphs and plots pick them up from there.
default_cache_dir
¶
Return the cache directory used when none is given.
The NETVIZ_TOOLS_CACHE environment variable takes precedence; otherwise
the operating system's user cache directory is used (via
pooch.os_cache). Nothing is created until data is downloaded.
Returns:
| Type | Description |
|---|---|
Path
|
The cache directory. |
store_path
¶
Return the directory that holds (or will hold) the Parquet store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_dir
|
str | PathLike[str] | None
|
Cache directory. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
|
items
¶
Return the catalogue of FAOSTAT trade items.
The catalogue ships with the package, so it works before any download.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
search
|
str | None
|
Optional case-insensitive substring to filter item names and slugs. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Columns |
Examples:
countries
¶
Return metadata for every FAOSTAT area in the trade matrix.
Regions come from the UN M49 standard; label points (lon, lat)
come from Natural Earth. Pass the result to
netviz_tools.build_graph as node_attrs to colour nodes by
continent.
Returns:
| Type | Description |
|---|---|
DataFrame
|
Indexed by FAOSTAT area |
download
¶
download(
cache_dir: str | PathLike[str] | None = None,
*,
known_hash: str | None = FAOSTAT_TRADE_SHA256,
progressbar: bool = False,
) -> Path
Download the FAOSTAT bulk zip into the cache, or reuse a cached copy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_dir
|
str | PathLike[str] | None
|
Cache directory. Defaults to |
None
|
known_hash
|
str | None
|
Expected SHA-256. Defaults to the value pinned in this release. Pass
|
FAOSTAT_TRADE_SHA256
|
progressbar
|
bool
|
Show a download progress bar (requires |
False
|
Returns:
| Type | Description |
|---|---|
Path
|
Path to the zip. |
Raises:
| Type | Description |
|---|---|
SourceHashMismatchError
|
If the file does not match |
build_store
¶
build_store(
cache_dir: str | PathLike[str] | None = None,
*,
zip_path: str | PathLike[str] | None = None,
known_hash: str | None = FAOSTAT_TRADE_SHA256,
force: bool = False,
progressbar: bool = False,
threads: int | None = None,
) -> Path
Build the local Parquet store from the FAOSTAT bulk zip.
This is a one-time step. It needs network access (unless zip_path is
given), about 9 GB of temporary disk space for the extracted CSV, and a
minute or two on a laptop. The finished store is about 400 MB.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_dir
|
str | PathLike[str] | None
|
Cache directory for the zip and the store. Defaults to
|
None
|
zip_path
|
str | PathLike[str] | None
|
Use a zip you already have instead of downloading it. It is still
checked against |
None
|
known_hash
|
str | None
|
Expected SHA-256 of the zip. Defaults to the value pinned in this
release. FAO replaces the file in place when it publishes an update;
to build from a newer file, pass |
FAOSTAT_TRADE_SHA256
|
force
|
bool
|
Rebuild even if a store already exists. |
False
|
progressbar
|
bool
|
Show a download progress bar (requires |
False
|
threads
|
int | None
|
Number of DuckDB threads. Defaults to all cores. |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
The store directory. |
Raises:
| Type | Description |
|---|---|
SourceHashMismatchError
|
If the zip does not match |
SchemaError
|
If the CSV inside the zip does not have the expected columns. |
store_info
¶
Return the manifest of the local store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_dir
|
str | PathLike[str] | None
|
Cache directory. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The parsed |
Raises:
| Type | Description |
|---|---|
StoreNotFoundError
|
If the store has not been built. |
load
¶
load(
items: str | int | Iterable[str | int],
years: int | Iterable[int] | None = None,
*,
reporter: Reporter = "importer",
measure: Measure = "quantity",
self_loops: bool = False,
details: bool = False,
cache_dir: str | PathLike[str] | None = None,
) -> FlowFrame
Load flows for some items and years from the local store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
str | int | Iterable[str | int]
|
One or more items, each given as a FAOSTAT item code ( |
required |
years
|
int | Iterable[int] | None
|
A year, an iterable of years (such as |
None
|
reporter
|
Reporter
|
|
'importer'
|
measure
|
Measure
|
|
'quantity'
|
self_loops
|
bool
|
Keep flows reported between a country and itself (re-imports). |
False
|
details
|
bool
|
Add |
False
|
cache_dir
|
str | PathLike[str] | None
|
Cache directory that holds the store. |
None
|
Returns:
| Type | Description |
|---|---|
FlowFrame
|
Columns |
Raises:
| Type | Description |
|---|---|
UnknownItemError
|
If an item is not in the catalogue. The error suggests close matches. |
StoreNotFoundError
|
If |
load_sample
¶
load_sample(
items: str | int | Iterable[str | int] | None = None,
years: int | Iterable[int] | None = None,
*,
reporter: Reporter = "importer",
self_loops: bool = False,
details: bool = False,
) -> FlowFrame
Load flows from the small sample that ships with the package.
The sample holds quantity flows in tonnes (both reporting perspectives)
for Wheat, Maize (corn) and Soya beans from 2010 to 2024, taken from the
pinned FAOSTAT release (about 140,000 rows, 0.6 MB). It uses the same
query as load.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
str | int | Iterable[str | int] | None
|
Items to keep; defaults to all three sample items. |
None
|
years
|
int | Iterable[int] | None
|
Years to keep; defaults to all. |
None
|
reporter
|
Reporter
|
As for |
'importer'
|
self_loops
|
Reporter
|
As for |
'importer'
|
details
|
Reporter
|
As for |
'importer'
|
Returns:
| Type | Description |
|---|---|
FlowFrame
|
Raises:
| Type | Description |
|---|---|
UnknownItemError
|
If an item is not in the catalogue, or is in the catalogue but not in the sample. |
Examples:
raw_sample
¶
raw_sample(
items: str | int | Iterable[str | int] | None = None,
years: int | Iterable[int] | None = None,
) -> DataFrame
Return the bundled sample in the column layout of the FAOSTAT bulk file.
This is the bundled sample (see load_sample) re-expanded into the
layout of the bulk CSV, so that netviz_tools.clean
can be demonstrated offline on a realistic reporter-based table. It is
not a fresh download. Each row is one country's report: a flow reported
by the exporter appears with that country as reporter and the element
"Export quantity"; a flow reported by the importer appears with the
importer as reporter and "Import quantity". Self-loops are included,
as in the bulk file. The M49 and CPC code columns of the bulk file are
omitted because the sample does not carry them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
str | int | Iterable[str | int] | None
|
Items to keep; defaults to all three sample items. |
None
|
years
|
int | Iterable[int] | None
|
Years to keep; defaults to all. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
Columns |
Raises:
| Type | Description |
|---|---|
UnknownItemError
|
If an item is not in the catalogue, or is in the catalogue but not in the sample. |
Examples: