diff --git a/.gitignore b/.gitignore index 9b65dcc..ce7ccff 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ desktop.ini *.geojson osm_cache/ .claude -stack.env \ No newline at end of file +stack.env +data/ \ No newline at end of file diff --git a/convert-addresses.py b/convert-addresses.py index 30aa121..b9d7d16 100644 --- a/convert-addresses.py +++ b/convert-addresses.py @@ -27,17 +27,38 @@ qgis_functions = importlib.import_module("qgis-functions") def load_exceptions(exceptions_path='/data/exceptions.yml'): + """Load street name corrections. Each correction has 'from'/'to', and + optionally a 'city' to restrict it to addresses in that city only - + otherwise it applies everywhere that street name occurs.""" path = Path(exceptions_path) if not path.exists(): - return {} + return [] import yaml with open(path) as f: data = yaml.safe_load(f) or {} - return { - item['from']: item['to'] - for item in data.get('corrections', []) + return [ + item for item in data.get('corrections', []) if 'from' in item and 'to' in item - } + ] + + +def apply_street_exceptions(street_names, city_names, exceptions): + if not exceptions: + return street_names + result = [] + for name, city in zip(street_names, city_names): + corrected = name + if name is not None: + for item in exceptions: + if item['from'] != name: + continue + scope_city = item.get('city') + if scope_city and (city is None or city.upper() != scope_city.upper()): + continue + corrected = item['to'] + break + result.append(corrected) + return result def process_address_fields(gdf, exceptions): @@ -103,13 +124,6 @@ def process_address_fields(gdf, exceptions): for col, addr in zip(unit_from_column, unit_from_address) ] - # Apply street name exceptions - if 'addr:street' in mapping and exceptions: - mapping['addr:street'] = [ - exceptions.get(name, name) if name is not None else None - for name in mapping['addr:street'] - ] - # City for field in ['POST_COMM', 'PostalCity', 'CITY', 'Jurisdicti']: if field in processed.columns: @@ -119,6 +133,14 @@ def process_address_fields(gdf, exceptions): ] break + # Apply street name exceptions (some are scoped to a specific city) + if 'addr:street' in mapping and exceptions: + mapping['addr:street'] = apply_street_exceptions( + mapping['addr:street'], + mapping.get('addr:city', [None] * len(processed)), + exceptions, + ) + # Postcode for field in ['POST_CODE', 'ZipCode', 'ZIP', 'POSTAL_CODE']: if field in processed.columns: