OvertureMaps / OvertureMaps/data

address_levels hierarchy inconsistent: 3-level countries have variable depth (LV 62%, SK 55% missing finest level)

Open Beginner friendly
#509 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.2k
Forks
47
Avg merge
3h 42m
Merged PRs (30d)
1

Description

Summary

In the 2026-03-18.0 release, several countries listed with 3 address_levels have a variable number of populated levels. When consumers assume the finest level (index [3]) always contains the city/municipality, they lose significant coverage — up to 62% for Latvia and 55% for Slovakia.

This is similar to #367 (US addresses with NULL address_levels[2]), but affects the 3-level countries more severely.

Affected Countries

3-level countries with variable depth
Country Total addresses level3 populated level3 NULL (city must come from level2 or level1) % lost if only checking level3
LV (Latvia) 548,712 208,256 340,456 62.0%
SK (Slovakia) 1,697,528 757,325 940,203 55.4%
EE (Estonia) 2,228,661 2,076,759 151,902 6.8%
IT (Italy) 25,914,431 25,912,438 1,993 <0.01%
TW (Taiwan) 9,630,602 9,630,597 5 <0.01%
Latvia — 3 distinct hierarchy patterns
Pattern 1 (111K): Major cities — only level1 populated
  level1=Rīga, level2=NULL, level3=NULL
  → City IS level1 (Rīga)

Pattern 2 (229K): Novads + town — level1 and level2 populated
  level1=Jēkabpils nov., level2=Jēkabpils, level3=NULL
  → City IS level2 (Jēkabpils)

Pattern 3 (208K): Novads + pagasts + village — all 3 levels
  level1=Olaines nov., level2=Olaines pag., level3=Jāņupe
  → City IS level3 (Jāņupe)
Slovakia — 2 patterns
Pattern 1 (940K): District — level3 NULL
  level1=Bratislavský, level2=Bratislava-Ružinov, level3=NULL
  → City IS level2 (Bratislava-Ružinov)

Pattern 2 (757K): Municipality — all 3 levels
  level1=Prešovský, level2=Spišská Nová Ves, level3=Spišská Nová Ves
  → City IS level3 (Spišská Nová Ves)
Estonia — 2 patterns
Pattern 1 (152K): Linn (town) — level3 NULL
  level1=Ida-Viru maakond, level2=Narva linn, level3=NULL
  → City IS level2 (Narva linn)

Pattern 2 (2.1M): Village/district — all 3 levels
  level1=Harju maakond, level2=Tallinna linn, level3=Kesklinn
  → City IS level3 (Kesklinn)

Also: US (related to #367)

The 2-level US data still has 37.6M addresses (30%) with address_levels[2] = NULL. Of those, 85% (32.1M) have postal_city as a fallback, but 5.5M US addresses have no city information at all — no level2 AND no postal_city. Top states affected: TX (1.7M), MS (852K), CA (575K), FL (455K).

Query to Reproduce

-- Shows all country × depth combinations
SELECT country,
  len(address_levels) as levels_count,
  CASE
    WHEN address_levels[3].value IS NOT NULL THEN 'level3'
    WHEN address_levels[2].value IS NOT NULL THEN 'level2'
    WHEN address_levels[1].value IS NOT NULL THEN 'level1'
    ELSE 'none'
  END AS finest_populated_level,
  count(*) as cnt
FROM read_parquet(
  's3://overturemaps-us-west-2/release/2026-03-18.0/theme=addresses/type=address/*',
  hive_partitioning=0
)
GROUP BY country, levels_count, finest_populated_level
ORDER BY country, levels_count, finest_populated_level

Suggestion

It would help consumers if the documentation clarified that:

  1. address_levels depth is variable within a country — the array length doesn't guarantee all values are populated
  2. The recommended city extraction pattern is a COALESCE cascade (finest → coarsest):
    COALESCE(address_levels[3].value, address_levels[2].value, address_levels[1].value)
    
  3. For US addresses without level2, postal_city is the intended fallback (and covers 85%)

This would prevent other consumers from hitting the same issue we did when building a geocoder on top of this data.

Environment

  • Release: 2026-03-18.0
  • Queried via DuckDB 1.5 + MotherDuck
  • 39 countries, 469M addresses total

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Review the documentation for address_levels and reproduce the issue with the provided DuckDB SQL query against the release data. Update the relevant guidance to explain variable depth, recommend the finest-to-coarsest COALESCE pattern, and document postal_city as the US fallback; done means consumers can identify city values without assuming index [3].

Written by the indexing model from the issue text.

Assessment

Tech stack
sql
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.