(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo hacer enriquecimiento geográfico en ETL: paso a paso

João Barros 15 de September de 2026 4 min de lectura

Este tutorial muestra cómo hacer enriquecimiento geográfico en ETL para añadir latitud/longitud y municipio a registros de clientes. Enriquecer datos geográficos hace que los análisis y las visualizaciones sean más útiles (mapas, segmentación por región) y mejora los informes de negocio.

Requisitos previos

  • Python 3.8+ instalado
  • Bibliotecas: requests, pandas
  • Fichero CSV con columna de dirección (address)
  • Clave de API de un servicio de geocodificación (p. ej.: Nominatim o Google Geocoding)

Paso 1: Preparar los datos de entrada

Empieza por cargar el CSV y garantizar que la columna address está normalizada (trim, eliminar duplicados obvios). Esto evita llamadas innecesarias a la API y costes. También crearemos un identificador único para cada dirección.

import pandas as pd

data = pd.read_csv('clientes.csv')
# Normalizar espacios y eliminar filas sin dirección
data['address'] = data['address'].astype(str).str.strip()
data = data[data['address']!='']
# Crear clave para deduplicación
data['addr_key'] = data['address'].str.lower()

Paso 2: Deduplicación antes de la geocodificación

Hacer geocodificación es costoso; deduplicamos las direcciones para llamar a la API solo una vez por dirección distinta. Mantenemos un mapeo para reaplicarlo a los registros originales.

# Obtener direcciones únicas
unique_addrs = data[['addr_key','address']].drop_duplicates().reset_index(drop=True)

Paso 3: Implementar la llamada a la API de geocodificación con manejo de errores

Crearemos una función sencilla que llama a la API (ejemplo con Nominatim) y gestiona errores básicos y límites de tasa. En producción utiliza reintentos exponenciales y caché persistente.

import requests
import time

def geocode(address, email='seu_email@example.com'):
    # Ejemplo con Nominatim (OpenStreetMap) — respeta políticas de uso
    url = 'https://nominatim.openstreetmap.org/search'
    params = {'q': address, 'format': 'json', 'limit': 1, 'addressdetails': 1, 'email': email}
    try:
        resp = requests.get(url, params=params, timeout=10)
        if resp.status_code == 200:
            j = resp.json()
            if j:
                lat = j[0].get('lat')
                lon = j[0].get('lon')
                city = j[0].get('address', {}).get('city') or j[0].get('address', {}).get('town') or j[0].get('address', {}).get('village')
                return {'latitude': float(lat), 'longitude': float(lon), 'city': city}
            return None
        else:
            return None
    except requests.RequestException:
        return None

# Prueba rápida (solo una dirección)
# print(geocode('Praça do Comércio, Lisbon'))

Paso 4: Ejecutar geocodificación en lote con caché en memoria

Recorremos las direcciones únicas, guardamos resultados en un diccionario (cache) y aplicamos un pequeño delay para evitar rate limits. En escenarios mayores, usa un caché persistente (Redis, fichero) y workers paralelos con throttling.

cache = {}
results = []
for idx, row in unique_addrs.iterrows():
    key = row['addr_key']
    addr = row['address']
    if key in cache:
        results.append({'addr_key': key, **cache[key]})
        continue
    res = geocode(addr)
    if res:
        cache[key] = res
        results.append({'addr_key': key, **res})
    else:
        cache[key] = {'latitude': None, 'longitude': None, 'city': None}
        results.append({'addr_key': key, 'latitude': None, 'longitude': None, 'city': None})
    time.sleep(1)  # Respetar límites del servicio

geo_df = pd.DataFrame(results)

Paso 5: Reunir los datos geocodificados con el dataset original

Hacemos un join entre los resultados de geocodificación y el dataset original por el campo addr_key. Así cada cliente recibe latitud, longitud y ciudad.

final = data.merge(geo_df, on='addr_key', how='left')
# Eliminar columnas temporales si es necesario
final = final.drop(columns=['addr_key'])
final.to_csv('clientes_enriquecidos.csv', index=False)

Verificar el resultado

Abre el fichero clientes_enriquecidos.csv y confirma que cada registro tiene latitud y longitud válidas o valores nulos controlados. Haz muestreos: verifica 10 direcciones con y sin coordenadas. Para validar geográficamente, cárgalo en una herramienta de visualización (p. ej.: Power BI o QGIS) y confirma que los puntos caen en los lugares esperados.

Conclusión

Has implementado un flujo de enriquecimiento geográfico sencillo en ETL: normalización, deduplicación, geocodificación con manejo básico de errores y unión de los resultados. Próximos pasos: añadir caché persistente, reintentos exponenciales, paralelismo controlado y validación de precisión (comprobaciones de distancia). Consejo: empieza probando con un subconjunto antes de procesar todo el dataset para evitar costes y bloqueos de la API.