spa-l1-capetown-hospital-nn
Map (reference ← swipe → agent)
0:00
I am putting together EMS coverage planning for the Western Cape and need each residential pickup address tagged with its nearest hospital so the ops-research team can join the result against shift schedules. For every address in `addresses.parquet`, find the nearest hospital from `hospitals.parquet` by straight-line distance and record that hospital's name plus the distance in metres. Keep the original `address_id` from the input so we can join back to the address master, and make sure `nearest_hospital_name` comes through as a non-empty string and `distance_m` as a numeric, finite, non-negative value in metres.
Please write the result to `nearest_hospital.gpkg` in GeoPackage format with one feature per input address, keeping the original address geometry and the columns `address_id`, `nearest_hospital_name`, and `distance_m`.
0:00
System info
{
"adapter": "openrouter",
"model": "deepseek/deepseek-v4-flash",
"base_url": "https://openrouter.ai/api/v1"
}
0:09
0:09
Bash
cd /work && ls -la addresses.parquet hospitals.parquet 2>/dev/null
-rw-r--r-- 1 agent agent 10609 Jun 16 07:44 addresses.parquet -rw-r--r-- 1 agent agent 10031 Jun 16 07:44 hospitals.parquet
0:13
0:13
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import pandas as pd
addr = pd.read_parquet('addresses.parquet')
hosp = pd.read_parquet('hospitals.parquet')
print('=== ADDRESSES ===')
print(addr.head(3))
print(addr.columns.tolist())
print(addr.dtypes)
print(f'Shape: {addr.shape}')
print()
print('=== HOSPITALS ===')
print(hosp.head(3))
print(hosp.columns.tolist())
print(hosp.dtypes)
print(f'Shape: {hosp.shape}')
"
=== ADDRESSES === address_id geometry 0 A0001 b'\x01\x01\x00\x00\x00\xc2\x99$,\xcf\x882@\xcd... 1 A0002 b'\x01\x01\x00\x00\x00\xfcg\xbf\x12\xc2\x802@t... 2 A0003 b'\x01\x01\x00\x00\x00\xb8\xa8\x80\x7fG\x882@r... ['address_id', 'geometry'] address_id str geometry object dtype: object Shape: (120, 2) === HOSPITALS === hospital_id ... geometry 0 H001 ... b"\x01\x01\x00\x00\x00\xb7''^\x8ey2@\x12\xf4z\... 1 H002 ... b'\x01\x01\x00\x00\x00\xb5\x01THdw2@\x15\xe1`N... 2 H003 ... b'\x01\x01\x00\x00\x00\x0b\xe8K\x90\x8dk2@\xd6... [3 rows x 3 columns] ['hospital_id', 'name', 'geometry'] hospital_id str name str geometry object dtype: object Shape: (37, 3)
0:18
0:18
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import geopandas as gpd
addr = gpd.read_parquet('addresses.parquet')
hosp = gpd.read_parquet('hospitals.parquet')
print('=== ADDRESSES CRS ===')
print(addr.crs)
print(addr.geometry.iloc[0])
print()
print('=== HOSPITALS CRS ===')
print(hosp.crs)
print(hosp.geometry.iloc[0])
print()
print('=== HOSPITALS names ===')
print(hosp['name'].head(10))
print(hosp['name'].isna().sum(), 'null names')
"
=== ADDRESSES CRS ===
{"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "GeographicCRS", "name": "WGS 84", "datum_ensemble": {"name": "World Geodetic System 1984 ensemble", "members": [{"name": "World Geodetic System 1984 (Transit)"}, {"name": "World Geodetic System 1984 (G730)"}, {"name": "World Geodetic System 1984 (G873)"}, {"name": "World Geodetic System 1984 (G1150)"}, {"name": "World Geodetic System 1984 (G1674)"}, {"name": "World Geodetic System 1984 (G1762)"}, {"name": "World Geodetic System 1984 (G2139)"}, {"name": "World Geodetic System 1984 (G2296)"}], "ellipsoid": {"name": "WGS 84", "semi_major_axis": 6378137, "inverse_flattening": 298.257223563}, "accuracy": "2.0", "id": {"authority": "EPSG", "code": 6326}}, "coordinate_system": {"subtype": "ellipsoidal", "axis": [{"name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree"}, {"name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree"}]}, "scope": "Horizontal component of 3D system.", "area": "World.", "bbox": {"south_latitude": -90, "west_longitude": -180, "north_latitude": 90, "east_longitude": 180}, "id": {"authority": "EPSG", "code": 4326}}
POINT (18.534411200462053 -33.94183671394203)
=== HOSPITALS CRS ===
{"$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", "type": "GeographicCRS", "name": "WGS 84", "datum_ensemble": {"name": "World Geodetic System 1984 ensemble", "members": [{"name": "World Geodetic System 1984 (Transit)"}, {"name": "World Geodetic System 1984 (G730)"}, {"name": "World Geodetic System 1984 (G873)"}, {"name": "World Geodetic System 1984 (G1150)"}, {"name": "World Geodetic System 1984 (G1674)"}, {"name": "World Geodetic System 1984 (G1762)"}, {"name": "World Geodetic System 1984 (G2139)"}, {"name": "World Geodetic System 1984 (G2296)"}], "ellipsoid": {"name": "WGS 84", "semi_major_axis": 6378137, "inverse_flattening": 298.257223563}, "accuracy": "2.0", "id": {"authority": "EPSG", "code": 6326}}, "coordinate_system": {"subtype": "ellipsoidal", "axis": [{"name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree"}, {"name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree"}]}, "scope": "Horizontal component of 3D system.", "area": "World.", "bbox": {"south_latitude": -90, "west_longitude": -180, "north_latitude": 90, "east_longitude": 180}, "id": {"authority": "EPSG", "code": 4326}}
POINT (18.47482861 -33.94920784)
=== HOSPITALS names ===
0 Mowbray Maternity Hospital
1 Life Claremont Hospital
2 Old Somerset Hospital
3 Mpheni Block C Elim Hospital
4 Life Kingsbury Hospital
5 Groote Schuur Hospital Renal Unit
6 Red Cross War Memorial Children's Hospital
7 NSH(New Somerset Hospital)
8 Out Patient Department Groote Schuur Hospital
9 UCT Private Academic Hospital
Name: name, dtype: str
0 null names
0:37
0:37
Write
/work/solve.py
content · 77 lines · py
import geopandas as gpd
import pandas as pd
import numpy as np
from shapely.geometry import Point
# ---------------------------------------------------------------------------
# 1. Load inputs
# ---------------------------------------------------------------------------
addr = gpd.read_parquet("/work/addresses.parquet")
hosp = gpd.read_parquet("/work/hospitals.parquet")
# Both are in WGS84 (EPSG:4326) — confirm
assert addr.crs is not None and addr.crs.to_epsg() == 4326, "Addresses CRS is not EPSG:4326"
assert hosp.crs is not None and hosp.crs.to_epsg() == 4326, "Hospitals CRS is not EPSG:4326"
# ---------------------------------------------------------------------------
# 2. Reproject to a metric CRS suitable for the Western Cape
# UTM zone 34S (EPSG:32734) covers the Western Cape well.
# ---------------------------------------------------------------------------
METRIC_CRS = "EPSG:32734"
addr_metric = addr.to_crs(METRIC_CRS)
hosp_metric = hosp.to_crs(METRIC_CRS)
# ---------------------------------------------------------------------------
# 3. For each address, find the nearest hospital by straight-line distance
# ---------------------------------------------------------------------------
# Extract coordinate arrays for fast computation
addr_coords = np.array([(p.x, p.y) for p in addr_metric.geometry])
hosp_coords = np.array([(p.x, p.y) for p in hosp_metric.geometry])
hosp_names = hosp_metric["name"].values
n_addr = len(addr_coords)
n_hosp = len(hosp_coords)
# Pre-allocate result arrays
nearest_name = np.empty(n_addr, dtype=object)
nearest_dist = np.empty(n_addr, dtype=np.float64)
for i in range(n_addr):
ax, ay = addr_coords[i]
# Squared Euclidean distance (avoid sqrt for every comparison)
dx = hosp_coords[:, 0] - ax
dy = hosp_coords[:, 1] - ay
dist_sq = dx * dx + dy * dy
idx_min = np.argmin(dist_sq)
nearest_name[i] = hosp_names[idx_min]
nearest_dist[i] = np.sqrt(dist_sq[idx_min]) # metres
# ---------------------------------------------------------------------------
# 4. Build result GeoDataFrame
# ---------------------------------------------------------------------------
result = gpd.GeoDataFrame(
{
"address_id": addr["address_id"].values,
"nearest_hospital_name": nearest_name,
"distance_m": nearest_dist,
},
geometry=addr.geometry.values, # keep original WGS84 geometry
crs="EPSG:4326",
)
# Sanity checks
assert result["nearest_hospital_name"].notna().all(), "Found null hospital names"
assert (result["nearest_hospital_name"].str.strip() != "").all(), "Found empty hospital names"
assert np.isfinite(result["distance_m"]).all(), "Found non-finite distances"
assert (result["distance_m"] >= 0).all(), "Found negative distances"
print(f"Result has {len(result)} rows")
print(f"Distance range: {result['distance_m'].min():.2f} m – {result['distance_m'].max():.2f} m")
print(result.head())
# ---------------------------------------------------------------------------
# 5. Write to GeoPackage
# ---------------------------------------------------------------------------
result.to_file("/work/nearest_hospital.gpkg", layer="nearest_hospital", driver="GPKG")
print("\nWritten to /work/nearest_hospital.gpkg")
Wrote /work/solve.py (3236 chars).
0:39
0:39
Bash
cd /work && python solve.py
Result has 120 rows Distance range: 47.02 m – 5956.74 m address_id ... geometry 0 A0001 ... POINT (18.53441 -33.94184) 1 A0002 ... POINT (18.50296 -33.93623) 2 A0003 ... POINT (18.53234 -33.95918) 3 A0004 ... POINT (18.44857 -33.98103) 4 A0005 ... POINT (18.49928 -33.99649) [5 rows x 4 columns] Written to /work/nearest_hospital.gpkg
0:48
0:48
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import geopandas as gpd
result = gpd.read_file('nearest_hospital.gpkg')
print('Columns:', result.columns.tolist())
print('CRS:', result.crs)
print('Shape:', result.shape)
print()
print('=== First 10 rows ===')
print(result.head(10).to_string())
print()
print('=== Column dtypes ===')
print(result.dtypes)
print()
print('=== Null checks ===')
print('null names:', result['nearest_hospital_name'].isna().sum())
print('empty names:', (result['nearest_hospital_name'].str.strip() == '').sum())
print('null distances:', result['distance_m'].isna().sum())
print('negative distances:', (result['distance_m'] < 0).sum())
print('non-finite:', (~np.isfinite(result['distance_m'])).sum())
print()
print('=== Distance stats ===')
print(result['distance_m'].describe())
print()
print('=== Unique hospitals ===')
print(result['nearest_hospital_name'].nunique(), 'unique hospitals')
print(result['nearest_hospital_name'].value_counts().head(10))
"
Columns: ['address_id', 'nearest_hospital_name', 'distance_m', 'geometry'] CRS: EPSG:4326 Shape: (120, 4) === First 10 rows === address_id nearest_hospital_name distance_m geometry 0 A0001 Melomed Gatesville Private Hospital 3192.958737 POINT (18.53441 -33.94184) 1 A0002 Life Vincent Pallotti Hospital 1468.601852 POINT (18.50296 -33.93623) 2 A0003 Melomed Gatesville Private Hospital 1271.941611 POINT (18.53234 -33.95918) 3 A0004 Maitland Cottage Children's Orthopaedic Hospital 984.047189 POINT (18.44857 -33.98103) 4 A0005 Kingsbury Hospital 3021.737824 POINT (18.49928 -33.99649) 5 A0006 Intercare Physical Rehabilitation Hospital - Newlands 1777.422286 POINT (18.48709 -33.97114) 6 A0007 Melomed Gatesville Private Hospital 1268.558960 POINT (18.54461 -33.96394) 7 A0008 Melomed Gatesville Private Hospital 1264.240167 POINT (18.52017 -33.97329) 8 A0009 Melomed Gatesville Private Hospital 2020.478965 POINT (18.51179 -33.97298) 9 A0010 Red Cross Children's Hospital 1811.017934 POINT (18.49876 -33.9682) === Column dtypes === address_id str nearest_hospital_name str distance_m float64 geometry geometry dtype: object === Null checks === null names: 0 empty names: 0 null distances: 0 negative distances: 0
Traceback (most recent call last):
File "<string>", line 19, in <module>
print('non-finite:', (~np.isfinite(result['distance_m'])).sum())
^^
NameError: name 'np' is not defined
1:04
1:04
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import numpy as np
import geopandas as gpd
result = gpd.read_file('nearest_hospital.gpkg')
print('non-finite:', (~np.isfinite(result['distance_m'])).sum())
print('All checks passed!')
print()
print('File size:', end=' ')
import os
print(f'{os.path.getsize(\"nearest_hospital.gpkg\")} bytes')
"
non-finite: 0 All checks passed! File size: 118784 bytes
1:10
Everything checks out. Let me also do an `ls` to confirm the output file is in the working directory.
1:10
Bash
ls -lh /work/nearest_hospital.gpkg
-rw-r--r-- 1 agent agent 116K Jun 16 07:45 /work/nearest_hospital.gpkg
1:21