La normalización de campos de texto, como nombres de calles, códigos o descripciones, es una tarea fundamental en cualquier sistema de información geográfica (SIG), especialmente cuando se integran fuentes de datos heterogéneas con diferentes convenciones o estructuras. RapidFuzz es una librería Python especializada en comparación de cadenas mediante algoritmos de fuzzy matching, que permite encontrar coincidencias aproximadas entre textos. En este artículo vamos a explorar una estrategia de normalización de textos con RapidFuzz y Python, aplicando algoritmos de comparación difusa (fuzzy matching) para geocodificar edificios a partir de capas de callejero.
RapidFuzz: una herramienta para normalización de textos en python
RapidFuzz ha sido optimizada para ofrecer un alto rendimiento en la comparación de cadenas y maneja de forma eficaz caracteres especiales y acentos. En este ejemplo, usamos la función partial_ratio, ratio y token_sort_ratio, para capturar tanto coincidencias parciales como exactas e independientes del orden de las palabras. El objetivo final es corregir el campo addr:street de cada edificio asignándole la calle más similar de su entorno, combinando precisión léxica y proximidad espacial. Esta técnica forma parte de una estrategia de normalización de textos con RapidFuzz y Python aplicada a datos espaciales.
Ejemplo práctico: normalización de direcciones en SIG
Partimos de dos capas vectoriales en formato GeoPackage: una de edificios (edificios.gpkg) descargada desde OpenStreetMap y otra de callejero (callejero.gpkg) procedente de la Infraestructura de Datos Espaciales (IDE) del Ayuntamiento de Madrid. Al provenir de fuentes distintas, es común que existan diferencias en la nomenclatura de las direcciones.
Paso a paso del proceso
Carga de capas con GeoPandas
import geopandas as gpd
from rapidfuzz import process, fuzz
# Leer las capas
gdf_edificios = gpd.read_file("edificios.gpkg")
gdf_callejero = gpd.read_file("callejero.gpkg")En esta primera sección se realiza la carga de datos espaciales desde archivos GeoPackage, utilizando la librería GeoPandas. Estas capas contienen la información de los edificios y del callejero que serán comparados.
Comparación de direcciones mediante fuzzy matching
# Función para obtener la dirección más similar
def obtener_direccion_similar(row):
direccion = row['addr:street']
geometria_edificio = row['geometry']
# Si ya tenemos esta dirección en el cache, la devolvemos
if direccion in cache_direcciones:
return cache_direcciones[direccion]
# Filtrar calles en un radio de 1km
buffer_1km = geometria_edificio.buffer(1000)
calles_cercanas = gdf_callejero[gdf_callejero.intersects(buffer_1km)]
# Obtener solo los nombres de las calles cercanas
direcciones_cercanas = calles_cercanas['DIRECCION'].unique()
# Si no hay calles cercanas, buscar en todo el callejero
if len(direcciones_cercanas) == 0:
direcciones_cercanas = gdf_callejero['DIRECCION'].unique()
# Obtener las mejores coincidencias con diferentes scorers
matches_partial = process.extract(direccion, direcciones_cercanas, scorer=fuzz.partial_ratio, limit=3)
matches_ratio = process.extract(direccion, direcciones_cercanas, scorer=fuzz.ratio, limit=3)
matches_token_sort = process.extract(direccion, direcciones_cercanas, scorer=fuzz.token_sort_ratio, limit=3)
# Combinar y ponderar los resultados
mejores_matches = {}
for match in matches_partial + matches_ratio + matches_token_sort:
nombre = match[0]
score = match[1]
if nombre not in mejores_matches:
mejores_matches[nombre] = score
else:
mejores_matches[nombre] = max(mejores_matches[nombre], score)
# Seleccionar la mejor coincidencia
if mejores_matches:
mejor_match = max(mejores_matches.items(), key=lambda x: x[1])
if mejor_match[1] >= 80: # Umbral de similitud
cache_direcciones[direccion] = mejor_match[0]
return mejor_match[0]
cache_direcciones[direccion] = None
return NoneAquí se define la lógica de comparación fuzzy para encontrar la dirección más parecida del callejero a la dirección de un edificio. Se utiliza una estrategia que combina diferentes scorers (partial_ratio, ratio, token_sort_ratio) y se aplica un umbral mínimo del 80% para asegurar la calidad del emparejamiento. También se emplea una caché para evitar repetir búsquedas y se filtran previamente las calles dentro de un buffer de 1 km alrededor del edificio.
Aplicación del algoritmo y exportación de resultados
# Aplicar la función a cada fila de gdf_edificios
gdf_edificios['DIRECCION_CORREGIDA'] = gdf_edificios.apply(obtener_direccion_similar, axis=1)
# Guardar resultado
gdf_edificios.to_file("edificios_geocodificados.gpkg", driver="GPKG")Finalmente, se aplica la función definida a cada registro de la capa de edificios, se seleccionan solo las columnas relevantes y se exporta el resultado corregido a un nuevo archivo GeoPackage. Este archivo contendrá las direcciones originales junto con su equivalente corregido y podrá ser utilizado en otros análisis o visualizaciones SIG.
Tras aplicar el procedimiento, podemos ver como algunas de las direcciones iniciales han sido correctamente asignadas a la dirección definida desde la capa del callejero.

Ventajas de usar RapidFuzz para normalización de textos en SIG
Este enfoque se apoya en una combinación de estrategias que mejoran tanto el rendimiento como la precisión del emparejamiento o comparación de direcciones en entornos SIG:
- Optimización espacial: limita las comparaciones a calles dentro de un radio de 1 km, reduciendo el número de comparaciones y acelerando el proceso.
- Uso de caché: evita recalcular coincidencias para direcciones repetidas, mejorando la eficiencia.
- Comparación avanzada con múltiples scorers: utiliza distintas funciones de RapidFuzz para medir la similitud entre cadenas:
partial_ratio: útil para coincidencias parciales.ratio: ideal para coincidencias exactas.token_sort_ratio: permite comparar cadenas con las mismas palabras en distinto orden.
- Combinación de resultados y umbral de calidad: se obtienen las tres mejores coincidencias con cada función, se combina la puntuación más alta por calle y solo se acepta la coincidencia si supera un umbral del 80% de similitud.
Este enfoque evita falsos positivos y mejora la fiabilidad, resolviendo casos como «Plaza de la Armería» frente a «Plaza de Armería», donde token_sort_ratio puede identificar que ambas contienen las mismas palabras aunque en diferente orden, y el umbral garantiza que no se seleccionen coincidencias dudosas. En conjunto, se trata de una solución eficaz de normalización de textos con RapidFuzz y Python en entornos geoespaciales.
Aplicaciones en el ámbito SIG
La normalización de textos con RapidFuzz y Python no solo mejora la calidad de los datos, sino que también abre la puerta a otras posibles aplicaciones en el entorno SIG.
- Normalización de direcciones: unificar nomenclaturas entre fuentes distintas.
- Geocodificación local: asignar nombres de calles a edificios en ausencia de coordenadas precisas.
- Integración de datos: comparar registros con diferentes esquemas de codificación o nomenclatura.
- Limpieza de datos: detectar y corregir errores ortográficos o inconsistencias.
Resumiendo
La combinación de RapidFuzz con optimización espacial y almacenamiento en caché representa una solución robusta para tareas de geocodificación y limpieza de direcciones en entornos SIG. Este enfoque permite una mejora significativa en la precisión y eficiencia del tratamiento de datos alfanuméricos vinculados a ubicaciones geográficas.
¿Quieres comentarnos algo? Adelante!