Geoinformática - Práctica 2

Geovisualización

Cartografía en Python con GeoPandas

In [1]:
%matplotlib inline

import matplotlib.pyplot as plt
import geopandas as gpd
import pysal as ps
import palettable as pltt
from seaborn import palplot
/home/datalab/miniconda3/envs/geoinf/lib/python3.7/site-packages/pysal/explore/segregation/network/network.py:16: UserWarning: You need pandana and urbanaccess to work with segregation's network module
You can install them with  `pip install urbanaccess pandana` or `conda install -c udst pandana urbanaccess`
  "You need pandana and urbanaccess to work with segregation's network module\n"
/home/datalab/miniconda3/envs/geoinf/lib/python3.7/site-packages/pysal/model/spvcm/abstracts.py:10: UserWarning: The `dill` module is required to use the sqlite backend fully.
  from .sqlite import head_to_sql, start_sql

En esta práctica, se aprenderá como importar, manipular y visualizar datos espaciales. Hasta cierto punto, los datos espaciales han sido tan propagados que existen casos en los que únicamente se consideran como "una columna más" dentro de una tabla; sin embargo, existen múltiples características que distinguen enormemente a los datos geográficos de las tablas numéricas comúnes.

En esta sesión, se pretende continuar avanzando sobre las habilidades desarolladas en la práctica de Transformación de Datos, para combinarlas y, en el proceso, descubrir que, salvo algunas particularidades, tratar con datos espaciales en Python se asemeja mucho al manejo de datos no espaciales.

Para esto, se utilizarán los datos derivados del Censo de Población y Vivienda 2010 de INEGI, así como la geografía utilizada para su construcción, lo cual puede ser consultado a través de este link, y descargado por este otro.

En primer lugar, como se hizo en la primera práctica, y por cuestiones de conveniencia, se definirá una variable de tipo string donde se almacene la ubicación de los datos de trabajo:

In [2]:
# Recuerda que podría ser diferente en tu caso, dependiendo de en dónde almacenes los datos
f = 'data/'

Importando Datos Espaciales

La forma más fácil y rápida de importar datos espaciales es a través de un objeto del tipo GeoDataFrame, que tiene la capacidad de interpretar cuáles son las columnas donde se almacena la componente espacial, ausente en un DataFrame convencional; además, se puede visualizar rápidamente a través del comando .plot().

La librería principal utilizada para el manejo de datos espaciales recibe el nombre de geopandas, la cual es una extensión geoespacial de la librería pandas con la que se ha trabajado hasta ahora. geopandas ofrece exactamente la misma funcionalidad de pandas, debido a que la primera fue construída a partir de la segunda, añadiendo un conjunto de funciones de caracter espacial que permiten que la manipulación y transformación de los datos espaciales sea tan sencilla como con los datos no espaciales.

En sólo dos líneas de código es posible obtener una representación gráfica de los datos espaciales contenidos en un archivo, siendo posible manejar una gran variedad de formatos; de hecho, debido a que ambos manejan el mismo tipo de drivers, la gran mayoría de los archivos vectoriales que son aceptados en QGIS pueden ser aceptados por geopandas. Se comenzará graficando una capa a la vez de forma tosca pero veloz, para poco a poco agregar estilo y sofisticación.

Polígonos

Comenzando por uno de los tipos de datos espaciales más comunes, Polígonos, se importará la geografía de todas las AGEB's que conforman la Ciudad de México, a través de la funcion .read_file() de geopandas; asimismo, se utilizará el método .set_index() para determinar su Clave Geográfica (CVEGEO) como el índice de cada fila:

In [3]:
agebs = gpd.read_file(f + 'agebs_cdmx.geojson')  # Importar los datos espaciales
agebs = agebs.set_index('ageb_urbana_cvegeo')    # Seleccionar su Clave Geográfica como el índice de las filas

La variable agebs contiene un objeto del tipo GeoDataFrame, el cual es muy similar a los DataFrame manejados en la práctica anterior, pero con una nueva columna llamada geometry:

In [4]:
agebs.head()
Out[4]:
geometry
ageb_urbana_cvegeo
0900700013628 (POLYGON ((-99.03887376191602 19.3912779889989...
0900300011533 (POLYGON ((-99.18009578508389 19.3077165167440...
0901500010235 (POLYGON ((-99.14494638586424 19.4562541831128...
0900200010097 (POLYGON ((-99.20573230218446 19.5045424604436...
0900200011184 (POLYGON ((-99.20722847036538 19.5038667281062...

Como tal, es posible graficar rápidamente este GeoDataFrame a través de la instrucción .plot():

In [5]:
agebs.plot(figsize = (10,10))
Out[5]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f08c4921e10>

Aunque no se trata de la visualización estética de las AGEB's, si permite visualizar rápidamente la apariencia de éstas; más adelante se aprenderá cómo mejorar la apariencia visual y personalizar estas representaciones.

¡Importante Si se utiliza la función .loc() aprendida en la práctica anterior para llamar una sola fila y su columna geometry, de forma automática se obtendrá una pequeña gráfica del shape en cuestión; debido a que el índice es la Clave Geográfica, éste puede ser utilizado para encontrar el AGEB deseado:

In [6]:
agebs.loc['0901200010337', 'geometry']
Out[6]:

Líneas

Visualizar líneas es tan sencillo y directo como lo es con los polígonos. En este caso, se importarán todas las vialidades de la Alcaldía Cuauhtémoc:

In [7]:
vias = gpd.read_file(f + 'vias_cuauhtemoc.geojson') # Se importan los datos espaciales
vias = vias.set_index('id')                         # Se establece una columna como índice
vias.head()                                         # Visualizar los primeros registros de la fila
Out[7]:
geometry
id
1 LINESTRING (-99.1704148 19.4009206, -99.170470...
2 LINESTRING (-99.1784986 19.4071955, -99.178681...
3 LINESTRING (-99.1490507 19.4379558, -99.148707...
4 LINESTRING (-99.1473476 19.4453084, -99.147175...
5 LINESTRING (-99.17655379999999 19.4210494, -99...

Al igual que con los polígonos, es posible utilizar la función .plot() para graficar las líneas rápidamente:

In [8]:
vias.plot(figsize = (10,10))
Out[8]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f08c470d828>

Y de igual forma, puede obtenerse una sola línea a través la función .loc(), su índice y la columna geometry:

In [9]:
vias.loc[9079, 'geometry']
Out[9]:

Al igual que con los polígonos, ésta no es la mejor visualización de las líneas, y probablemente se buscará cambiar algunos parámetros como colores, ancho, entre otros; sin embargo, es la forma más veloz en la que puede visualizarse la apariencia de los datos espaciales.

Puntos

Nuevamente, los puntos siguen una estructura similar; en este caso, se trabajarán con las Estaciones del Metro de la Ciudad de México:

In [10]:
estaciones = gpd.read_file(f + 'estaciones_metro.shp')
estaciones.head()
Out[10]:
stop_lat stop_lon geopoint agency_id stop_id stop_desc stop_name trip_heads geometry
0 19.443082 -99.139034 (2:19.443082,-99.139034) METRO 14169.0 Metro Línea 8 correspondencia con línea B. Garibaldi_1 Garibaldi - Constitución de 1917 POINT (485405.8425224103 2149860.572109856)
1 19.468965 -99.136176 (2:19.468965,-99.13617600000001) METRO 14103.0 Metro Línea 5 correspondencia con línea 3. La Raza_1_3 Pantitlán - Politécnico POINT (485708.1095785024 2152724.377907486)
2 19.376256 -99.187746 (2:19.37625563,-99.18774605) METRO 14079.0 Metro Línea 7 correspondencia con línea 12. Mixcoac_1 Tláhuac - Mixcoac POINT (480284.5584925968 2142470.87422094)
3 19.408944 -99.122279 (2:19.40894369,-99.12227869) METRO 14144.0 Metro Línea 9 correspondencia con línea 4. Jamaica Tacubaya - Pantitlán POINT (487161.9392610416 2146081.72623959)
4 19.375679 -99.186866 (2:19.37567873,-99.18686628) METRO 132131.0 Metro Línea 12 correspondencia con línea 7. Mixcoac Mixcoac - Tláhuac POINT (480376.8753979359 2142406.938427646)

Y la visualización se produce de forma idéntica a los casos anteriores:

In [11]:
estaciones.plot(figsize = (10,10))
Out[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f08c06b3860>

Estilizando Gráficas

Es posible trabajar con múltiples características de una gráfica para personalizarla y que cumpla con necesidades específicas. En esta sección, se explorarán algunos de estos elementos básicos que permiten obtener mapas mejor representados y más fáciles de comprender.

Cambio de Transpariencia

La intensidad del color de un polígono puede ser cambiado sencillamente a través del argumento alpha de la función .plot(); éste se especifica a través de un valor entre cero y uno, donde el 0 representa transparencia completa y el 1 completa opacidad (máxima intensidad):

In [12]:
agebs.plot(alpha = 0.5 , figsize = (10,10))
Out[12]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f08c0614eb8>