Town Boundaries of Bicol Region

This notebook prepares the study area’s geographical data. It downloads Philippine administrative boundaries, filters them to isolate the Bicol Region, and cleans the town names before saving the data.

0 Preliminaries

import os

import contextily as cx
import geopandas as gpd
import matplotlib.pyplot as plt
from matplotlib.axes import Axes
BASE_PATH = os.path.join(".", "outputs")

if not os.path.exists(BASE_PATH):
    os.makedirs(BASE_PATH)

1 Load data from Humanitarian Data Exchange

filename = (
    "https://data.humdata.org/dataset/caf116df-f984-4deb-85ca-41b349d3f313/resource/"
    "314cbaea-c7a0-4ce9-a4ea-e5af2a788ac1/download/phl_adm_psa_namria_20231106_gdb.gdb.zip"
)

gdf_bounds = gpd.read_file(filename, layer="phl_admbnda_adm3_psa_namria_20231106")
gdf_bounds.head()
/home/ainz/Code/transport-network-analysis/.venv/lib64/python3.13/site-packages/pyogrio/raw.py:198: RuntimeWarning: organizePolygons() received a polygon with more than 100 parts.  The processing may be really slow.  You can skip the processing by setting METHOD=SKIP.
  return ogr_read(
ADM3_EN ADM3_PCODE ADM2_EN ADM2_PCODE ADM1_EN ADM1_PCODE ADM0_EN ADM0_PCODE date validOn validTo ADM3_REF ADM3ALT1EN Shape_Length Shape_Area AREA_SQKM geometry
0 Adams PH0102801 Ilocos Norte PH01028 Region I (Ilocos Region) PH01 Philippines (the) PH 2022-11-09 00:00:00+00:00 2023-11-06 00:00:00+00:00 NaT None None 0.423604 0.009506 111.143026 MULTIPOLYGON (((120.96915 18.51012, 120.95867 ...
1 Bacarra PH0102802 Ilocos Norte PH01028 Region I (Ilocos Region) PH01 Philippines (the) PH 2022-11-09 00:00:00+00:00 2023-11-06 00:00:00+00:00 NaT None None 0.309136 0.004725 55.303195 MULTIPOLYGON (((120.66821 18.28705, 120.66441 ...
2 Badoc PH0102803 Ilocos Norte PH01028 Region I (Ilocos Region) PH01 Philippines (the) PH 2022-11-09 00:00:00+00:00 2023-11-06 00:00:00+00:00 NaT None None 0.599295 0.006880 80.683970 MULTIPOLYGON (((120.47814 17.97717, 120.47816 ...
3 Bangui PH0102804 Ilocos Norte PH01028 Region I (Ilocos Region) PH01 Philippines (the) PH 2022-11-09 00:00:00+00:00 2023-11-06 00:00:00+00:00 NaT None None 0.483066 0.009843 115.059041 MULTIPOLYGON (((120.81318 18.53457, 120.81358 ...
4 City of Batac PH0102805 Ilocos Norte PH01028 Region I (Ilocos Region) PH01 Philippines (the) PH 2022-11-09 00:00:00+00:00 2023-11-06 00:00:00+00:00 NaT None None 0.613500 0.013493 158.123132 MULTIPOLYGON (((120.61242 18.10947, 120.612 18...

2 Limit coverage to Bicol Region

gdf_bounds = gdf_bounds[gdf_bounds["ADM1_EN"].str.contains("Bicol")]
gdf_bounds = gdf_bounds.reset_index(drop=True)
_, ax = plt.subplots(figsize=(8, 8))

gdf_bounds.plot(ax=ax, edgecolor="white", facecolor="seagreen", linewidth=0.5)

x_min, y_min, x_max, y_max = gdf_bounds.total_bounds
padding = 0.1
ax.set_xlim(x_min - padding, x_max + padding)
ax.set_ylim(y_min - padding, y_max + padding)

cx.add_basemap(
    ax,
    crs=gdf_bounds.crs,
    source=cx.providers.CartoDB.Positron,
    attribution="",
)

ax.set_title("Town Boundaries of Bicol Region")
ax.set_axis_off()
plt.tight_layout()

filepath = os.path.join(BASE_PATH, "boundaries.png")
plt.savefig(filepath, dpi=300, bbox_inches="tight")

plt.show()

3 Select relevant columns

gdf_bounds = gdf_bounds[["ADM3_EN", "ADM2_EN", "geometry"]]
gdf_bounds = gdf_bounds.rename(columns={"ADM3_EN": "town", "ADM2_EN": "province"})
gdf_bounds.head()
town province geometry
0 Bacacay Albay MULTIPOLYGON (((123.84193 13.3341, 123.84204 1...
1 Camalig Albay MULTIPOLYGON (((123.6559 13.06131, 123.65536 1...
2 Daraga (Locsin) Albay MULTIPOLYGON (((123.71487 13.03995, 123.71474 ...
3 Guinobatan Albay MULTIPOLYGON (((123.68355 13.25321, 123.67729 ...
4 Jovellar Albay MULTIPOLYGON (((123.6559 13.06131, 123.65568 1...

4 Format town names

gdf_bounds["town"] = gdf_bounds["town"].str.replace(r"\s*\(.*\)", "", regex=True)

mask = gdf_bounds["town"].str.startswith("City of ", na=False)
gdf_bounds.loc[mask, "town"] = gdf_bounds["town"].str.removeprefix("City of ")
gdf_bounds.loc[mask, "town"] = gdf_bounds["town"] + " City"

gdf_bounds["town"].unique()
array(['Bacacay', 'Camalig', 'Daraga', 'Guinobatan', 'Jovellar',
       'Legazpi City', 'Libon', 'Ligao City', 'Malilipot', 'Malinao',
       'Manito', 'Oas', 'Pio Duran', 'Polangui', 'Rapu-Rapu',
       'Santo Domingo', 'Tabaco City', 'Tiwi', 'Basud', 'Capalonga',
       'Daet', 'San Lorenzo Ruiz', 'Jose Panganiban', 'Labo', 'Mercedes',
       'Paracale', 'San Vicente', 'Santa Elena', 'Talisay', 'Vinzons',
       'Baao', 'Balatan', 'Bato', 'Bombon', 'Buhi', 'Bula', 'Cabusao',
       'Calabanga', 'Camaligan', 'Canaman', 'Caramoan', 'Del Gallego',
       'Gainza', 'Garchitorena', 'Goa', 'Iriga City', 'Lagonoy',
       'Libmanan', 'Lupi', 'Magarao', 'Milaor', 'Minalabac', 'Nabua',
       'Naga City', 'Ocampo', 'Pamplona', 'Pasacao', 'Pili',
       'Presentacion', 'Ragay', 'Sagñay', 'San Fernando', 'San Jose',
       'Sipocot', 'Siruma', 'Tigaon', 'Tinambac', 'Bagamanoc', 'Baras',
       'Caramoran', 'Gigmoto', 'Pandan', 'Panganiban', 'San Andres',
       'San Miguel', 'Viga', 'Virac', 'Aroroy', 'Baleno', 'Balud',
       'Batuan', 'Cataingan', 'Cawayan', 'Claveria', 'Dimasalang',
       'Esperanza', 'Mandaon', 'Masbate City', 'Milagros', 'Mobo',
       'Monreal', 'Palanas', 'Pio V. Corpus', 'Placer', 'San Jacinto',
       'San Pascual', 'Uson', 'Barcelona', 'Bulan', 'Bulusan',
       'Casiguran', 'Castilla', 'Donsol', 'Gubat', 'Irosin', 'Juban',
       'Magallanes', 'Matnog', 'Pilar', 'Prieto Diaz', 'Santa Magdalena',
       'Sorsogon City'], dtype=object)

5 Save data

filepath = os.path.join(BASE_PATH, "boundaries.gpkg")
gdf_bounds.to_file(filepath, driver="GPKG")