En esta entrada del blog vamos a ver un ejemplo de extracción de información de un fichero en formato shapefile y de exportación de esa información a Excel utilizando las herramientas que nos ofrece Python y QGIS. Vamos a utilizar por ejemplo una capa con todos los aeropuertos del mundo, la cual podemos descargar de la página de Natural Earth.
El código lo desarrollaremos directamente en la consola de Python que ofrece QGIS, accediendo a ella con el comando Ctrl + Alt + P y haciendo click en el símbolo que os señalo a continuación.
Generamos un nuevo fichero .py para nuestro código. Lo primero es importar las librerías que vamos a utilizar. En este caso importaremos la librería de pandas, la cual usaremos más adelante. Lo primero es definir la ruta donde hemos almacenado el fichero shapefile, denominado “ne_10m_airports.shp”, con el objetivo de instanciar nuestra capa con la clase QgsVectorLayer.
/** import pandas as pd from pathlib import Path basepath = Path().home().joinpath("Documents","entradas") filePath = basepath.joinpath("ne_10m_airports.shp") shpLayer = QgsVectorLayer(filePath.as_posix(), 'Aeropuertos mundo', 'ogr') */
El siguiente paso es conocer cuáles son los campos que tiene la capa para ver cuáles nos interesan. Esto se puede hacer simplemente con los métodos .fields() y .names() de la clase QgsFields.
/** campos = shpLayer.fields().names() print (campos) */
Como resultado vemos en la consola el nombre de los campos, entre los que se encuentra el nombre del aeropuerto en varios idiomas (inglés, español, chino, italiano, japonés, etc), o su influencia. Los campos que vamos a elegir van a ser ‘name_es’ (nombre en español) y ‘iata_code’ (nombre del aeropuerto codificado).
El objetivo es iterar estos campos para extraer los atributos, almacenarlos en un array, y exportarlos a un fichero Excel. Lo primero que podemos hacer es crear el fichero *.xls donde vamos a guardar la información. Para ello vamos a utilizar la clase de pandas pd.ExcelWriter. Guardamos el fichero en la carpeta donde estamos trabajando. En este caso le damos el nombre de “lista_aeropuertos.xls”.
/** fichero = pd.ExcelWriter(basepath.joinpath("lista_aeropuertos.xls").as_posix()) */
Posteriormente, creamos dos arrays vacíos en los que almacenaremos el resultado de la iteración.
/** nombre = [] iata = [] */
Accederemos a las entidades con el método .getFeatures() de la clase QgsVectorLayer e iteramos para añadir a los arrays cada una de las entidades de ambos campos.
/** for f in shpLayer.getFeatures(): nombre.append(f['name_es']) iata.append(f['iata_code']) */
Con estos arrays creamos un DataFrame con pd.DataFrame() y lo exportamos a nuestro Excel con el método .to_excel(). Guardamos nuestro fichero y lo cerramos.
/** df = pd.DataFrame({'Nombre aeropuerto': nombre, 'Iata' : iata}) df.to_excel(fichero, index = False) fichero.save() fichero.close() */
Si abrimos el fichero tenemos una primera columna denominada “Nombre aeropuerto” con los nombres en castellano y otra columna de “Iata” con los nombres codificados de los aeropuertos.
Si nos fijamos en la columna con los nombres nos daremos cuenta de que hay muchas entidades con valores NULL, puesto que el nombre de ese aeropuerto no se ha traducido. Una solución para no dejar estos valores nulos es asignarles el valor del campo que contiene el nombre del aeropuerto en inglés. Para ello, en nuestro bloque condicional, aplicamos lo siguiente.
/** for f in shpLayer.getFeatures(): if (f['name_es']) == '' or not f['name_es']: nombre.append(f['name']) else: nombre.append(f['name_es']) iata.append(f['iata_code']) */
De esta manera, especificamos que en aquellas entidades donde haya valor nulo en el campo ‘name_es’ se utilice el valor del campo ‘name’.
De nuestro fichero vamos a extraer también las coordenadas X e Y de cada aeropuerto. Como no disponemos de un campo donde vengan especificadas vamos a extraerlas mediante la geometría de los puntos utilizando .geometry().asPoint(). Para extraer la coordenada X basta con añadir al final de la sentencia .x(), al igual que para extraer la coordenada Y hay que especificar .y(). Estas coordenadas las añadimos a 2 arrays vacíos que hemos creado junto con los arrays de nombre y iata.
/** coordenada_x = [] coordenada_y = [] */
Añadimos unas sentencias dentro de nuestro bucle para calcular las coordenadas de las entidades y añadirlas a los arrays.
/** for f in shpLayer.getFeatures(): if (f['name_es']) == '' or not f['name_es']: nombre.append(f['name']) else: nombre.append(f['name_es']) iata.append(f['iata_code']) coordX = f.geometry().asPoint().x() coordenada_x.append(coordX) coordY = f.geometry().asPoint().y() coordenada_y.append(coordY) */
Para saber el sistema de coordenadas que está utilizando el fichero shapefile podemos utilizar el método .sourceCrs(), añadiéndole al final el método .authid() para mostrar el ID del sistema de coordenadas. Si imprimimos vemos en la pantalla de la consola que el sistema de coordenadas es el EPSG:4326, correspondiente al WGS 84.
/** sist_coord = shpLayer.sourceCrs().authid() print (sist_coord) */
Por último, añadimos los arrays con las coordenadas al DataFrame.
df = pd.DataFrame({‘Nombre aeropuerto’: nombre, ‘Iata’ : iata,
‘Coordenada X’ : coordenada_x, ‘Coordenada Y’ : coordenada_y})
Como resultado tendremos automáticamente todos los nombres de los aeropuertos, su codificación y sus coordenadas dentro de nuestro fichero Excel.
El código completo del ejercicio es el siguiente.
/** import pandas as pd from pathlib import Path basepath = Path().home().joinpath("Documents","entradas") filePath = basepath.joinpath("ne_10m_airports.shp") shpLayer = QgsVectorLayer(filePath.as_posix(), 'Aeropuertos mundo', 'ogr') campos = shpLayer.fields().names() print (campos) sist_coord = shpLayer.sourceCrs().authid() print (sist_coord) fichero = pd.ExcelWriter(basepath.joinpath("lista_aeropuertos.xls").as_posix()) nombre = [] iata = [] coordenada_x = [] coordenada_y = [] for f in shpLayer.getFeatures(): if (f['name_es']) == '' or not f['name_es']: nombre.append(f['name']) else: nombre.append(f['name_es']) iata.append(f['iata_code']) coordX = f.geometry().asPoint().x() coordenada_x.append(coordX) coordY = f.geometry().asPoint().y() coordenada_y.append(coordY) df = pd.DataFrame({'Nombre aeropuerto': nombre, 'Iata’ : iata, 'Coordenada X' : coordenada_x, 'Coordenada Y' : coordenada_y})*/
–
El curso de Python en QGIS dotará a los alumnos de los conocimientos necesarios para afrontar con seguridad la programación de scripts, plugins y la automatización de procesos en QGIS 3. Mediante la adquisición de una base sólida de Python 3 se capacitará al alumno en el tratamiento de datos vectoriales y ráster en QGIS y la automatización de procesos creando plugins y scripts.
Deja tu comentario