Geospatial Python Toolbox
Tu arsenal completo de herramientas para análisis geoespacial con Python
Este capítulo presenta las bibliotecas Python esenciales para el análisis geoespacial. Desde la lectura de archivos shapefile hasta el procesamiento de imágenes satelitales, Python ofrece un ecosistema completo de herramientas que te permiten conquistar cualquier desafío en el campo geoespacial.
Exploraremos soluciones pure Python siempre que sea posible, y cuando la eficiencia lo requiera, utilizaremos bindings a bibliotecas de alto rendimiento escritas en C/C++. La portabilidad de Python lo convierte en la herramienta ideal para cualquier analista geoespacial.
Instalación de Módulos
Antes de comenzar a trabajar con herramientas geoespaciales, necesitas configurar tu entorno Python correctamente. Existen varias formas de instalar módulos de terceros en Python.
Requisitos Técnicos
pip install
# Instalación básica con pip pip install shapefile pip install numpy pip install gdal # Para PIL en Python 3, usa Pillow pip install Pillow # Instalar desde GitHub pip install https://github.com/GeospatialPython/dbfpy3/archive/master.zip
Conda Environment
Conda facilita la instalación de bibliotecas geoespaciales complejas con múltiples dependencias:
# Crear entorno virtual con Conda conda create -n geospatial python=3.9 conda activate geospatial # Instalar bibliotecas geoespaciales conda install -c conda-forge gdal conda install -c conda-forge geopandas conda install -c conda-forge osmnx
osmnx que tienen docenas de dependencias complejas. Simplifica enormemente el proceso de instalación.
Adquisición de Datos
Python proporciona bibliotecas robustas para descargar datos geoespaciales de internet. Las dos principales son urllib (biblioteca estándar) y requests (terceros).
urllib Module
import urllib.request # URL de un archivo shapefile comprimido url = "https://github.com/GeospatialPython/Learn/raw/master/point.zip" # Descargar el archivo urllib.request.urlretrieve(url, "point.zip") print("Descarga completada!")
requests Module
import requests url = "https://github.com/GeospatialPython/Learn/raw/master/hancock.zip" # Realizar la petición HTTP response = requests.get(url) # Guardar el contenido binario with open("hancock.zip", "wb") as f: f.write(response.content) print(f"Status: {response.status_code}")
FTP Protocol
import ftplib server = "ftp.ngdc.noaa.gov" directory = "hazards/DART/20070815_peru" filename = "21415_from_20070727_08_55_15_tides.txt" # Conectar al servidor FTP ftp = ftplib.FTP(server) ftp.login() # Acceso anónimo ftp.cwd(directory) # Descargar el archivo with open(filename, "wb") as out: ftp.retrbinary("RETR " + filename, out.write) # Verificar los datos with open(filename) as dart: for line in dart: if "LAT, " in line: print(line) break
Parsers de Datos
Los formatos de intercambio de datos geoespaciales incluyen XML (KML, GML) y JSON (GeoJSON). Python ofrece bibliotecas robustas para trabajar con ambos formatos.
ElementTree para XML/KML
import xml.etree.ElementTree as ET # Parsear documento KML tree = ET.ElementTree(file="time-stamp-point.kml") # Definir namespace KML ns = "{http://www.opengis.net/kml/2.2}" # Buscar elemento Placemark placemark = tree.find(f".//{ns}Placemark") # Extraer coordenadas coordinates = placemark.find(f"./{ns}Point/{ns}coordinates") print(coordinates.text)
JSON/GeoJSON
import json # Documento GeoJSON de ejemplo geojson_data = """ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [97.03125, 39.7265625] }, "properties": {"name": "Sample Point"}, "crs": { "type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"} } } """ # Parsear GeoJSON point = json.loads(geojson_data) # Acceder a la geometría print("Tipo:", point["geometry"]["type"]) print("Coordenadas:", point["geometry"]["coordinates"])
Coordenadas: [97.03125, 39.7265625]
eval() podría parsear JSON simple, aunque json.loads() es más seguro y robusto.
Bibliotecas para Datos Vectoriales
Los datos vectoriales representan features geográficos como puntos, líneas y polígonos. Python ofrece múltiples bibliotecas para trabajar con estos formatos.
OGR - Open Geospatial Library
OGR es parte de GDAL y soporta docenas de formatos vectoriales. Es el estándar de la industria:
from osgeo import ogr # Abrir shapefile con OGR shp = ogr.Open("point.shp") layer = shp.GetLayer() # Iterar sobre features for feature in layer: geometry = feature.GetGeometryRef() print(geometry.GetX(), geometry.GetY(), feature.GetField("FIRST_FLD"))
3.0 1.0 Second
4.0 3.0 Third
2.0 2.0 Fourth
0.0 0.0 Appended
PyShp - Pure Python Shapefile
PyShp es una biblioteca simple y pura Python para leer y escribir shapefiles. Es portátil y fácil de usar:
import shapefile # Leer shapefile con PyShp shp = shapefile.Reader("point.shp") # Iterar sobre features for feature in shp.shapeRecords(): point = feature.shape.points[0] rec = feature.record[0] print(point[0], point[1], rec)
3.0 1.0 Second
4.0 3.0 Third
2.0 2.0 Fourth
0.0 0.0 Appended
Shapely - Computational Geometry
Shapely proporciona una API Pythonic sobre la biblioteca GEOS para operaciones geométricas avanzadas:
from shapely import wkt, geometry # Crear polígono desde WKT wkt_poly = "POLYGON((0 0,4 0,4 4,0 4,0 0))" poly = wkt.loads(wkt_poly) # Calcular área print("Área original:", poly.area) # Crear buffer de 5 unidades buffered = poly.buffer(5.0) print("Área con buffer:", buffered.area) # Diferencia entre áreas print("Área del buffer:", buffered.difference(poly).area)
Área con buffer: 174.41371226364848
Área del buffer: 158.413712264
Fiona - Simplified OGR
Fiona simplifica OGR con una API más Pythonic, exportando a GeoJSON por defecto:
import fiona from pprint import pprint # Abrir shapefile con Fiona f = fiona.open("GIS_CensusTract_poly.shp") # Información del archivo print("Driver:", f.driver) print("CRS:", f.crs) print("Bounds:", f.bounds) print("Features:", len(f)) # Ver esquema de datos pprint(f.schema)
CRS: {'init': 'epsg:4269'}
Bounds: (-89.87, 30.16, -89.13, 30.66)
Features: 45
GeoPandas - High-Level Analysis
GeoPandas extiende Pandas para datos geoespaciales, combinando la potencia de Shapely, Fiona y matplotlib:
import geopandas import matplotlib.pyplot as plt # Cargar shapefile como GeoDataFrame gdf = geopandas.GeoDataFrame census = gdf.from_file("GIS_CensusTract_poly.shp") # Visualizar mapa census.plot() plt.show() # Exportar a GeoJSON census.to_file("census.geojson", driver="GeoJSON")
Bibliotecas para Datos Raster
Los datos raster son imágenes georreferenciadas compuestas por píxeles. Python ofrece herramientas poderosas para procesamiento de imágenes satelitales y teledetección.
GDAL - Raster I/O
GDAL es la biblioteca dominante para datos raster, presente en casi todas las herramientas geoespaciales:
from osgeo import gdal # Abrir imagen satelital raster = gdal.Open("SatImage.tif") # Obtener información del raster print("Bandas:", raster.RasterCount) print("Ancho (px):", raster.RasterXSize) print("Alto (px):", raster.RasterYSize) # Obtener geotransform gt = raster.GetGeoTransform() print("Origen X:", gt[0]) print("Origen Y:", gt[3])
Ancho (px): 2592
Alto (px): 2693
NumPy - Array Processing
NumPy es el procesador de arrays multidimensional esencial para análisis raster. Su integración con GDAL es perfecta:
from osgeo import gdal_array # Cargar imagen como array NumPy src_array = gdal_array.LoadFile("SatImage.tif") # Extraer primera banda band1 = src_array[0] # Guardar banda como JPEG gdal_array.SaveArray(band1, "band1.jpg", format="JPEG") # Información del array print("Shape:", src_array.shape) print("Dtype:", src_array.dtype)
Dtype: uint8
PIL/Pillow - Image Processing
PIL (Pillow en Python 3) fue desarrollada originalmente para teledetección y es excelente para procesamiento de imágenes:
from PIL import Image, ImageDraw # Crear imagen nueva img = Image.new("RGB", (400, 300), "black") draw = ImageDraw.Draw(img) # Dibujar polígono polygon = [(50, 50), (200, 50), (200, 200), (50, 200)] draw.polygon(polygon, fill="cyan", outline="white") # Guardar imagen img.save("polygon.png")
Rasterio - Pythonic GDAL
Rasterio envuelve GDAL en una API Python limpia y simple:
import rasterio # Abrir imagen con Rasterio ds = rasterio.open("SatImage.tif") # Información del dataset print("Nombre:", ds.name) print("Bandas:", ds.count) print("Dimensiones:", ds.width, "x", ds.height) # Leer banda como array band1 = ds.read(1) print("Array shape:", band1.shape)
Bandas: 3
Dimensiones: 2592 x 2693
PNGCanvas - Pure Python PNG
PNGCanvas crea imágenes PNG sin dependencias externas, ideal para visualización simple:
import shapefile import pngcanvas # Leer shapefile r = shapefile.Reader("hancock.shp") # Calcular dimensiones xdist = r.bbox[2] - r.bbox[0] ydist = r.bbox[3] - r.bbox[1] iwidth, iheight = 400, 600 xratio = iwidth / xdist yratio = iheight / ydist # Convertir coordenadas a píxeles pixels = [] for x, y in r.shapes()[0].points: px = int(iwidth - ((r.bbox[2] - x) * xratio)) py = int((r.bbox[3] - y) * yratio) pixels.append([px, py]) # Crear imagen y dibujar polilínea c = pngcanvas.PNGCanvas(iwidth, iheight) c.polyline(pixels) # Guardar PNG with open("hancock.png", "wb") as f: f.write(c.dump())
Bases de Datos Espaciales
Las bases de datos espaciales permiten almacenar y consultar datos geográficos de forma eficiente. Python puede conectarse a todas las principales bases de datos espaciales.
PyMySQL con Funciones Espaciales
import pymysql # Conectar a MySQL conn = pymysql.connect( host="localhost", user="root", password="password", database="spatial_db" ) cursor = conn.cursor() # Crear tabla con geometría cursor.execute(""" CREATE TABLE IF NOT EXISTS PLACES ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), location POINT NOT NULL, SPATIAL INDEX(location) ) """) # Insertar ciudades como puntos cursor.execute(""" INSERT INTO PLACES (name, location) VALUES ('New York', ST_GeomFromText('POINT(-74.006 40.7128)')), ('Los Angeles', ST_GeomFromText('POINT(-118.2437 34.0522)')) """) # Calcular distancia entre ciudades cursor.execute(""" SELECT ST_Distance( (SELECT location FROM PLACES WHERE name='New York'), (SELECT location FROM PLACES WHERE name='Los Angeles') ) AS distance_degrees """) result = cursor.fetchone() print(f"Distancia: {result[0]} grados") conn.commit() conn.close()
Redes Viales con OSMnx
OSMnx combina OpenStreetMap con NetworkX para descargar, analizar y visualizar redes de calles. Es una herramienta poderosa para análisis de routing y movilidad urbana.
import osmnx as ox # Descargar red de calles de una ciudad G = ox.graph_from_place( 'Bay Saint Louis, MS, USA', network_type='drive' ) # Calcular estadísticas básicas stats = ox.basic_stats(G) print("Longitud promedio de calle:", stats["street_length_avg"], "metros") # Visualizar red ox.plot_graph(G)
conda install -c conda-forge osmnx
PDF Geoespacial
Los PDFs geoespaciales contienen información de georreferenciación que permite conocer las coordenadas de cualquier punto en el documento. Python puede crear estos documentos usando la biblioteca geopdf.
from geopdf import GeoCanvas from reportlab.pdfbase.pdfdoc import PDFString, PDFArray # Crear canvas PDF canvas = GeoCanvas("map.pdf") # Dibujar el estado de Colorado (rectángulo) canvas.rect(100, 150, 400, 250, stroke=1, fill=0) # Definir coordenadas del mapa minx, miny = -109.05, 37.0 maxx, maxy = -102.05, 41.0 # Registrar georreferenciación registration = PDFArray([ PDFArray([PDFString('100'), PDFString('400'), PDFString(str(minx)), PDFString(str(maxy))]), PDFArray([PDFString('500'), PDFString('400'), PDFString(str(maxx)), PDFString(str(maxy))]), PDFArray([PDFString('100'), PDFString('150'), PDFString(str(minx)), PDFString(str(miny))]), PDFArray([PDFString('500'), PDFString('150'), PDFString(str(maxx)), PDFString(str(miny))]) ]) canvas.addGeo(Registration=registration) canvas.save()
pip install https://github.com/GeospatialPython/geopdf-py3/archive/master.zip
Jupyter Notebooks
Jupyter Notebook es una aplicación web que crea documentos interactivos combinando código ejecutable, visualizaciones y texto narrativo. Es la herramienta preferida para análisis geoespacial exploratorio.
# Instalar Jupyter pip install jupyter # Iniciar servidor de notebooks jupyter notebook # O usar JupyterLab (interfaz moderna) pip install jupyterlab jupyter lab
Catálogo de Herramientas
| BIBLIOTECA | TIPO | USO PRINCIPAL |
|---|---|---|
| GDAL/OGR | Raster Vector | I/O de formatos geoespaciales |
| PyShp | Vector | Lectura/escritura de shapefiles |
| Shapely | Vector | Operaciones geométricas |
| Fiona | Vector | API simplificada sobre OGR |
| GeoPandas | Vector | Análisis de datos espaciales |
| NumPy | Raster | Procesamiento de arrays |
| PIL/Pillow | Raster | Edición de imágenes |
| Rasterio | Raster | API Pythonic para GDAL |
| OSMnx | Vector | Redes de calles |
| PyMySQL | Database | Conexión a MySQL espacial |
01 // Datos Vectoriales
OGR, PyShp, Shapely, Fiona y GeoPandas para puntos, líneas y polígonos.
02 // Datos Raster
GDAL, NumPy, PIL y Rasterio para imágenes satelitales y teledetección.
03 // Adquisición de Datos
urllib, requests y ftplib para descargar datos geoespaciales de internet.
04 // Formatos de Intercambio
ElementTree para XML/KML y json para GeoJSON y APIs web.