Comment puis-je convertir des données sous la forme de lat, lon, value dans un fichier raster en utilisant R?

40

J'ai un ensemble de données de valeurs sur une grille de km dans le continent américain. Les colonnes sont "latitude", "longitude" et "observation", par exemple:

"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

ou, en tant que trame de données 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))

(le jeu de données complet peut être téléchargé en tant que csv ici )

Les données sont générées à partir d'un modèle de culture (destiné à être utilisé) sur une grille de 30 km sur 30 km (d'après Miguez et al, 2012 ).

entrez la description de l'image ici

Comment puis-je les convertir en un fichier raster avec des métadonnées liées au SIG telles que la projection cartographique?

Idéalement, le fichier serait un fichier texte (ASCII?), Car je souhaiterais qu'il soit indépendant de la plate-forme et du logiciel.

Abe
la source
En tant que CSV, il s’agit déjà d’ un "fichier texte" en ASCII. De plus, comme il n’utilise aucune projection, il peut y avoir peu de métadonnées pertinentes à ajouter (datum, principalement). Pourriez-vous être un peu plus précis sur le type de sortie que vous recherchez et sur ce que vous comptez en faire?
whuber
J'aimerais rendre l'utilisation de ces données aussi simple que possible avec divers logiciels de cartographie (ArcGIS, Google Maps, Grass, R, etc.) afin de faciliter leur réutilisation, par exemple en ne nécessitant pas d'étapes de conversion supplémentaires. En se basant sur la page Wikipedia des formats de fichier SIG, j’en déduis 1) un fichier "raster" devrait avoir des noms de domaine avec des noms de latitude et de colonne, comme une image, et que 2) les métadonnées devraient inclure des informations géographiques (emplacement d’un coin, zone couverte) par données).
Abe
C'est l'une des meilleures références que j'ai rencontrées sur R et les SIG. Merci beaucoup! Pouvez-vous s'il vous plaît fournir un autre csv avec lat et long avec proj4string correct? Je vais vraiment apprécier ça.
@Nandini Je ne sais pas ce que le proj4string est correct, je soupçonne lambert conformationnelle:proj +proj=lcc +lat_1=50.0 +lat_2=50.0 +units=km +lon_0=-145.5 +lat_0=1.0 . Je ne suis pas sûr de ce que vous demandez en ce qui concerne un autre fichier csv - en quoi cela diffère-t-il de celui qui est lié à la question ou de la réponse acceptée?
Abe
pour moi ça ne marche pas! Je ne sais pas quoi mettre "x" et "y" en "coordonnées (pts) = ~ x + y"

Réponses:

44

Plusieurs étapes requises:

  1. Vous dites que c'est une grille régulière de 1 km, mais cela signifie que les lat-long ne sont pas réguliers. Vous devez d’abord le transformer en un système de coordonnées de grille régulier afin que les valeurs X et Y soient régulièrement espacées.

    une. Lisez-le dans R en tant que trame de données, avec les colonnes x, y, donnez.

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

    b. Convertissez le cadre de données en un fichier SpatialPointsDataFrame à l’aide du package sp et reproduisez les éléments suivants:

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

    c. Convertissez votre système habituel en km en lui indiquant d'abord de quel CRS il s'agit, puis spTransform vers la destination.

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

    ré. Dites à R que cela est maillé:

    gridded(pts) = TRUE

    À ce stade, vous obtiendrez une erreur si vos coordonnées ne se trouvent pas sur une belle grille régulière.

  2. Maintenant, utilisez le package raster pour convertir en un raster et définir son CRS:

    r = raster(pts)
    projection(r) = CRS("insert your proj4 string here")
  3. Regardez maintenant:

    plot(r)
  4. Maintenant, écrivez-le en tant que fichier geoTIFF en utilisant le paquetage raster:

    writeRaster(r,"pts.tif")

Ce fichier geoTIFF doit être lisible dans tous les principaux packages SIG. La pièce manquante évidente ici est la chaîne proj4 à convertir: ce sera probablement une sorte de système de référence UTM. Difficile à dire sans plus de données ...

Spacedman
la source
+1 Merci d'avoir présenté le flux de travail. Notez que les données sont disponibles sur le lien fourni dans la question: regardez. Vous découvrirez, hélas, que certaines de vos hypothèses à leur sujet sont incorrectes. (En particulier, j'ai recherché toute la documentation sur la projection utilisée pour créer la grille, mais je n'en ai trouvé aucune. Et c'est une projection étrange, comme vous pouvez le constater en traçant les points.)
whuber
C'est très proche d'être un système UTM, mais aucun de ceux que j'ai essayés n'est assez proche d'une grille régulière pour que R les mette en grille. Je suis à moitié tenté de parcourir l'intégralité de la base de données epsg de R ....
Spacedman
Ce serait un véritable tour de force si vous pouviez découvrir la projection de cette façon! La clé est de trouver un critère effectif et efficient pour déterminer quand ces 7 000 points ou plus sont suffisamment proches pour être situés sur une grille régulière (car il est possible qu'ils ne forment pas une grille parfaite dans une projection standard du tout). Pour parcourir rapidement la base de données, il devrait suffire de comparer un petit nombre de distances, par exemple une distance est-ouest dans la partie nord de la grille à une distance est-ouest dans la partie sud. Cela devrait éliminer rapidement la grande majorité des candidats.
whuber
3
J'ai parcouru toutes les projections (par défaut) prises en charge par Mathematica 8. Il a trouvé une projection dans laquelle les points semblent réellement tomber sur une grille: Alaska State Plane (1983), Zone 10! Ceci est une projection conique conforme de Lambert. Je crois que c'est EPSG 26940 . Si vous modifiez ceci pour le centrer approximativement à -106 de longitude, les points forment une très bonne grille.
whuber
1
Abe, voulez-vous dire lire la page Web? C'était r = Import[ "https://ebi-forecast.igb.illinois.edu/bety/miscanthusyield.csv", "Data"];. Vous pouvez ensuite obtenir un aperçu rapide des points via data = Rest[r]; ListPlot[data[[;; , {3, 2}]]](ou ListPointPlot3D[data[[;; , {3, 2, 4}]]]). Pour les reprojections, commencez par l'aide GeoGridPosition, puis faites des suppositions intelligentes et des références croisées pour comprendre ce qui se passe :-). BTW, l'explication de Spacedman est vraiment pertinente: la distorsion métrique de 25 à 49 degrés est égale à cos (25) / cos (49) = 1,38; c'est substantiel.
whuber
29

Depuis la dernière réponse à la question, une solution beaucoup plus simple existe en utilisant la rasterFromXYZfonction du package raster qui encapsule toutes les étapes nécessaires (y compris la spécification de la chaîne CRS).

library(raster)
rasterFromXYZ(mydata)
Lucas Fortini
la source
1
Toutes mes excuses à l'inlassable @Spacedman, qui m'a souvent assisté, mais je pense que cette réponse mérite d'hériter de la tique verte.
geotheory
@geotheory Je choisirais cette réponse, c'est une fonction très utile, mais elle semble être très lente sur le jeu de données que j'utilise (lié à l'opération)
Abe
1
... en fait, cela s’est étouffé, car il a fallu mon fichier de ~ 400Ko pour créer un fichier de ~ 19 Go /tmp/lorsque j’ai manqué d’espace disque.
Abe
Il existe probablement un processus n-squared quelque part. Vous pourrez peut-être regrouper les données de points sur une large grille, pixelliser chaque groupe individuellement, puis merge()les résultats.
geotheory
Avec tout le respect que je vous dois, mais cette réponse est bien meilleure que celle de Spacedman.
Ghost