Improve address matching
This commit is contained in:
+54
-13
@@ -14,6 +14,7 @@ Usage:
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import zipfile
|
||||
@@ -374,10 +375,41 @@ out geom;"""
|
||||
|
||||
return processed_gdf
|
||||
|
||||
def _normalize_street_name(self, street: str) -> str:
|
||||
"""
|
||||
Normalize street names for better matching.
|
||||
Handles common abbreviation and formatting differences between county and OSM data.
|
||||
"""
|
||||
if not street or street == 'nan':
|
||||
return ''
|
||||
|
||||
street = street.strip()
|
||||
|
||||
# Convert to lowercase for comparison
|
||||
street_lower = street.lower()
|
||||
|
||||
# Normalize State Road variations
|
||||
street_lower = re.sub(r'\bstate road\b', 'sr', street_lower)
|
||||
street_lower = re.sub(r'\bstate route\b', 'sr', street_lower)
|
||||
|
||||
# Normalize County Road variations
|
||||
street_lower = re.sub(r'\bcounty road\b', 'cr', street_lower)
|
||||
street_lower = re.sub(r'\bc\b', 'cr', street_lower) # "C 44a" -> "cr 44a"
|
||||
|
||||
# Normalize County Road number formatting: "109d 1" -> "109d-1", "109d-1" stays same
|
||||
# This handles both space and hyphen separators
|
||||
street_lower = re.sub(r'\b(cr\s+\d+[a-z])\s+(\d+)', r'\1-\2', street_lower)
|
||||
street_lower = re.sub(r'\b(cr\s+\d+[a-z])-(\d+)', r'\1-\2', street_lower)
|
||||
|
||||
# Remove extra spaces
|
||||
street_lower = re.sub(r'\s+', ' ', street_lower).strip()
|
||||
|
||||
return street_lower
|
||||
|
||||
def compare_addresses(self, local_file: str, osm_file: str) -> Tuple[List[Dict], List[Dict], List[Dict]]:
|
||||
"""
|
||||
Compare local and OSM address data.
|
||||
|
||||
|
||||
Returns:
|
||||
Tuple of (new_addresses, existing_addresses, removed_addresses)
|
||||
"""
|
||||
@@ -435,19 +467,28 @@ out geom;"""
|
||||
local_house_num = str(local_row.get('addr:housenumber', ''))
|
||||
osm_house_num = str(osm_row.get('addr:housenumber', ''))
|
||||
|
||||
# Check street name match (required)
|
||||
local_street = str(local_row.get('addr:street', '')).strip().lower()
|
||||
osm_street = str(osm_row.get('addr:street', '')).strip().lower()
|
||||
street_match = (local_street == osm_street and local_street != '' and local_street != 'nan')
|
||||
# Check street name match (required) - use normalization for better matching
|
||||
local_street = self._normalize_street_name(str(local_row.get('addr:street', '')))
|
||||
osm_street = self._normalize_street_name(str(osm_row.get('addr:street', '')))
|
||||
street_match = (local_street == osm_street and local_street != '')
|
||||
|
||||
# Check unit match (only if both have units specified)
|
||||
# Check unit match - if either has a unit, both must match
|
||||
local_unit = local_row.get('addr:unit')
|
||||
osm_unit = osm_row.get('addr:unit')
|
||||
# Unit matches if: (1) both are None/null, OR (2) both have values and they're equal
|
||||
unit_match = True
|
||||
if local_unit is not None and pd.notna(local_unit) and osm_unit is not None and pd.notna(osm_unit):
|
||||
|
||||
# Determine if each side has a unit
|
||||
local_has_unit = local_unit is not None and pd.notna(local_unit) and str(local_unit).strip() != ''
|
||||
osm_has_unit = osm_unit is not None and pd.notna(osm_unit) and str(osm_unit).strip() != ''
|
||||
|
||||
if local_has_unit and osm_has_unit:
|
||||
# Both have units - they must match
|
||||
unit_match = (str(local_unit).strip().lower() == str(osm_unit).strip().lower())
|
||||
elif local_has_unit or osm_has_unit:
|
||||
# One has unit, other doesn't - no match
|
||||
unit_match = False
|
||||
else:
|
||||
# Neither has unit - match
|
||||
unit_match = True
|
||||
|
||||
# Only consider as potential match if house numbers, street, and unit all match
|
||||
if (local_house_num == osm_house_num and
|
||||
@@ -500,10 +541,10 @@ out geom;"""
|
||||
local_house_num = str(local_row.get('addr:housenumber', ''))
|
||||
osm_house_num = str(osm_row.get('addr:housenumber', ''))
|
||||
|
||||
# Check street name match (required)
|
||||
local_street = str(local_row.get('addr:street', '')).strip().lower()
|
||||
osm_street = str(osm_row.get('addr:street', '')).strip().lower()
|
||||
street_match = (local_street == osm_street and local_street != '' and local_street != 'nan')
|
||||
# Check street name match (required) - use normalization for better matching
|
||||
local_street = self._normalize_street_name(str(local_row.get('addr:street', '')))
|
||||
osm_street = self._normalize_street_name(str(osm_row.get('addr:street', '')))
|
||||
street_match = (local_street == osm_street and local_street != '')
|
||||
|
||||
# Check unit match (only if both have units specified)
|
||||
local_unit = local_row.get('addr:unit')
|
||||
|
||||
Reference in New Issue
Block a user