Como posso converter dados na forma de lat, lon, value em um arquivo rasterizado usando R?

40

Eu tenho um conjunto de dados de valores em uma grade de km nos EUA continentais. As colunas são "latitude", "longitude" e "observação", por exemplo:

"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, como um quadro de dados 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))

(o conjunto completo de dados pode ser baixado como csv aqui )

Os dados são gerados a partir de um modelo de cultivo (destinado a ser ligado) em uma grade de 30 km x 30 km (de Miguez et al 2012 ).

insira a descrição da imagem aqui

Como posso convertê-los em um arquivo raster com metadados relacionados ao GIS, como projeção de mapa?

Idealmente, o arquivo seria um arquivo de texto (ASCII?) Porque eu gostaria que fosse independente da plataforma e do software.

Abe
fonte
Como CSV, esse já é um "arquivo de texto" em ASCII. Além disso, como não usa projeção, pode haver poucos metadados relevantes a serem adicionados (dados, principalmente). Você poderia ser um pouco mais específico sobre o tipo de resultado que deseja e o que pretende fazer com ele?
whuber
Eu gostaria de tornar o mais fácil possível para alguém usar os dados com uma variedade de software de mapeamento (ArcGIS, Google Maps, Grass, R etc.) para facilitar a reutilização, por exemplo, não exigindo etapas adicionais de conversão. Com base na página da Wikipedia dos formatos de arquivo GIS, deduzo 1) um arquivo "raster" deve ter nomes de nomes com latitude e nomes de colunas de longitude, como uma imagem e 2) os metadados devem incluir informações geográficas (localização de um canto, área coberta por dados).
Abe
Essa é uma das melhores referências que encontrei no R e GIS. Muito obrigado! Você pode fornecer outro csv com lat e long com proj4string correto? Eu realmente aprecio isso.
@Nandini Não sei o que o proj4string correta é, eu suspeito conforme de Lambert:proj +proj=lcc +lat_1=50.0 +lat_2=50.0 +units=km +lon_0=-145.5 +lat_0=1.0 . Não tenho certeza do que você está pedindo em relação a outro arquivo csv - como ele diferiria daquele vinculado na pergunta ou que seria produzido pela resposta aceita?
Abe
para mim não funciona! Eu não sei o que colocar em "x" e "y" para "coordenadas (pts) = ~ x + y"

Respostas:

44

Várias etapas necessárias:

  1. Você diz que é uma grade regular de 1 km, mas isso significa que os longos não são regulares. Primeiro, você precisa transformá-lo em um sistema de coordenadas de grade regular, para que os valores X e Y sejam espaçados regularmente.

    uma. Leia-o em R como um quadro de dados, com colunas x, y, rendimento.

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

    b. Converta o quadro de dados em um SpatialPointsDataFrame usando o pacote sp e algo como:

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

    c. Converta para o seu sistema de km regular, primeiro informando o que é CRS e depois spTransform para o destino.

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

    d. Diga a R que isso está na grade:

    gridded(pts) = TRUE

    Nesse ponto, você receberá um erro se suas coordenadas não estiverem em uma boa grade regular.

  2. Agora use o pacote raster para converter em raster e defina seu CRS:

    r = raster(pts)
    projection(r) = CRS("insert your proj4 string here")
  3. Agora dê uma olhada:

    plot(r)
  4. Agora escreva-o como um arquivo geoTIFF usando o pacote raster:

    writeRaster(r,"pts.tif")

Esse geoTIFF deve ser legível em todos os principais pacotes GIS. A peça que falta obviamente aqui é a string proj4 para a qual converter: provavelmente será algum tipo de sistema de referência UTM. Difícil dizer sem mais alguns dados ...

Spacedman
fonte
+1 Obrigado por definir o fluxo de trabalho. Observe que os dados estão disponíveis no link fornecido na pergunta: dê uma olhada. Você descobrirá, infelizmente, que algumas de suas suposições sobre elas estão incorretas. (Em particular, eu caçados por qualquer documentação sobre a projeção usada para criar a grade, mas não encontrou nenhuma E é uma projeção estranha, como você pode ver, plotando os pontos..)
whuber
Está muito perto de ser um sistema UTM, mas nenhum dos que eu tentei está perto o suficiente de uma grade regular para o R fazer a grade deles. Eu estou meio tentado a percorrer toda base de dados EPSG de R ....
Spacedman
Seria um verdadeiro tour de force se você pudesse descobrir a projeção dessa maneira! A chave é encontrar um critério eficaz e eficiente para determinar quando esses mais de 7.000 pontos estão próximos o suficiente para ficarem em uma grade regular (porque é possível que eles não formem uma grade perfeita em nenhuma projeção padrão). Para uma rápida pesquisa no banco de dados, basta comparar um pequeno número de distâncias, como uma distância leste-oeste na parte norte da grade e uma distância leste-oeste na parte sul. Isso deve eliminar a grande maioria dos candidatos rapidamente.
whuber
3
Passei por todas as projeções (padrão) suportadas pelo Mathematica 8. Ele encontrou uma projeção na qual os pontos realmente parecem cair em uma grade: Alaska State Plane (1983) Zona 10! Esta é uma projeção cônica conforme Lambert. Eu acredito que é EPSG 26940 . Se você modificar isso para centralizá-lo aproximadamente na longitude -106, os pontos formarão uma grade muito boa.
whuber
1
Abe, você quer ler a página da Web? Foi r = Import[ "https://ebi-forecast.igb.illinois.edu/bety/miscanthusyield.csv", "Data"];. Você pode obter uma plotagem rápida dos pontos posteriormente via data = Rest[r]; ListPlot[data[[;; , {3, 2}]]](ou ListPointPlot3D[data[[;; , {3, 2, 4}]]]). Para reprojeções, comece com a ajuda GeoGridPositione faça algumas suposições inteligentes e referências cruzadas para descobrir o que está acontecendo :-). Aliás, a explicação de @ Spacedman é realmente relevante: a distorção métrica de 25 a 49 graus é igual a cos (25) / cos (49) = 1,38; isso é substancial.
whuber
29

Desde que a pergunta foi respondida pela última vez, existe uma solução muito mais fácil usando a rasterFromXYZfunção do pacote raster que encapsula todas as etapas necessárias (incluindo a especificação da cadeia CRS).

library(raster)
rasterFromXYZ(mydata)
Lucas Fortini
fonte
1
Desculpas ao incansável @Spacedman, que sempre me ajudou, mas acho que essa resposta merece herdar o tique verde alegre.
Geotheory
@geotheory eu iria selecionar esta resposta, é uma grande função, mas parece ser muito lento no conjunto de dados Eu estou usando (vinculado na op)
Abe
1
... de fato, ele engasgou porque pegou meu arquivo de ~ 400 KB e criou um arquivo com /tmp/~ 19 GB quando fiquei sem espaço em disco.
21415 Abe
Provavelmente existe um processo n-quadrado em algum lugar. Você pode agrupar os dados dos pontos por uma grade ampla, rasterizar cada grupo individualmente e depois merge()os resultados juntos.
geotheory
Com todo o respeito, mas essa resposta é muito melhor que a de Spacedman.
Ghost