Postal Codes Dataset for Philippines, PH

377
Updated:
Files:1
Size:240 kB
Rows:2,317
Formats:csv

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

Part of a Data Solution

  • Postal Codes Solution

    Every worldwide postal-code dataset in one bundle — the ultimate global reference for precise postal codes.

    Explore →

Premium

You're viewing a free sample

Get the complete dataset — all rows and files — delivered instantly after checkout, with lifetime access to the latest version.

  • Secure checkout via Stripe
  • Instant download after payment
  • Lifetime access to the latest version
  • Creative Commons Attribution 4.0 (GeoNames) license
20% off
$49.90$39.92
one-time payment

API Access

Access dataset files directly from scripts, code, or AI agents.

Browse dataset files
Dataset Files

Each file has a stable URL (r-link) that you can use directly in scripts, apps, or AI agents. These URLs are permanent and safe to hardcode.

/logistics/postal-codes-ph/
https://datahub.io/logistics/postal-codes-ph/_r/-/.licensing-notes.md
https://datahub.io/logistics/postal-codes-ph/_r/-/.migration-notes.md
https://datahub.io/logistics/postal-codes-ph/_r/-/ATTRIBUTION.txt
https://datahub.io/logistics/postal-codes-ph/_r/-/README.md
https://datahub.io/logistics/postal-codes-ph/_r/-/datapackage.yaml
Key Files

Start with these files — they give you everything you need to understand and access the dataset.

datapackage.yaml— metadata & schema
https://datahub.io/logistics/postal-codes-ph/_r/-/datapackage.yaml
README.md— documentation
https://datahub.io/logistics/postal-codes-ph/_r/-/README.md
Typical Usage
  1. 1. Fetch datapackage.yaml to inspect schema and resources
  2. 2. Download data resources listed in datapackage.yaml
  3. 3. Read README.md for full context

Data Files

postal-codes-ph-sample


About this dataset

Philippines (PH): migration notes

Internal record of the P5 migration from the old scripts to the producer: the discrepancies found, their causes, and who decided what. This is a dated record, so the numbers are as of the migration and not kept current. It is not shipped in the zip.

  • Issue: pc-28e.7.43 (closed 2026-10-03)
  • Commit: 69801b0 (worktree commit 4806b0f, landed unchanged), batch 4; follow-up 568cd10 by the orchestrator (PSGC in sources, rapidfuzz in requirements-producers.txt)
  • Parity verdict: unexplained (2 unclassified cells plus a duplicate key on both sides; the gate blocks on either); accepted
  • Producer: custom, refresh disabled

Sources

InputURLNotes
GeoNames postal exporthttps://download.geonames.org/export/zip/PH.zip
GeoNames gazetteer dumphttps://download.geonames.org/export/dump/PH.zipUsed for alternative_city_name
PSA PSGC register via the psgc.gitlab.io APIhttps://psgc.gitlab.io/api/provinces/, /cities-municipalities/, /barangays/Stable, undated URLs; the same API the old enrich_admin.py used
  • Live ph.csv carries cleaned names and dump alternate names, which come from the monthly generic GeoNames job (geonames_parse_to_R2.py), with build_base.py's fixes and enrich_admin.py's PSGC enrichment on top. Until 2026-08-19 build_base.py read a snapshot of the live R2 file (ph_r2_snapshot_2026-08-18.csv). After it was repointed to the raw GeoNames export, it would have shipped alternative_city_name empty, because nothing reproduced the alternate-names join.
  • The producer folds in all three layers, so the GeoNames-job step (name cleaning + dump alternate names, the same rule as scripts/producers/geonames.py) is back.

Parity against the live zip (2026-10-03)

Rows: 2,317 live and 2,317 fresh, none only on one side. 14 changed rows. All PSGC admin columns (admin_code2, admin_name3, admin_code3), all names and all ISO region codes match live exactly.

ClassCellsExamplesCause
float_suffix_dropped13 (6 latitude, 7 longitude)7021 Midsalip lat 8.0 → 8; 3521 Santa Praxedes lon 121.0 → 121; 5309 San Vicente 10.0/119.0 → 10/119The old pipeline went through pandas, which writes .0; the producer copies GeoNames' text. Same number
unclassified, alternative_city_name26108 Himamaylan: empty → Khimamejlen; 8002 Digos: Digos City → emptyGeoNames dump drift. Today's entry 1711718 (Himamaylan) lists Khimamejlen,Химамейлен; entry 1714956 (Digos) lists Digos first, which equals place_name and is dropped, so Digos City no longer wins

Duplicate key (both sides): 1412 Isla de Cocomo / Isla De Cocomo. GeoNames has both rows, differing only in case. parity.py casefolds keys, so it counts them as a duplicate; the exact primary key is unique and frictionless accepts it. The same pair is in live.

Decisions

DecisionByBasis
Accept the 2 alt-name cellsUser, 2026-10-03 (session d33e1b7e): "in general I accept any changes that stem from updated source data"Said in reply to the pl/ph question ("Accept both?"), which the user had left unanswered in the form. Recorded as the extended standing rule in docs/parity/p5.md
Accept the 13 float_suffix_dropped cellsKnown class signed off by the user in P4 (2026-10-02, docs/parity/p4.md)Also listed in the same pl/ph question
Accept the case-only duplicate keyOrchestrator, after the user's general replyIt's in live and upstream alike; the reply didn't address it explicitly
Rebuild the GeoNames-job layer (name cleaning + alternate names from the dump) instead of porting only the in-repo scripts, which would have emptied alternative_city_nameAgent: matches what live was built fromNot put to the user as a separate question; the handback listed it as the first folded step
List PSA PSGC in the descriptor sourcesOrchestrator, on landing (568cd10)The agent flagged that only GeoNames was listed
Add rapidfuzz==3.10.0 to requirements-producers.txtOrchestrator, on landing (568cd10)The agent couldn't edit outside datasets/ph/; the producer imports it lazily and the tests skip without it
Drop row, distinct-code and fill counts from README; keep admin-unit counts (17 regions, 87 provinces and districts, 82 provinces)Agent, per the README counts ruleATTRIBUTION.txt untouched

Transforms carried over

Folded, in order, from the GeoNames job → build_base.py → enrich_admin.py (fetch_source.py, integrity_checker.py, package.py, publish_r2.py and the scripts README deleted):

  • GeoNames job: clean_name on place_name and admin_name1–3 (parenthesised part dropped, punctuation → space, whitespace collapsed, e.g. "Manila CPO-PO Box# 1000 to 1099" → "Manila CPO PO Box 1000 to 1099"); alternative_city_name = first non-numeric alternate name of the dump entry whose asciiname equals the cleaned place_name (last entry wins).
  • build_base.py: null-ish literals ("nan", "none", "null", …) cleared and cells stripped; accuracy as an integer; admin_code1 = ISO 3166-2:PH for all 17 regions (Metro Manila NCR → 00); an alternate equal to place_name (case-insensitive) dropped.
  • enrich_admin.py: admin_code2 = 9-digit PSGC code of the province or NCR district; admin_name3/admin_code3 = the LGU by the rule cascade (NCR district, LGU name in province, NCR barangay, unique LGU name, barangay in province, unique barangay, NCR CPO anchor, rapidfuzz WRatio ≥ 92 within the province, code-sibling); otherwise a city GeoNames supplied is kept, with its PSGC code when the name matches.
  • No row added, dropped or reordered. integrity_checker.py's hard gates are now ProducerErrors: 4-digit postal code, unique (postal_code, place_name), no null-ish cell, every region mapped and present, region name ↔ code one-to-one, coordinates inside the Philippines, accuracy 1–6, every admin_code3 in the PSGC register. No row-count assert.

Open questions

  • .licensing-notes.md still carries counts (2,317 rows, 403 rows, …) and describes the old scripts; left for the end-of-epic sweep (pc-hfz).

Provenance

Reconstructed 2026-10-05 from the agent transcript d33e1b7e-5027-498a-a97f-ba914ee2524e/subagents/agent-ae607b241a17fc834.jsonl, the orchestrator session d33e1b7e-… (hold, question, user reply, landing and follow-up commit), the commit messages, the bd notes and close reason, and docs/parity/p4.md / p5.md.