Skip to main content

geolintr

Stop silently joining datasets with mismatched ONS geography boundaries.

pip install geolintr

Requires Python 3.9+ · Zero dependencies · Built for UK government and NHS data work


The problem

Every UK government dataset uses ONS geography codes. But those codes change — sometimes quietly and sometimes dramatically:

  • CCGs became ICBs in July 2022 (106 areas became 42)
  • LSOA and MSOA boundaries were redesigned after Census 2021
  • Local authority districts merge and split regularly
  • Terminated postcodes still appear in older datasets

When you join two datasets with codes from different years, the join silently succeeds but the results are wrong. geolintr catches this before it causes problems.


Quick start

from geolintr import detect_vintages, format_report

# Check a list of codes from your dataset
codes = ["E38000240", "E38000244", "E54000028", "E54000029"]

warnings = detect_vintages(codes)
print(format_report(warnings))

Output:

============================================================
  geolintr report
============================================================
  2 error(s)  0 warning(s)  1 info(s)
============================================================

[ERROR] 2 CCG code(s) found (E38 prefix). CCGs were abolished on 1 July 2022 and replaced by ICBs (E54).
       Codes: E38000240, E38000244
       Tip:   Use geolintr.map_ccg_to_icb() to convert CCG codes to their ICB successors.

[ERROR] Both CCG (pre-2022) and ICB (post-2022) codes found. These represent different organisational boundaries.
       Codes: E38000240, E38000244, E54000028, E54000029
       Tip:   Standardise to ICB using geolintr.map_ccg_to_icb().

Detect geography type

from geolintr import detect_geo_type

info = detect_geo_type("E38000240")
info.geo_type     # "CCG"
info.description  # "CCG (England) - deprecated 2022"
info.warnings     # ["E38000240 appears to be a CCG code. CCGs were replaced by ICBs in July 2022."]

info = detect_geo_type("E54000028")
info.geo_type     # "ICB"
info.is_known     # True

Map CCG codes to ICB

from geolintr import map_ccg_to_icb

result = map_ccg_to_icb("E38000240")
result.found        # True
result.target_code  # "E54000029"
result.message      # "Mapped CCG E38000240 to ICB E54000029."

Map any codes using a custom lookup

from geolintr import map_codes

# e.g. after a LAD merger
old_to_new = {
    "E07000187": "E06000066",  # Kettering -> North Northamptonshire
    "E07000188": "E06000066",  # Corby -> North Northamptonshire
}

results = map_codes(my_lad_codes, old_to_new, on_missing="warn")
for r in results:
    if not r.found:
        print(f"No mapping for {r.source_code}")

Validate codes against a known set

from geolintr import validate_codes

valid_icbs = {"E54000028", "E54000029", "E54000030"}
result = validate_codes(my_codes, valid_icbs)

result["coverage"]      # 0.94 — 94% of codes matched
result["invalid"]       # list of unrecognised codes
result["invalid_count"] # how many failed

What changed and when

from geolintr import boundary_changes_between

changes = boundary_changes_between(2021, 2023)
for c in changes:
    print(f"{c['year']}: {c['description']}")

# 2021: LAD restructure - several mergers in England
# 2022: CCGs abolished, replaced by ICBs
# 2023: LSOA/MSOA boundaries updated for Census 2021
# 2023: Further LAD restructure

Supported geography types

Prefix Type Notes
E01/W01/N01 LSOA Redesigned after Census 2021
E02/W02 MSOA Redesigned after Census 2021
E06-E09/W06/S12/N09 LAD Changes annually
E38 CCG Abolished July 2022
E54 ICB Replaced CCGs July 2022
E40 NHS England Region Stable
E12 Region Stable
E92/W92/S92/N92 Country Stable

Why geolintr

If you work with UK open data, you have almost certainly joined datasets with mismatched boundaries without realising. The results look plausible, but the numbers are wrong. geolintr makes this class of error visible and fixable.

Built by someone who hits this issue everyday.


License

MIT

Metadata

Release files for geolintr 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for geolintr 1.0.1
File Size Uploaded Provenance Actions
geolintr-1.0.1.tar.gz 11.9 kB Without provenance Details for geolintr-1.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for geolintr 1.0.1
File Interpreter ABI Platform Actions
geolintr-1.0.1-py3-none-any.whl Python 3 none any Details for geolintr-1.0.1-py3-none-any.whl

Total release size: 22.4 kB

Release files / geolintr-1.0.1.tar.gz

Download URL geolintr-1.0.1.tar.gz
Size 11.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9053957ac0aa8d6c89728969bb306c590d3a112c8b61728abb2a894f6aada3b2
BLAKE2b-256 checksum
How to use checksums
8ac92ba59cd33b080e3e909b230d231f2613a368b697b2b4704e585e1b141480
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / geolintr-1.0.1-py3-none-any.whl

Download URL geolintr-1.0.1-py3-none-any.whl
Size 10.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2749ef5afbed3d900f7fb6878f205863fe20ad0ea71ca5917c2aac50936b6278
BLAKE2b-256 checksum
How to use checksums
a44e94ee4664a69d0f5c3d02fe4916a34ccaabc38e069c9b7afb387aba24ba8e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Security for geolintr 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page