Autonomía digital y tecnológica

Código e ideas para una internet distribuida

Cómo cambiar un grupo de ubicaciones georreferenciadas de sistema de referencia de coordenadas geográficas (CRS)

Imago voragine.net

Los sistemas de referencia de coordenadas (CRS) o sistemas de referencia espacial (SRS) son complicados, al menos para mí que no soy geógrafo y tengo un conocimiento superficial de GIS: existen más de 13.000 sistemas diferentes y siempre me cuesta saber en qué sistema están las ubicaciones de un conjunto de datos georreferenciados. Siempre he tenido la intuición de que es algo complejísimo, sin saber exactamente a qué nivel. Solo cuando leí este maravilloso post de 2011 sobre el tema (que por supuesto no hace falta leer para conseguir cambiar de CRS un conjunto de datos), empecé a tomar consciencia de la magnitud de la complejidad: el post explica la incapacidad de las distintas herramientas de transformación para conseguir precisión en las conversiones, dando resultados que pueden diferir en torno a 20km. Apasionante lectura también para personas interesadas en saber curiosidades como de dónde vienen los códigos EPSG, hoy uno de los estándares para sistemas de referencia de coordenadas.

Pero voy a tema. A mí que trabajo casi siempre desarrollando para web me interesa en general que los datos geográficos usen latitud y longitud. Es el sistema de coordenadas que se suele usar en web y en aplicaciones GPS: Google Maps, Bing Maps, OpenStreetMap usan latitud y longitud. Si los datos que recibo usan un sistema cartesiano, tengo que transformarlos.

Detectar el sistema de referencia de coordenadas de un conjunto de datos

Lo primero que hay que hacer es saber en qué sistema de referencia están. Esto puede no ser fácil. Para ello hay que mirar los meta-datos del conjunto de datos y no todos los formatos guardan información sobre el CRS. Cuando no sé en qué sistema están los datos, uso QGIS: abro el archivo con los datos y luego lo exporto a geojson. Este formato guarda meta-datos sobre el CRS. Por ejemplo:

{
 "type": "FeatureCollection",
 "name": "projects",
 "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::3857" } },
 "features": []
}

Otra forma de detectar el CRS de un conjunto de datos es usar el programa de línea de comandos projinfo, que forma parte del paquete de software PROJ. Sin embargo projinfo únicamente detecta el CRS de archivos .prj (información geoespacial de los archivos shape) o .geotiff, hasta donde he podido leer en la documentación. Así que es QGIS el que me suele ayudar en esta tarea.

Cambiar el sistema de referencia de coordenadas de un conjunto de datos

Hay multitud de maneras de cambiar el CRS de un conjunto de datos. Yo busco herramientas que permitan automatizar la tarea dentro de los procesos de limpieza de datos que hago. Para este tipo de procesos, los programitas que integran el paquete de software PROJ me funcionan de maravilla.

PROJ integra librerías para varios lenguajes de programación. Yo he usado dos: cs2cs en la línea de comandos, y pyproj en scripts de Python.

Transformar EPSG:3857 (Web Mercator) a EPSG:4326 (WGS 84) con cs2cs

EPSG:4386 es el sistema que usan la mayoría de cartografías web como OpenStreetMap o Google Maps. Para transformar datos en otro CRS, por ejemplo EPSG:3857, a EPSG:4326 con cs2cs en la línea de comandos:

echo "20037508.34 20037508.34 100" | cs2cs -f "%.6f" EPSG:3857 EPSG:4326

El modificador -f permite especificar el formato de salida tras la conversión. Si no se usa -f, cs2cs devuelve por omisión grados, minutos y segundos. Para obtener grados decimales, que es lo que yo necesito para web, hay que añadir -f "%.6f" donde 6 es el número de cifras decimales.

cs2cs devuelve tres coordenadas: x y z. En proyecciones planas la tercera es siempre 0, por supuesto:

85.051129 180.000000 0.000000

cs2cs puede transformar un conjunto de coordenadas si se le suministra un archivo con pares por líneas. Por ejemplo, el siguiente listado en EPSG:3857 alojado en el archivo coords.list:

echo coords.list
231362.441622 5082306.625994
-97756.310090 5108535.370440
-674547.189064 4487249.462584
-220554.193010 5360852.515295
-36260.920048 5255629.363755
245097.478426 5071621.614563
-455214.864321 4964279.036953
-53978.135458 4628117.767552

Se puede transformar masivamente de la siguiente manera:

cs2cs -f "%.6f" EPSG:3857 EPSG:4326 coords.list
41.472631	2.078364 0.000000
41.648932	-0.878160 0.000000
37.344603	-6.059560 0.000000
43.320300	-1.981272 0.000000
42.628723	-0.325737 0.000000
41.400673	2.201748 0.000000
40.673346	-4.089265 0.000000
38.343871	-0.484894 0.000000

Transformar EPSG:3857 (Web Mercator) a EPSG:4326 (WGS 84) con pyproj en Python

Para transformaciones de CRS dentro de un proceso de limpieza o estructuración de datos más amplio, quizás tenga más sentido usar una librería como pyproj en Python. La transformación en Python se podría hacer de la siguiente manera, suponiendo que el conjunto de datos esté en formato CSV:

import pandas as pd
from pyproj import Transformer

# define la conversión de EPSG:3857 a EPSG:4326
transformer = Transformer.from_crs("EPSG:3857", "EPSG:4326", always_xy=True)

# variables para el dataset de origen y el transformado
input_csv = "input.csv"
output_csv = "output.csv"

# abre el archivo de origen
df = pd.read_csv(input_csv)

# variables para las columnas con la información geográfica
x_col = "longitude"
y_col = "latitude"

# hace la conversión
df[[x_col, y_col]] = df.apply(lambda row: transformer.transform(row[x_col], row[y_col]), axis=1, result_type="expand")

# guarda los datos transformados
df.to_csv(output_csv, index=False)

Dejar un comentario

No hay comentarios en esta entrada.
*
*

 

No hay trackbacks