Geocodificación de direcciones con Python
Para representar en un mapa las direcciones con la localización de personas, sucesos como accidentes, denuncias, incidencias de algún servicio, o cualquier otra elemento, se necesita realizar un proceso de geocodificación. Al geocodificar direcciones básicamente lo que hacemos es calcular las coordenadas geográficas latitud y longitud de un lugar donde solo conocemos el nombre de una localidad, un código postal o una dirección de calle.
¿Qué nos aporta la geocodificación? Principalmente con ella podemos mostrar localizaciones en un mapa y determinar las relaciones entre lugares, como son distancias, direcciones, o un patrón de dispersión. Pero además, determinando la ubicación de personas, cosas o sucesos podemos asociar sus localizaciones con otros datos que tengan una referencia geográfica como el censo demográfico, las transacciones de ventas, la concentración de accidentes de tráficos, contaminación, la distribución espacial de alguna enfermedad, etc.
Geocodificar una dirección a nivel de calle es el proceso más preciso para localizar un lugar, pero esto requiere una base de datos de referencia bastante completa que permita una localización a nivel de número de portal, información que no siempre es posible obtener.
Geocodificar múltiples direcciones
Un ejemplo de geocodificación muy fácil es introducir una dirección en la barra de búsqueda de Google Maps y la URL devuelta contendrá la longitud y latitud del lugar.
Si tenemos un listado de direcciones podríamos realizar esto a mano, pasando cada dirección una por una, aunque no es una opción muy atractiva. Una alternativa más interesante es programar algún script que las lea de un archivo csv y nos devuelva los pares de coordenadas latitud y longitud que necesitamos para posicionar esos puntos en nuestro mapa. Para ello necesitamos un geocodificador de direcciones que las analice en elementos identificables (nombre de la calle, número, localidad, región, código postal), que compare esas direcciones con la información almacenada en una base de datos de referencia, evalúe la similitud entre todos los candidatos y determine unas coordenadas geográficas para esa dirección en caso de que el porcentaje de similitud sea elevado.
Podemos realizar geocodificaciones masivas de diversas maneras. A través de un software de escritorio instalados en el ordenador, como ArcGIS, QGIS o Google Earth, o mediante un servicio de geocodificación on line como Google Map o Bing.
Ya hablamos en otra entrada de la geocodificación utilizando OpenRefine, pero en esta lo que nos interesan son los servicios on line con una interfaz de programación de aplicaciones (API) que nos permitan utilizar algún lenguaje de programación para geocodificar una vasta cantidad de direcciones. En Internet existen varios y la siguiente tabla muestra algunos de ellos:
Google Maps Geocoding API | Bing Maps REST Services | ESRI ArcGIS on line | ESRI ArcGIS Desktop | OpenStreetMap (vía Nominatim |
GeoNames | OpenCage | Mapbox | |
Requiere programación | No, si se usa Google Earth Pro o QGIS con el componente mmqgis | Sí | Sí | No | Sí | Sí | Sí | Sí |
Limitaciones en número de peticiones | 2.500 en periodos de 24 horas y 5 por segundo. | 10.000 al mes. 5.000 al día para aplicaciones Windows. | 1.250 al día. | Ilimitadas. | 1 petición por segundo en Nominatim. |
Ilimitadas. | 2.500 por día en periodo beta. | Los resultados deben ser mostrados en un mapa de Mapbox. 1 geocodificación por petición. |
Calidad de la información | Alta | Alta | Alta | Alta | Media (depende de las zonas) | Media | Variable. Combina varios sistemas de geocodificación | Alta |
Covertura geográfica | Mundial | Mundial | Mundial | Depende de la base de datos utilizada | Mundial, aunque la precisión depende mucho de las zonas. | Parcial. Depende del país. | Mundial | Mundial |
Servicio on line o local | On line | On line | On line | On line y local | On line | On line | On line | On line |
Geocodificar direcciones con Python
Uno de los módulos más conocidos en Python para realizar geocodificación es geopy. Con él podremos utilizar varios servicios web de geocodificación como OpenStreetMap Nominatim, ESRI ArcGIS, Google Geocoding API (V3), Baidu Maps, Bing Maps API, Yahoo! PlaceFinder, Yandex, IGN France, GeoNames, NaviData, OpenMapQuest, What3Words, OpenCage, SmartyStreets, geocoder.us o GeocodeFarm.
Además de poder realizar geocodificaciones y geocodificaciones inversas (encontrar una dirección a partir de unas coordenadas), geopy también es capaz de medir distancias entre dos puntos. El siguiente código muestra la forma de geocodificar un listado de direcciones almacenadas en un archivo CSV. En este caso utilizamos el servicio de Nominatim y creamos otro CSV donde guardamos las coordenadas que corresponden a cada dirección.
# -*- coding: utf-8 -*- #Importación del módulo Nominatim de geopy que utilizaremos para geocodificar from geopy.geocoders import Nominatim #Importación del módulo csv que necesitaremos para leer y escribir en nuestros csv import csv #Importación del módulo shutil que usaremos para crear una copia de nuestro csv original import shutil #Realizamos una copia del archivo csv original que llamaremos procesado.csv shutil.copyfile("original.csv","procesado.csv") #Abrimos el archivo y le asignamos una variable. archivo = open('original.csv', 'rb') #Creamos una lista vacía donde almacenaremos las direcciones. direcciones = [] #Utilizamos la función reader para leer el contenido del csv cuyas columnas están delimitadas por el caracter ; csv_archivo = csv.reader(archivo, delimiter=';') #Vamos leyendo la primera columna de cada fila del csv y añadiendo la dirección a la lista. for fila in csv_archivo: direcciones.append(fila[0]) #Cerramos el archivo abierto archivo.close() #Creamos un nueva lista donde se guardarán las localizaciones. localizaciones = [] #Cada servicio de geolocalización como Google Maps, Bing Maps, Yahoo, MapQuest o Nominatim tiene su propia clase en geopy.geocoders para utilizar el servicio API. #Creamos un objeto llamado geolocalizador a partir de la clase Nominatim(). geolocalizador = Nominatim() #Para cada dirección almacenada en la lista 'direcciones' pedimos al servicios de geocodificación de Nominatim que nos devuelva su coordenada y la guardamos en la variable 'coordenadas'. Añadimos la latitud y lo9ngitud a la lista 'localizaciones'. for val in direcciones: direccion = geolocalizador.geocode([val], timeout=15) localizaciones.append((direccion.latitude, direccion.longitude)) #Creamos una cabecera para nuestro nuevo csv. cabecera = ['DIRECCION','COORDENADAS'] #Abrimos de nuevo el archivo original y guardamos todos los datos en la variable 'datos'. Finalmente cerramos el archivo. archivo = open('original.csv') datos = [item for item in csv.reader(archivo, delimiter=';')] archivo.close() #Creamos una nueva lista llamada 'nuevos_datos' nuevos_datos = [] #Para cada item en la lista 'datos' añadimos sus cordenadas almacenadas en la lista 'localizacion'. Finalmente incorporamos todo el conjunto a la lista 'nuevos_datos'. for i, item in enumerate(datos): item.append(localizaciones[i]) print localizaciones[i] nuevos_datos.append(item) #Abrimos el archivo procesado.csv que habíamos creado y le asignamos una variable. El parámetro wb indica que queremos escribir. Añadimos una cabecera seguido de las filas con cada uno de los datos almacenados en la lista. Cerramos el archivo. archivo = open('procesado.csv', 'wb') csv.writer(archivo, delimiter=';', lineterminator='\n').writerow(cabecera) csv.writer(archivo, delimiter=';', lineterminator='\n').writerows(nuevos_datos) archivo.close()
Algo a tener en cuenta, es que el servicio de geocodificación de OpenStreetMap basado en Nominatim no requiere de ninguna key ni de registro, puede ser instalado en local (gracias @Xeviby) y no tiene límite de consultas. Por contra presenta dos principales inconvenientes:
- Al utilizar datos de OpenStreetMap la calidad de los resultados varía mucho según la zona geográfica.
- En sus búsquedas no filtra muchas de las palabras vacías de algunos idiomas, lo que condiciona su uso para la georreferenciación de direcciones en español, por ejemplo. No obstante, sí es efectivo para la geocodificación de poblaciones o para realizar geocodificaciones inversas.
Imagen de portada CC: Thomas Abbs, tomada de Flickr.

GIS Project Manager con más de 15 años de experiencia en el campo de los Sistemas de Información Geográfica (GIS) participando en proyectos aplicados al transporte y movilidad, los servicios urbanos, el medio ambiente y el patrimonio.