2016-09-15 3 views
2

Ich habe einen Datenrahmen von Standorten und ich wollte sie zu einer kategorischen Variable (Klimaregion) von einer Karte zuordnen. Hier ein kleiner Auszug:R extrahieren Kategorien für Punkte aus gerasterten Daten

df <- data.frame(lat = c(29.30050, 47.67309, 53.30710, -27.60303, 41.31858, 40.50738, 
         50.67013,60.23163, 42.54555), 
       long = c(47.806320, -122.315312, -6.281798, 151.951778, -72.849961, 
          -74.382711, 4.348718, 19.710874, -71.038764)) 

ich wo gelernt, die Daten aus dieser excellent article zu erhalten. Was ich tun möchte, ist die kategoriale Variable für jeden Punkt in meinem Datenrahmen zu extrahieren. Das mag trivial klingen, aber ich bin neu im Mapping und finde keine Hilfeartikel. Das Problem könnte sein, dass ich die falschen Begriffe benutze!

Die Zuordnung der Datensätze ist mit dem Lernprogramm ziemlich einfach, aber die Rasterübereinstimmung ist über mich hinaus. Die kategorischen Kartendaten sind entweder im .txt-, .kmz- oder im GIS-Format here verfügbar. Daher bin ich nicht auf eine Methode beschränkt.

Ich habe Nearest-Matches pro Lat und Long versucht, aber es unterscheidet nicht, auf welcher Seite des Gitters Sie wählen können. Ich habe die Dokumentation über Pastor, Rworldmap, Rgdal und alle Suchkombinationen durchsucht, die ich beim Stack-Überlauf finden konnte.

+0

Suchen Sie nach einer räumlichen Überlagerung? Können die gleichen Daten auch über "rworldmap" gesammelt werden? –

+1

Ich habe in der rworldmap-Dokumentation nichts über eine interne Klimaregionskarte gesehen, obwohl der Tutorial-Link, den ich gepostet habe, von den Rworldmap-Autoren stammt. Ich konnte die beiden leicht übereinander abbilden, aber nicht die Kategorie extrahieren. Alistaires Antwort unten macht den Trick. –

Antwort

3

Wenn wir die Daten von der Website herunterladen und lesen Sie es als koeppen, z.

download.file('http://koeppen-geiger.vu-wien.ac.at/data/Koeppen-Geiger-ASCII.zip', 
       'Koeppen-Geiger-ASCII.zip', 
       method = 'curl') 

# use read.table if you like, but read_table cuts a lot of hassle with poor formatting 
koeppen <- readr::read_table('Koeppen-Geiger-ASCII.zip') 

und wir betrachten die Daten, alle Breiten und Längen unzweckmäßig enden mit .25 oder .75:

koeppen 
## # A tibble: 92,416 × 3 
##  Lat  Lon Cls 
##  <dbl> <dbl> <chr> 
## 1 -89.75 -179.75 EF 
## 2 -89.75 -179.25 EF 
## 3 -89.75 -178.75 EF 
## 4 -89.75 -178.25 EF 
## 5 -89.75 -177.75 EF 
## 6 -89.75 -177.25 EF 
## 7 -89.75 -176.75 EF 
## 8 -89.75 -176.25 EF 
## 9 -89.75 -175.75 EF 
## 10 -89.75 -175.25 EF 
## # ... with 92,406 more rows 

So die beiden Tabellen zu verschmelzen, müssen wir df ‚s Breiten abzurunden und Längen in .25 oder .75 enden, z von

df[] <- lapply(df, function(x){ifelse(x %% 1 > .5, 0.75, 0.25) + floor(x)}) 

erhält den Rest aus der Division durch eine, dh die nicht-ganzzahligen Teil, und wenn es größer ist als .5 kehrt .75, sonst kehrt .25, dann wieder Addieren der ganzzahligen Teil, so df sieht jetzt aus wie:

df 
##  lat long 
## 1 29.25 47.75 
## 2 47.75 -122.25 
## 3 53.25 -6.25 
## 4 -27.75 151.75 
## 5 41.25 -72.75 
## 6 40.75 -74.25 
## 7 50.75 4.25 
## 8 60.25 19.75 
## 9 42.75 -71.25 

Jetzt können wir merge (oder dplyr schließt sich, wenn Sie bevorzugen) eine Cls Spalte df für passende Breiten und Längen hinzuzufügen:

df <- merge(df, koeppen, 
      by.x = c('lat', 'long'), 
      by.y = c('Lat', 'Lon'), 
      all.x = TRUE) 

# or dplyr::left_join(df, koeppen, by = c('lat' = 'Lat', 'long' = 'Lon')) 

df 
##  lat long Cls 
## 1 -27.75 151.75 Cfa 
## 2 29.25 47.75 BWh 
## 3 40.75 -74.25 Cfa 
## 4 41.25 -72.75 Cfa 
## 5 42.75 -71.25 Dfb 
## 6 47.75 -122.25 Csb 
## 7 50.75 4.25 Cfb 
## 8 53.25 -6.25 Cfb 
## 9 60.25 19.75 Dfb 

Dies könnte auch ein guter Fall für data.table's non-equi-joins sein, wenn Sie die Grammatik mögen.

+0

Das ist genau das, was ich brauchte! Ich arbeitete gerade daran, eine 'round_any (df [, 1], 0.25, floor)' Arbeit zu benutzen und stellte natürlich fest, dass eines meiner Probleme die 0.25 und 0.75 war, als ich deine Antwort bekam. Ich arbeite immer noch daran zu lernen, wie man %% Modifier benutzt, und das hilft mir besser zu verstehen, wie das funktioniert. Vielen Dank! –

+1

'% /%' und '%%' geben Ihnen die zwei Teile einer langen Division Antwort: '% /%', genannt Integer oder Floor Division, gibt Ihnen die ganze Zahl Teil; '%%' gibt den Rest (auch Modulo genannt), also gibt '7% /% 3' 2 zurück und' 7 %% 3' gibt 1 zurück. – alistaire