Title Image

Blog

Sobremapa

Enriqueciendo datos con OpenRefine: geocodificación de direcciones

  |   Geolocalización, Tratamiento de datos
Sobremapa

Fotografía: Craig Luecke

En una entrada anterior (Normalización de datos con OpenRefine: un ejemplo práctico) ya pudimos ver como normalizar datos desordenados o inconsistentes a través OpenRefine, una rara avis del software libre que ocupa un nicho que no llega a alcanzar plenamente a los ETL. En este casos nos vamos a valer de esta herramienta para contextualizar los datos geográficamente mediante servicios web de terceros.

En este ejemplo vamos a crear un nuevo proyecto en OpenRefine, donde cargaremos el archivo CSV del Directorio de direcciones y teléfonos del Ministerio de Justicia, siguiendo los paso que ya vimos.

Una vez hecho esto observamos que tenemos varias columnas que recogen la dirección física de los órganos y servicios de la Administración de Justicia en Cantabria propensas para ser utilizada en la geocodificación. No obstante, antes vamos a completar estos datos con información adicional para facilitar el número de coincidencias.

Columnas con las direcciones postales de los juzgados de Cantabria

Vista en OpenRefine de las columnas con datos de las direcciones postales de los juzgados de Cantabria parcialmente desagregados.

Hay que tener en cuenta que una buena herramienta de geocodificación puede tolerar errores esperables, buscando maximizar el porcentaje de acierto en las respuestas  proporcionando tolerancia a errores tipográficos y teniendo cierta capacidad para resolver indeterminaciones. Pero, si estos son continuos y sistemáticos, inevitablemente el resultado puede producir una sesgo significativo en la nueva información que se ha creado. Por ello es conveniente simplificar la tarea del algoritmo de geocodificación hasta donde podamos.

Así, crearemos una nueva columna con nueva información que evite ambigüedades. Simplemente hacemos clic en la columna de la dirección y seleccionamos el menú Edit Column -> Add column, e introducimos la siguiente expresión:

value + ", " + cells["C.P."].value + " " + cells["LOCALIDAD"].value + ", Cantabria, España"

A la nueva columna la denominaremos «DIRECCION_EXTENDIDA».

Extendiendo la dirección con Tabula

A continuación utilizaremos la API de geocodificación de Google Maps, cuya sintaxis de solicitud es la siguiente:

http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=direccion_de_busqueda

Para ello crearé una nueva columna, que llamaremos «JSON» donde se guardará la respuesta en formato JSON que nos devolverá el servicio Google. Para ello desde la columna «DIRECCION_EXTENDIDA» seleccionamos el menú Edit Column -> Add column by fetching URLs y  añadimos la expresión con la URL del servicio web, estableciendo el parámetro de dirección con el valor de cada fila.

"http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=" + escape(value,"url")

URL de petición de geocodificación de la API de Google Maps

Hay que tener en cuenta que la mayoría de los servicios web de geocodificación restringen su API a un número limitado de peticiones por tiempo e IP para evitar abusos. Podemos ver en la captura de pantalla como en el ejemplo el retardo antes de realizar una nueva petición al servicio web para analizar la dirección de la siguiente fila es de 5000 milisegundos. Esta variable la podemos modificar según el número filas que tengamos que procesar teniendo en cuenta las restricciones que hemos comentado.

Mensaje del proceso de geocodificación

El resultado que nos devuelve cada consulta será una respuesta en formato JSON. El siguiente paso es aislar los valores lat y lng que dependen de la propiedad location y esta a su vez de geometry.

Respuesta JSON de Google Maps para geocodificar direcciones.

En notación JSON llegamos a estos valores mediante:

results[0].geometry.location.lat
results[0].geometry.location.lng

OpenRefine es capaz de analizar estos datos JSON y crear nuevas columnas extrayendo las coordenadas. Para ello desde la columna «JSON» seleccionamos Edit Column -> Add column based on this column… Nombramos a la nueva columna como «LATITUD» y escribimos la siguiente expresión GREL:

value.parseJson().results[0].geometry.location.lat

Repetimos el proceso con la longitud y et voilat!

Extracción de la longitud de los datos JSON

Una vez finalizado podemos eliminar las columnas que no necesitemos y exportar la tabla a un formato con el que poder continuar nuestro flujo de trabajo, para, por ejemplo, visualizarlo, a través de un Sistemas de Información Geográfica (SIG).

Geocodificación de una calle.

Consideraciones finales

El servicio de Google de georreferenciación de direcciones es muy bueno, sin duda. No obstante, a día de hoy la API gratuita de Google Maps no permite más de 2500 consultas de geocodificación en 24 horas y por dirección IP. Existen alternativas gratuitas, aunque vaya por delante que en la actualidad estas no están a la altura de la de Google si queremos precisiones a nivel de número de portal.

Una de ellas es la API de Nominatim, un servicio de nomenclátor desarrollada dentro del ecosistema de herramientas del proyecto OpenStreetMap, que permite la búsqueda y geocodificación de direcciones:

'http://nominatim.openstreetmap.org/search?' + 'format=json&' + 'q=' + escape(value, 'url')

El servicio de Nominatim del proyecto OSM se ejecuta sobre servidores con una capacidad limitada, por lo que tiene una política de uso restrictiva. Aún así MapQuest proporciona una versión de esta API sin límites de uso:

'http://open.mapquestapi.com/nominatim/v1/search.php?' + 'format=json&' + 'q=' + escape(value, 'url')

Hoy por hoy la versión actual de Nominatim posee limitaciones técnicas al no filtrar muchas de las stop words en español, ya que la eliminación de palabras vacías de un idioma puede causar problemas en otros, lo que condiciona su uso para la georreferenciación de direcciones en castellano. No obstante si es efectivo para la geocodificación de unidades poblacionales.