Skip to content

polars-pycountry

ISO 3166 and ISO 4217 code lookup for Polars, as a native Rust expression plugin.

Turning a country column into codes looks like a dictionary lookup until you meet real data. US, USA, 840, United States, United States of America and πŸ‡ΊπŸ‡Έ are all the same country; CΓ΄te d'Ivoire and Cote d'Ivoire are not the same string; CA is Canada or California depending on the column next to it. The reference answer in Python is pycountry β€” a good library, but a Python one. Inside Polars it can only be driven through Expr.map_elements, one interpreter round-trip per row.

This package reads the same iso-codes tables pycountry ships, implements its lookup rules in Rust, and exposes them as ordinary Polars expressions. It is built to produce identical output to pycountry, not merely similar output β€” see Correctness.

import polars as pl
import polars_pycountry as pc

df = pl.DataFrame({
    "country": ["USA", "united kingdom", "276", "πŸ‡«πŸ‡·", "Nowhere", None],
})

df.with_columns(
    pc.alpha_2("country").alias("alpha_2"),
    pc.alpha_3("country").alias("alpha_3"),
    pc.name("country").alias("name"),
    pc.flag("country").alias("flag"),
)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”
β”‚ country        ┆ alpha_2 ┆ alpha_3 ┆ name           ┆ flag β”‚
β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•ͺ═════════β•ͺ═════════β•ͺ════════════════β•ͺ══════║
β”‚ USA            ┆ US      ┆ USA     ┆ United States  ┆ πŸ‡ΊπŸ‡Έ   β”‚
β”‚ united kingdom ┆ GB      ┆ GBR     ┆ United Kingdom ┆ πŸ‡¬πŸ‡§   β”‚
β”‚ 276            ┆ DE      ┆ DEU     ┆ Germany        ┆ πŸ‡©πŸ‡ͺ   β”‚
β”‚ πŸ‡«πŸ‡·             ┆ FR      ┆ FRA     ┆ France         ┆ πŸ‡«πŸ‡·   β”‚
β”‚ Nowhere        ┆ null    ┆ null    ┆ null           ┆ null β”‚
β”‚ null           ┆ null    ┆ null    ┆ null           ┆ null β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”˜

Install

pip install polars-pycountry
# or
uv add polars-pycountry

Prebuilt wheels cover Linux (glibc and musl, x86_64 and aarch64), macOS (Intel and Apple Silicon), and Windows (x64 and arm64). There is one wheel per platform rather than one per Python version, because the extension is built against the stable ABI. An sdist is published too, so anything else builds from source given a Rust toolchain β€” see CONTRIBUTING.md.

pycountry is not a runtime dependency. The ISO tables are compiled into the extension; pycountry is installed only for the test suite, which asserts the two agree.

Compatibility

Python 3.10+ β€” one abi3 wheel covers all versions
Polars 1.37+ β€” the plugin FFI ABI is (0, 1) and unchanged across that range
Linux manylinux2014 and musllinux_1_2, x86_64 and aarch64
macOS x86_64 (10.12+) and arm64 (11.0+)
Windows x64 and arm64

If a future Polars release bumps the plugin ABI, this package fails loudly at load rather than miscomputing.

Where to go next

  • Usage β€” the three expression families, null semantics, and the .country namespace.
  • Matching β€” exact vs. fuzzy, historic codes, and why fuzzy is opt-in.
  • The ISO tables β€” the vendored snapshot, overriding it, and swapping it in a running process.
  • Performance β€” measured throughput against map_elements, and when not to reach for this.
  • Correctness β€” how parity with pycountry is proven.
  • API reference β€” every public expression and helper.
  • Architecture β€” how this implementation maps onto pycountry's.