¿Cómo puedo convertir datos en forma de lat, lon, value en un archivo ráster usando R?

40

Tengo un conjunto de datos de valores en una cuadrícula de km en los Estados Unidos continentales. Las columnas son "latitud", "longitud" y "observación", por ejemplo:

"lat"    "lon"     "yield"
 25.567  -120.347  3.6 
 25.832  -120.400  2.6
 26.097  -120.454  3.4
 26.363  -120.508  3.1
 26.630  -120.562  4.4

o, como un marco de datos R:

mydata <- structure(list(lat = c(25.567, 25.832, 26.097, 26.363, 26.63), 
lon = c(-120.347, -120.4, -120.454, -120.508, -120.562), 
yield = c(3.6, 2.6, 3.4, 3.1, 4.4)), .Names = c("lat", 
"lon", "yield"), class = "data.frame", row.names = c(NA, -5L))

(el conjunto de datos completo se puede descargar como csv aquí )

Los datos se obtienen de un modelo de cultivo (destinado a estar en) una cuadrícula de 30 km x 30 km (de Miguez et al 2012 ).

ingrese la descripción de la imagen aquí

¿Cómo puedo convertirlos en un archivo ráster con metadatos relacionados con SIG, como la proyección de mapas?

Idealmente, el archivo sería un archivo de texto (ASCII?) Porque me gustaría que fuera independiente de la plataforma y el software.

Abe
fuente
Como CSV, este ya es un "archivo de texto" en ASCII. Además, como no utiliza ninguna proyección, puede haber pocos metadatos relevantes para agregar (dato, principalmente). ¿Podría ser un poco más específico sobre qué tipo de salida busca y qué piensa hacer con ella?
whuber
Me gustaría facilitar que alguien pueda usar los datos con una variedad de software de mapeo (ArcGIS, Google Maps, Grass, R, etc.) para facilitar la reutilización, por ejemplo, al no requerir pasos de conversión adicionales. Basado en la página de Wikipedia de los formatos de archivo SIG, infiero 1) un archivo "raster" debe tener nombres de fila con nombres de latitud y columna de longitud, como una imagen y 2) los metadatos deben incluir información geográfica (ubicación de una esquina, área cubierta por datos).
Abe
Esta es una de las mejores referencias que encontré en R y GIS. ¡Muchas gracias! ¿Puede proporcionar otro csv con lat y long con proj4string correcto? Realmente lo apreciaré.
@Nandini No está seguro de lo que el proj4string correcta es, sospecho conforme de Lambert:proj +proj=lcc +lat_1=50.0 +lat_2=50.0 +units=km +lon_0=-145.5 +lat_0=1.0 . No estoy seguro de lo que está pidiendo con respecto a otro archivo csv: ¿en qué diferiría del que está vinculado en la pregunta, o eso sería producido por la respuesta aceptada?
Abe
para mi no funciona! No sé qué poner en "x" y "y" a "coordenadas (pts) = ~ x + y"

Respuestas:

44

Se requieren varios pasos:

  1. Dices que es una cuadrícula regular de 1 km, pero eso significa que los lat-long no son regulares. Primero debe transformarlo en un sistema de coordenadas de cuadrícula regular para que los valores X e Y se espacien regularmente.

    a. Léalo en R como un marco de datos, con columnas x, y, rendimiento.

    pts = read.table("file.csv",......)

    si. Convierta el marco de datos en un SpatialPointsDataFrame usando el paquete sp y algo como:

    library(sp)
    library(rgdal)
    coordinates(pts)=~x+y

    do. Convierta a su sistema de km regular diciéndole primero qué CRS es, y luego spTransform al destino.

    proj4string(pts)=CRS("+init=epsg:4326") # set it to lat-long
    pts = spTransform(pts,CRS("insert your proj4 string here"))

    re. Dile a R que esto está cuadriculado:

    gridded(pts) = TRUE

    En este punto, obtendrá un error si sus coordenadas no se encuentran en una cuadrícula regular agradable.

  2. Ahora use el paquete ráster para convertir a un ráster y establecer su CRS:

    r = raster(pts)
    projection(r) = CRS("insert your proj4 string here")
  3. Ahora echa un vistazo:

    plot(r)
  4. Ahora escríbalo como un archivo geoTIFF usando el paquete ráster:

    writeRaster(r,"pts.tif")

Este geoTIFF debería ser legible en todos los paquetes principales de SIG. La pieza obvia que falta aquí es la cadena proj4 a la que convertir: probablemente sea algún tipo de sistema de referencia UTM. Difícil de decir sin algunos datos más ...

Hombre espacial
fuente
+1 Gracias por diseñar el flujo de trabajo. Tenga en cuenta que los datos están disponibles en el enlace proporcionado en la pregunta: eche un vistazo. Descubrirá, por desgracia, que algunos de sus supuestos sobre ellos son incorrectos. (En particular, Cacé para cualquier documentación acerca de la proyección utilizada para crear la red, pero no encontré ninguno y es una proyección extraña, como se puede ver por el trazado de los puntos..)
whuber
Está muy cerca de ser un sistema UTM, pero ninguno de los que he probado está lo suficientemente cerca de una cuadrícula regular como para que R los cuadricule. Estoy medio tentado de recorrer toda la base de datos epsg de R ...
Spacedman
¡Sería un verdadero tour de force si pudieras descubrir la proyección de esa manera! La clave es encontrar un criterio efectivo y eficiente para determinar cuándo estos más de 7,000 puntos están lo suficientemente cerca de estar en una cuadrícula regular (porque es posible que no formen una cuadrícula perfecta en ninguna proyección estándar). Para una ejecución rápida a través de la base de datos, debería ser suficiente comparar una pequeña cantidad de distancias, como una distancia este-oeste en la parte norte de la cuadrícula con una distancia este-oeste en la parte sur. Eso debería eliminar a la gran mayoría de los candidatos rápidamente.
whuber
3
Revisé todas las proyecciones (predeterminadas) compatibles con Mathematica 8. Encontré una proyección en la que los puntos realmente parecen caer en una cuadrícula: Alaska State Plane (1983) Zone 10! Esta es una proyección cónica conforme de Lambert. Creo que es EPSG 26940 . Si modifica esto para centrarlo aproximadamente a una longitud de -106, los puntos forman una cuadrícula bastante buena.
whuber
1
Abe, ¿quieres leer la página web? Fue r = Import[ "https://ebi-forecast.igb.illinois.edu/bety/miscanthusyield.csv", "Data"];. Puede obtener una gráfica rápida de los puntos luego a través de data = Rest[r]; ListPlot[data[[;; , {3, 2}]]](o ListPointPlot3D[data[[;; , {3, 2, 4}]]]). Para las reproyecciones, comience con la ayuda GeoGridPosition, luego haga algunas suposiciones inteligentes y referencias cruzadas para descubrir qué está sucediendo :-). Por cierto, la explicación de @ Spacedman es realmente relevante: la distorsión métrica de 25 a 49 grados es igual a cos (25) / cos (49) = 1.38; Eso es sustancial.
whuber
29

Desde la última respuesta a la pregunta, existe una solución mucho más fácil mediante el uso de la rasterFromXYZfunción del paquete ráster que encapsula todos los pasos necesarios (incluida la especificación de la cadena CRS).

library(raster)
rasterFromXYZ(mydata)
Lucas Fortini
fuente
1
Disculpas al incansable @Spacedman, que me ha ayudado a menudo, pero creo que esta respuesta merece heredar la alegre garrapata verde.
geotheory
@geotheory Seleccionaría esta respuesta, es una gran función, pero parece ser muy lenta en el conjunto de datos que estoy usando (vinculado en la operación)
Abe
1
... de hecho se atragantó porque tomó mi archivo de ~ 400 KB y creó un archivo de /tmp/~ 19 GB cuando me quedé sin espacio en disco.
Abe
Probablemente hay un proceso de n cuadrado en alguna parte. Es posible que pueda agrupar los datos de puntos por una cuadrícula amplia, rasterizar cada grupo individualmente y luego merge()juntar los resultados.
geotheory
Con el debido respeto, pero esta respuesta es mucho mejor que la de Spacedman.
Fantasma