Published

Singapore (SG) build pipeline

Postal Codes Dataset for Singapore, SG including name of the city, town, or place, various administrative divisions and alternative city names.

Singapore (SG) build pipeline

Builds from a staged Universal-Schema (FedEx-pipeline) export, not a live fetch — the raw postal source was already scraped once and staged as sources/singapore_fedex_base.csv (121,513 rows, one per postal code, building-level, 0 duplicates). The original scraper still exists and is maintained separately at ~/Desktop/Research/fedex-agents-prototype/countries/SGP/scripts/scrape_postal.py if the base ever needs re-fetching from scratch — not duplicated here, this pipeline picks up from the staged export.

Column mapping (Universal Schema -> 13-column postal-codes schema):

SourceTargetNote
countryCodecountry_codeSG, not SGP — this repo's convention is alpha-2
postalCodepostal_code
additionalInfoplace_nameBUILDING name if present, else ROAD_NAME, else subzone as last resort
stateName / stateCodeadmin_name1 / admin_code1CDC District
countyadmin_name2URA Planning Area; no code source exists
cityNameadmin_name3URA Subzone; no code source exists
(none)alternative_city_namenothing available — left blank, not invented

latitude/longitude/accuracy are intentionally left blank by build_base.pyjoin_coordinates.py fills them from a separately staged geocode lookup (sources/singapore_coordinates.csv) in a second pass, the same two-stage shape as Canada's admin2 enrichment.

Run order

python3 build_base.py
python3 join_coordinates.py
python3 integrity_checker.py
python3 package.py
python3 publish_r2.py          # dry run by default; --apply to publish

Verification (2026-08-19)

Byte-identical. All 4 output files (csv, datapackage.json, README.md, zip) match what's live on R2 exactly. publish_r2.py (written this session — it didn't exist before) confirms a zero-diff plan on dry run.