archivo

Python

Seguidores de la programación en PyQGIS conoceréis de sobra el blog de Jose Guerrero, en el que pone una gran cantidad de información sobre el tema de programación en QGIS muy bien explicada, si os interesa el tema totalmente obligatoria su visita.

En próximos post intentaré replicar alguno de sus post como son los de la creación de segmentos que unan las geometrías más cercanas. En gvSIG ahora mismo tengo que utilizar una librería que es jts, creo que directamente desde código no puedo calcular el punto más cercano desde un punto a una línea (refiriéndome a sacar con qué punto de esa línea hace el cálculo).

A falta de que pregunte, (que para eso son estas cosas para aprender, yo el primero), he utilizado la librería jts convirtiendo las geometrías de gvSIG y viceversa. De seguro que esta no es la mejor forma, pero por ahora nos valdrá. Lo veremos en los próximos post.

Ahora, un pequeño ejemplo de como sería utilizar esta librería. Aquí podéis ver su javadoc:

 


from gvsig import *
from geom import *

def gv2jts(geom1):
    import com.vividsolutions.jts as jts
    import com.vividsolutions.jts.io as io
    geomWKT = str(geom1.convertToWKT())
    wktReader = io.WKTReader
    wkt = wktReader()
    gI = wkt.read(geomWKT)
    return gI
    
def main(*args):

    line1 = createGeometry(2)
    line1.addVertex(createPoint(0, 0))
    line1.addVertex(createPoint(10,10))
    line1.addVertex(createPoint(20,10))

    line2 = createGeometry(2)
    line2.addVertex(createPoint(5,0))
    line2.addVertex(createPoint(5,2))
    line2.addVertex(createPoint(6,3))
    line2.addVertex(createPoint(10,0))
    print line1, line2
    print type(gv2jts(line1))

    print line1.convertToWKT()
    print line2.convertToWKT()

    l1 = gv2jts(line1)
    l2 = gv2jts(line2)

    import com.vividsolutions.jts.operation.distance.DistanceOp as DistanceOp
    d = DistanceOp(l1, l2)
    nearestPoints = d.nearestPoints()
    print nearestPoints
    print "Punto de geom 1: ", nearestPoints[0]
    print "Punto de geom 2: ", nearestPoints[1]
    pass

saliendo por consola:

Running script test_jts_nearest.
Curve2D Curve2D
<type 'com.vividsolutions.jts.geom.LineString'>
LINESTRING (0 0, 10 10, 20 10)
LINESTRING (5 0, 5 2, 6 3, 10 0)
array(com.vividsolutions.jts.geom.Coordinate, [(3.5, 3.5, NaN), (5.0, 2.0, NaN)])
Punto de geom 1:  (3.5, 3.5, NaN)
Punto de geom 2:  (5.0, 2.0, NaN)
Script test_jts_nearest terminated.

Tanto como ponente como asistente. El 20 de Noviembre en la PyConEs tendré un Taller sobre Python en gvSIG que daré junto a Joaquin del Cerror, desarrollador principal de gvSIG, y asistiré el resto de días al resto de conferencias. He visto algunas muy interesantes sobre tratamiento de datos e incluyendo la que viene de parte de Geoinquietos Valencia (@geoinquietosvlc) sobre Fiona y Shapely.

Cualquiera que vaya que avise por aquí y será un placer conoceros en persona.

¡Allí nos vemos!

Para abrir boca, un vídeo que cada vez que lo veo aprendo algo nuevo. Totalmente recomendado:

Cuarenta características de Python que quizás no conoces (PyConES 2013)

Siguiendo el post de ayer sobre Subir capas a CartoDB mediante Python, ahora vamos a ver cómo podemos realizar peticiones de información a estas capas.

Lo más complicado es tener la instalación completada tal y como explico en el post anterior. Si llegaste a ejecutar el código de subir un fichero a CartoDB, no debería de aparecer ningún nuevo error al ejecutar estas peticiones.

Para realizar este código nos hemos basado en la información que aparece sobre la SQL API y sobre la librería cartodb-python.

La peticiones SQL que hacemos es muy sencilla, le pedimos a la base de datos que nos devuelva los datos de: osm_id y name, que corresponden a las 5 primeras ciudades ordenadas por osm_id.

from cartodb import CartoDBAPIKey, CartoDBException, FileImport

API_KEY ='apikey'
cartodb_domain = 'cuenta'
cl = CartoDBAPIKey(API_KEY, cartodb_domain)

#Peticion SQL
petition = ('SELECT osm_id, name FROM cities_europe_shp ORDER BY osm_id LIMIT 5;')
catch = (cl.sql(petition))
for f in catch['rows']:
    print f

Ocurre que no todas las ciudades tienen un nombre válido, aparecen algunas con nombre ‘???’.

{u'name': u'Gala?i', u'osm_id': u'100035698'}
{u'name': u'Leicester', u'osm_id': u'10021976'}
{u'name': u'???', u'osm_id': u'100890898'}
{u'name': u'???????', u'osm_id': u'101480194'}
{u'name': u'Lincoln', u'osm_id': u'10671639'}

Así que para limpiar datos vamos a ejecutar un código SQL que genere una nueva columna donde indique si el nombre de la ciudad contiene un’?’ o no.

Primero añadimos una columna nueva a nuestra tabla:

#Agregar columna
petition = ('ALTER TABLE cities_europe_shp ADD valid_name2 BOOLEAN;')
catch = (cl.sql(petition))

Antes de nada vamos a comprobar cuantos  nombre contienen alguna ‘?’:

petition = ("""
SELECT count(*)
FROM cities_europe_shp
WHERE name
LIKE '%?%';
""")
catch = (cl.sql(petition))
for f in catch['rows']:
    print f

Vemos que muestra que hay más de quinientos nombres incompletos:

{u'count': 564}

Esto puede ocurrir porque no nos preocupamos de esto al hacer la importación, y hay caracteres no soportados.

Ahora, le damos valor a la nueva columna según el campo name: si no contiene ningún carácter ‘?’, se le asignará el valor de True.

#Actualizar columna
petition = ("""
UPDATE cities_europe_shp
SET valid_name=True
WHERE name
NOT LIKE '%?%';
""")
catch = (cl.sql(petition))
for f in catch['rows']:
    print f

Si vemos nuestro dataset en CartoDB veremos, algo por el estilo a esto, apareciendo True en la columna nueva creada:

2015-11-11 21_00_45-cities_europe_shp _ CartoDB

Comprobamos que ahora podemos hacer la petición inicial pero solo con los nombres que sean válidos para nosotros:

#Peticion SQL sin ?
petition = ('SELECT osm_id, name FROM cities_europe_shp WHERE valid_name=True ORDER BY osm_id LIMIT 5;')
catch = (cl.sql(petition))
for f in catch['rows']:
    print f

Y vemos que los que muestra es algo más parecido a lo que buscábamos:

{u'name': u'Leicester', u'osm_id': u'10021976'}
{u'name': u'Lincoln', u'osm_id': u'10671639'}
{u'name': u'London', u'osm_id': u'107775'}
{u'name': u'Marbella', u'osm_id': u'1081751552'}
{u'name': u'Guarda', u'osm_id': u'1084227094'}

Por supuesto, esta petición la podemos realizar directamente sin crear un campo nuevo quedando así:

petition = ("SELECT osm_id, name FROM cities_europe_shp WHERE name NOT LIKE '%?%' ORDER BY osm_id LIMIT 5;")

Con esto estamos actualizando, modificando y consultando directamente nuestros datos desde código. Y al ser desde código, con esto puedes crear procesos fácilmente automatizados.

Este es el código completo:

from cartodb import CartoDBAPIKey, CartoDBException, FileImport

API_KEY ='apikey'
cartodb_domain = 'cuenta'
cl = CartoDBAPIKey(API_KEY, cartodb_domain)

#Peticion SQL
petition = ('SELECT osm_id, name FROM cities_europe_shp ORDER BY osm_id LIMIT 5;')
catch = (cl.sql(petition))
for f in catch['rows']:
   print f

#Agregar columna
#petition = ('ALTER TABLE cities_europe_shp ADD valid_name2 BOOLEAN;')
#catch = (cl.sql(petition))

#Seleccionar columnas que cumplen el nombre con ?
petition = ("""
SELECT count(*)
FROM cities_europe_shp
WHERE name
LIKE '%?%';
""")
catch = (cl.sql(petition))
for f in catch['rows']:
   print f

#Actualizar columna
petition = ("""
UPDATE cities_europe_shp
SET valid_name=True
WHERE name
NOT LIKE '%?%';
""")
catch = (cl.sql(petition))
for f in catch['rows']:
   print f

#Peticion SQL sin ?
petition = ("SELECT osm_id, name FROM cities_europe_shp WHERE name NOT LIKE '%?%' ORDER BY osm_id LIMIT 5;")
catch = (cl.sql(petition))
for f in catch['rows']:
   print f

Y se me olvidaba ya, también podemos por supuesto añadir nuevas entidades a nuestra capa, el código sql sería similar al siguiente:

#Insert info
rows = [
    "(CDB_LatLng(10, 10), 'Ciudad 1',
    "(CDB_LatLng(20, 12), 'Ciudad 2'",
    "(CDB_LatLng(30, 14), 'Ciudad 3'"
]

petition = "INSERT INTO cities_europe_shp (the_geom, name) (VALUES %s)%s" % (','.join(rows),';')
catch = (cl.sql(petition))

Este código ha sido sacado del siguiente post en gis.stackexchange.

Vamos a ejecutar ahora código SQL directamente desde la visualización de CartoDB. Para ello abrimos nuestro dataset y nos vamos a: Map View. A la derecha veremos un botón donde aparece: ‘SQL’.

2015-11-11 21_07_22-cities_europe_shp _ CartoDB

Lo interesante de esta petición SQL es que maneja los datos que se mostraran en la visualización. Al aplicar el QUERY, vemos como gran parte de las ciudades rusas desaparecen. Esto confirma la sospecha de que ha sido al convertir los caracteres el alfabeto ruso.

(Se poco sobre codificación, si alguien está interesado en aportar documentación donde se pudiera realizar esta importación desde OSM hasta fichero de texto, manteniendo correctamente todos los caracteres, seré el primero encantado de oirlo).

2015-11-11 21_19_18-cities_europe_shp _ CartoDB2015-11-11 21_16_42-cities_europe_shp _ CartoDB

Así pues, con esto también hemos aprendido a modificar nuestra visualización con una petición SQL. Probablemente saque otro post dedicado en exclusiva a esta visualización mediante SQL.

Más post próximamente, y no olvidéis de comunicarme por comentarios o Twitter los temas en los que más estéis interesados.

 

 

 

 

La plataforma de CartoDB es por muchos conocida, y se está situando como referente en la visualización de datos geográficos. Ya realicé hace casi dos años un post sobre ejemplos de esta plataforma, donde además se incluía una charla-taller organizada por Geospatial Training, realizada por Alejandro Martínez, ingeniero en CartoDB.

Si no conocíais esta plataforma podéis entrar se web para descubrir ejemplos de uso o para aprender mediante tutoriales a usar la plataforma (muy interesantes estos tutoriales, no se limitan a lo básico). Justo acabo de ver que incluyen un apartado “The Map Academy” donde incluyen minicursos sobre CartoDB, desconozco como serán pero seguro que os pueden interesar.

Al grano, vamos a explicar rápidamente como subir archivos a tu cuenta de CartoDB desde código Python.

Para ello lo primero que vamos a necesitar es (para los que no lo tengáis ya) una cuenta en CartoDB, y registraros es completamente gratuito. No penséis que por ser gratuito estarán muy limitadas sus opciones, para nada.

Una vez hecho esto, ya podemos entrar a la web con nuestro login, hasta entrar a la web que tiene una pinta similar a esta:

2015-11-10 21_01_16-CartoDB · oscar9

Aquí nos saldrán las últimas modificaciones que hemos hecho sobre nuestros datos, la visualización que aparece será una hecha por vosotros.

Para acceder a nuestra cuenta desde código necesitaremos una API Key. Tendremos que ir al icono de arriba a la derecha y al hacer el click nos aparecerá un desplegable con la opción “Your API Key”.

Os aparecerá una página como esta, donde podréis copiar vuestra Key y ver dos ejemplos de uso de esta Key para usarla con peticiones mediante http.

2015-11-10 21_09_07-Your API keys _ CartoDB

Cuidado, esta Api key da acceso a vuestra cuenta de forma completa, esto lo digo tanto para que no la compartáis como para que tengáis cuidado con vosotros mismos, si tenéis información importante y ejecutáis algún código SQL que no fuera correcto, podríais modificar tablas que necesitéis o llegar a borrar vuestras bases de datos. Si estáis usando CartoDB de manera profesional, recomiendo que os creéis otra cuenta diferente para hacer pruebas.

Para acceder desde Python a vuestra cuenta tendréis que bajaros la siguiente librería: cartodb-python 

Esta os permitirá acceder a vuestras bases de datos en la plataforma y, como en este caso, a subir ficheros nuevos. Para más información sobre la SQL API de CartoDB en su web, explican esto y muchos más, partes que también explicaremos en próximos post.

En Github, a la derecha, aparece el botón de descargar zip. La carpeta os la descargáis y la descomprimís en C:// por ejemplo. Ahora desde terminal accedéis a ella.

Anotación rápida para moveros por la consola: podéis escribir “cd ..” para bajar ruta hasta C://, y luego podéis escribir “cd cart” y apretar TAB hasta que salga el nombre de cartodb-python-master, nombre del fichero que habéis descomprimido. Con “dir“, aparecen los ficheros de la carpeta.

Ahora, en esta carpeta, podéis ejecutar:

python setup.py install

2015-11-10 21_42_49-Administrador_ Símbolo del sistema

 

Si escribimos en la terminal: python accedemos a la consola de python en la que podemos internar importar la librería con un:

import cartodb

Para hacer este post lo estoy haciendo en otra máquina y me ha aparecido que me falta una librería, así que vamos a instalarla. Volvemos a la terminal pulsando “Control + D“. Y en mi caso parece que todo se soluciona con un:

pip install requests_oauthlib

2015-11-10 21_51_12-Administrador_ Símbolo del sistema - python

Si no os funciona lo anterior, hay que comprobar que tenemos instaladas las siguientes librerías. Es posible que ya tengáis algunas, ir comprobando la consola por si os aparece algún error sobre la falta de estas al ejecutar el código, similar al que me aparecía arriba. Creo que todas las que necesitáis son las siguientes.

En principio podéis instalarlas siempre escribiendo en la terminal mediante:

pip install nombre-libreria

Si esto no os funciona por lo que sea, podéis descargarlas manualmente y copiarlas a la carpeta de instalación de lib dentro de C://Python27// o cual sea la distribución que uséis.

Si seguís el post que expliqué sobre Instalación de Python con Anaconda, la carpeta será C://Anaconda//Lib y también podréis instalar las librerías directamente desde la terminal con:

conda install nombre-libreria

Ejemplo de descargarlas de forma manual.

2015-11-10 21_53_54-httplib2-0.9.1.zip - WinRAR (copia de evaluación)

Copiaríamos solo a la carpeta lib de python, la carpeta señalada que contiene exactamente el nombre de la librería

Estoy utilizando la IDE de Python denominada Rodeo, la cual instalé en el post anterior junto a Anaconda. De todas formas este código lo podéis ejecutar también desde la terminal que hemos estado usando o cualquier otra IDE de Python.

Para probar podemos empezar con un código sencillo, solo para ver que realmente nos coge bien la librería de CartoDB.

2015-11-10 22_00_33-Rodeo

Como paso final, vamos a crear una conexión a nuestra cuenta con la API Key que tenemos y el nombre de nuestra cuenta, permitiéndonos subir un shape directamente (comprimido en un zip). El zip que utilizamos es el que usamos de ejemplo en anteriores post, descargado desde OSM y trasnformado a shape con ogr2ogr, que podéis descargar de aquí en Github.

El código, solo tendréis que cambiar vuestra apikey, cuenta, y la ruta del zip que contenga los 4 ficheros necesarios para un shape: .shp, .prj, .dbf, .shx. También podríais, por ejemplo, subir un fichero csv e indicar en cartodb, una vez ya subido, cuales coordenadas corresponden a X e Y. En la web de la librería CartoDB-Python, explica el siguiente código y el uso que le podemos dar.

from cartodb import CartoDBAPIKey, CartoDBException, FileImport

API_KEY ='miapikey'
cartodb_domain = 'micuenta'
cl = CartoDBAPIKey(API_KEY, cartodb_domain)

#Import shape
fi = FileImport("C:/temp/shp/cities_europe_shp.zip", cl)
fi.run()

Revisando estas fuentes, he comprobado que también permite la subida de datos directamente desde un enlace web con el siguiente código:

from cartodb import URLImport

fi = URLImport("http://acdmy.org/d/counties.zip", cl)
fi.run()

Si tenemos la web de cartodb nos aparecerá una pestaña abajo a la izquierda así, indicando que se está subiendo un nuevo dataset:

2015-11-10 22_15_02-oscar9 _ CartoDB

¡Y listo! si comprobáis vuestros dataset, ya veréis que aparece la visualización del nuevo shape:

2015-11-10 22_18_32-cities_europe_shp _ CartoDB

Próximamente otro post sobre cómo hacer peticiones SQL sobre esta base de datos que acabamos de subir, fácil si ya hemos completado hasta aquí en este post.

Si estáis interesados particularmente en algo ponerlo en los comentarios y podrá ser temas de próximos post.

 

 

Después de instalar la distribución de Anaconda, explicada en el anterior post, ya podemos acceder también a los notebook de IPython, ahora denominado Jupyter.

El Jupyter Notebook es un entorno interactivo web de ejecución de código en los que, por ejemplo, puedes incluir gráficas que ayuden en el análisis e explicación de tus datos. Utilizados para facilitar la explicación y reproducción de estudios y análisis.

Para trabajar con ellos se realiza directamente desde el navegador. Estos notebook se pueden almacenar e intercambiar o mostrar en páginas web.

Mucha más información y mejor explicada en la documentación de su página web Jupyter.org.

Si instalamos Anaconda este paquete ya viene instalado por defecto en la distribución, si utilizamos la versión estándar tendremos que instalarla.

Si ya tenías una versión antigua de IPython con Anaconda, podemos actualizar estas versiones ejecutando en el terminal:

conda update conda

2015-11-07 19_49_07-conda_1

Apareciendo algo similar a lo siguiente cuando encuentra actualizaciones de librerías y nos pregunta si actualizar:

2015-11-07 19_50_03-conda_2

Una vez actualizado, podremos abrir Jupyter escribiendo en el terminal:

ipython notebook

Se nos abrirá una ventana en el navegador automáticamente quedando así:

2015-11-07 19_51_40-conda_3

Ahora ya podemos crear nuestro Notebook. A la derecha elegimos Python Notebook:

2015-11-07 19_53_33-conda_4

 

Y por fin ya tendremos en nuestro navegador nuestro Notebook abierto, el que poder trabajar y salvar progresos. Con la tecla Intro normal podremos escribir varias líneas, con el Control+Intro ejecutaremos esas líneas. Con Alt+Intro, pasaremos a un nuevo bloque. El orden en el que se ejecutan las líneas influye en los resultados. Se puede ejecutar todo de nuevo dando click arriba en Cell – Run All. De esta forma todos los cálculos de reiniciarán. Esto permite de una forma muy cómoda hacer modificaciones en los datos iniciales y ejecutar de nuevo todo el proceso.

Un ejemplo rápido sobre un Notebook puede ser este:

2015-11-07 20_05_08-conda_5

Podéis ver en este notebook gran cantidad de estilos sobre gráficas. Si buscáis más ejemplos solo tenéis que buscar Ipython Notebook en Google.

Para seguir el próximo ejemplo (web muy completa) tuve que ejecutar en terminal:

conda install basemap

Código:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
 
# make sure the value of resolution is a lowercase L,
#  for 'low', not a numeral 1
my_map = Basemap(projection='ortho', lat_0=50, lon_0=-100,
              resolution='l', area_thresh=1000.0)
 
my_map.drawcoastlines()
my_map.drawcountries()
my_map.fillcontinents(color='coral')
my_map.drawmapboundary()
 
my_map.drawmeridians(np.arange(0, 360, 30))
my_map.drawparallels(np.arange(-90, 90, 30))
 
plt.show()

2015-11-07 20_16_47-conda_5

Esto es todo por ahora, no suelo utilizar estos notebooks pero me sorprende lo increíblemente sencillo que es de utilizar y de mostrar resultados tan sorprendentes. También puede ser útil para iniciados en la materia.

¡Próximamente más!

 

Si necesitas Python para análisis de datos recomiendo la distribución de Anaconda. Es una instalación de Python ya preparada con las principales librerías que se usan instaladas, incluye numpy, scipy, etc y la instalación de IPython (ahora llamado Jupyter Notebook). Si queréis enteraros aprender más sobre el por qué de las ventajas de esta distribución, ellos lo explican mucho mejor. En Twitter, Continuum Analytics.

Anaconda lo podemos descargar para varias versiones de Python y diferentes sistemas operativos. Con descargar y ejecutar el .exe, ya se encargará el setup de todo. Nos aparecerá instalado en: C:/Anaconda y añadirá la ruta de Anaconda al Path de Windows.

Que esté todo lo necesario para que funcione Jupyter Notebook es requisito para que funcione el IDE de Rodeo. Este entorno intenta simular el IDE de RStudio. Dispone de cuatro divisiones en la pantalla: el sistema de archivos, los scripts que tengamos, el valor de las variables de los scripts y la consola. Además nos permitirá dibujar gráficas. Podéis ver más información del proyecto en el repositorio de Github – Rodeo.

Una vez abierto Rodeo, tendremos que ir en la ventana inferior derecha a Preferencias. En el apartado Default Python Command introducir: C:/Anaconda/python.exe Si utilizáis una versión estándar de Python donde ya tenéis todo lo necesario instalado, la ruta será similar a C:/Python27/python.exe

La librería que utilizaremos para dibujar gráficas es matplotlib. Podéis ver en su documentación gran cantidad de información para realizar estas gráficas. De ejemplo, una muy sencilla, con matplotlib.pyplot.plot(*args, **kwargs):

import matplotlib as mpl
import numpy as np

# Funcion valores aleatorios
# Devuelve 100 pares de valores, entre 0 y 1
x, y = np.random.rand(2, 100)

# Mostramos la grafica
mpl.pyplot.plot(x, y, 'go')

Y este es el aspecto que tiene:

2015-11-06 20_54_13-Rodeo

 

El argumento ‘go’ indica que la gráfica se dibuje en formato de coordenadas.

Cualquier fallo en la explicación o confusión de conceptos, soy todo oídos :)