Skip to content

Latest commit

 

History

History
87 lines (48 loc) · 8.66 KB

README.md

File metadata and controls

87 lines (48 loc) · 8.66 KB

dondevoto

dondevoto es un intento de construir un mapa de los locales de votación para las Primarias Abiertas Simultáneas y Obligatorias (PASO) para el año 2013. El sitio padron.gob.ar muestra la ubicación de los locales de votación una vez realizada una consulta. Esto indica que alguna dependencia estatal tiene una base de datos como la que estamos intentando construir, pero no hemos podido encontrarla y nada indica que haya sido publicada. Si ese mapa en efecto existe y es público, avisen así no trabajamos de más.

La Dirección Nacional Electoral publicó un listado de los locales de votación. En formato PDF, como no podía ser de otra manera (¿cuándo van a entender que NO hay que usar PDF para publicar datos?).

Procesamos ese archivo con Tabula para convertirlo a un formato usable. Tabula todavía no es perfecto y hubo que acomodar un poco su output, pero nada del otro mundo. En pocos minutos logramos un conjunto de datos sano, que contiene toda la información antes atrapada en PDF.

Primer intento — Google Geocoder

Una vez que tuvimos la información en CSV, formato apropiado para el intercambio y publicación de datos de este tipo, subimos el archivo a Google Fusion Tables y procesamos los registros con el geocoder. Falló estrepitosamente. La razón es la gran inconsistencia en el formato y contenido de las direcciones de los locales. Algunos ejemplos:

  • "AGUIRRE E/STORNI Y DE LA VEGA,B° LOS ALAMOS - GLEW"
  • "ROSARIO Y BOLIVAR S/N°,B° RAYO DE SOL - LON"

Descartado el geocoder.

Segundo intento — Combinando fuentes

En Argentina, las escuelas suelen servir como locales de votación. Hay excepciones (municipalidades, sociedades de fomento), pero podemos asumir con alto grado de certeza que un establecimiento (los publicados por DNE) va a corresponderse con una escuela. Este segundo intento consistió en intentar matchear cada local de votación con una escuela. Pero nos hace falta conseguir un listado de escuelas que contenga su ubicación geográfica.

Hurgando en mapaeducativo.edu.ar

El Mapa Educativo es un gran recurso de información sobre el sistema educativo argentino, confeccionado por el Ministerio de Educación de la Nación.

El sitio contiene un mapa con la ubicación precisa de todos los establecimientos educativos del país, justo lo que necesitamos. El mapa en cuestión está implementado con un GeoServer que expone un Web Mapping Service, es decir un servidor de tiles. Los tiles son imágenes (mosaicos) que, combinados, componen un mapa parecido a los de Google Maps.

Esas imágenes no pueden darnos la información que necesitamos (datos de las escuelas y su ubicación geográfica). Miramos un poco más de cerca y "descubrimos" que ese mismo GeoServer también expone un servicio Web Feature Service (WFS). Bingo.

Los layers en WFS contienen datos vectoriales, es decir, geometrías con atributos. Vimos que el layer que contiene los datos que necesitamos es men:escuelas_oferta y los transferimos a un Shapefile con ogr2ogr, parte del proyecto GDAL:

for i in `seq 1 1000 60000`;
  do ogr2ogr -append -f "ESRI Shapefile" escuelas WFS:"http://www.mapaeducativo.edu.ar/geoserver/ows?service=wfs&version=1.0.0&sortBy=gid&startIndex=$i" men:escuelas_oferta;
done

(Este WFS entrega hasta 1000 features por pedido y el layer contiene ~60k features. Por eso el loop.)

Establecimientos → Escuelas

Para laburar más cómodos, cargamos los datasets que tenemos hasta ahora en un PostgreSQL + PostGIS, valiéndonos de la librería dataset. En este punto, contamos con dos tablas en nuestra DB:

  • establecimientos (los locales de votación originalmente publicados en PDF)
  • escuelas (las escuelas georeferenciadas obtenidas del WFS de mapaeducativo.edu.ar)

La idea era implementar un matching aproximado entre el nombre, dirección, localidad y provincia de los establecimientos y los mismos campos de la tabla escuelas. Esto lo implementamos con la función get_close_matches de difflib, parte de la librería estándar de Python.

Mejoró notablemente la precisión del matching con respecto al primer intento, pero todavía teníamos muchos falsos positivos. Por ejemplo, hay muchas escuelas en el país que se llaman "Colegio Manuel Belgrano" y como nuestro matching es fuzzy, tenemos baja precisión.

Tercer intento — Restringiendo el espacio de búsqueda

Notamos que la lista de establecimientos de votación (la tabla establecimientos) tiene dos campos interesantes: codigo_distrito y seccion. Le preguntamos a la máxima autoridad electoral de la Internet que es Andy Tow y nos aseguró que codigo_distrito es un código correspondiente a cada provincia y la seccion es un número de cada partido, departamento o comuna, definido por el Código Nacional Electoral.

También contamos con la ayuda de Gonzalo Iglesias, otro gran héroe de la información pública que hace tiempo confeccionó una suerte de Piedra Rosetta de información distrital. Uno de los campos de esa tabla, es DNE_ID y se corresponde con los campos codigo_distrito y seccion de nuestra tabla establecimientos! Esto quiere decir que ahora podemos saber con seguridad en qué partido, departamento o comuna está cada local de votación.

Importamos esos datos a una nueva tabla en nuestro Postgres: divisiones_administrativas

Podemos aprovecharnos de ese hecho para mejorar el segundo intento y restringir el espacio de búsqueda: en vez de intentar nuestro fuzzy matching sobre toda la tabla escuelas, obtenemos las escuelas contenidas geográficamente en el distrito y sección del establecimiento y matcheamos en ese espacio. Subyace a esto la suposición de que en cada distrito los nombres y direcciones de las escuelas van a ser "suficientemente distintos" entre sí.

Hubo otro salto muy grande en la precisión, pero todavía no es perfecto. Y nunca lo va a ser.

Y qué hacemos?

Si llegaste hasta acá es porque te interesa el problema y quizás te interese colaborar. Si querés ver qué hice:

  • Importá el dump dondevoto.sql.bz2 a un Postgres + PostGIS
  • Hay una tabla weighted_matches: vincula establecimientos (lugares de votacion) con escuelas (puntos en el mapa), atribuído con un grado de certeza del match (retornado por difflib).
  • El script join_establecimientos_escuelas.py es el que construye esa tabla. Si cambiás el algoritmo que la construye, truncala antes de correrlo.

Es probable que la información con la que contamos hasta ahora contenga bastantes pistas con las que definir reglas o heurísticas que permitan mejorar la precisión del (rudimentario) matching que venimos haciendo hasta ahora. Hay establecimientos que nunca vamos a poder referenciar con la información disponible: por ejemplo, locales de votación que no son escuelas. No va a quedar otra más que trabajo manual, también son bienvenidas ideas sobre eso.

Visualizando los resultados

En el directorio webapp hay una aplicación web simple para visualizar los resultados del matching. Dentro de poco va a convertirse en una aplicación para crowdsourcear la validación de los resultados. Hay alrededor de 13000 locales de votación, no son tantos; si nos ponemos, los valdiamos en poco tiempo :)

Para correr la aplicación, instalar flask y ejecutar python webapp/dondevoto.py.

Tanto laburo para qué?

Contar con un mapa completo de locales de votación puede servir, en el futuro, para varias cosas. Una de ellas: visualización de resultados electorales a gran resolución (nivel circuito electoral).

Y por otro lado, por que sí.

Entonces, si tenés ganas de ver qué sale, contactame: @manuelaristaran en Twitter o a mi mail, que figura en jazzido.com