SpatialPointsDataFrame-Eigenschaften und -Operatoren in R

14

Ich habe ein Objekt vom Typ SpatialPointsDataFramemit dem spPaket in R erstellt. Ich bin jedoch verwirrt über die @, $, . and []Operatoren und wann sie verwendet werden müssen, um auf die verschiedenen Eigenschaften meines Objekts zuzugreifen. Hier ist mein Beispielcode:

library(sp)
library(rgdal)

#creating a SpatialPointsDataFrame with sample points in UTM
x <- c(15.2, 15.3, 15.4, 15.5, 15.7)
y <- c(50.4, 50.2, 50.3, 50.1, 50.4)
v1 <- c(1.0, 2.0, 3.0, 4.0, 5.0)
v2 <- c("a","b","b","c","a")
attributes <- as.data.frame(cbind(v1,v2))
xy <- cbind(x,y)
locationsDD <- SpatialPointsDataFrame(xy, attributes)
proj4string(locationsDD) <- CRS("+proj=longlat")
locations <- spTransform(locationsDD, CRS("+proj=utm +zone=33"))
plot(locations)

#using the different operators: WHEN TO USE @, $ or [] ?

#all these work!
property1 <- locations$v1
property2 <- locations@data$v1
property3 <- locations@data[,"v1"]
property4 <- locations@data["v1"]

#these also work
property5 <- locations@coords
property6 <- locations@bbox
property7 <- locations@coords[,2]

#these three work only in my special case
property8 <- locations@coords[,"y"]
property9 <- locations$x
property10 <- locations$y

#these don't work: $ operator is invalid for atomic vectors
property11 <- locations@coords$x
property12 <- locations@coords$y

Könnte mir jemand helfen, wann man die @, $, []Operatoren benutzt? Wenn ich versuche, die Dokumentation zu lesen, ?SpatialPointsDataFramesehe ich die verschiedenen Eigenschaften wie coordsoder, bboxaber ich bin verwirrt, welchen Operator ich @, $, []verwenden soll, um darauf zuzugreifen oder sie zu ändern.

jirikadlec2
quelle
1
Da es sich hier wirklich um eine Frage der RSyntax handelt, sind weder das spPaket noch seine Objekte betroffen. Rwird mit einem Tutorial installiert: Beginnen Sie dort mit Ihrer Recherche. Das Web und die Printmedien bieten eine Fülle zusätzlicher Lernressourcen R.
Whuber

Antworten:

21

Räumliche sp-Daten sind S4-Klassenobjekte und bestehen aus Slots (mit @ bezeichnet), die Komponenten der dargestellten räumlichen Feature-Class enthalten (z. B. @data enthält Attribute, @coords enthält Koordinatenpaare usw.). Sie können die Steckplatznamen der obersten Ebene mit slotNames () zurückgeben, dies ist jedoch nicht rekursiv und es werden keine verschachtelten Steckplatznamen für Polygonklassenobjekte zurückgegeben. Jeder Slot kann eine andere Objektklasse enthalten und sollte vor der Bearbeitung mit str () oder class () überprüft werden. Der Slot @data ist immer ein data.frame-Objekt und @coords ist eine Matrix, während @polygons ein Listenobjekt mit zusätzlichen Slots ist (labpt, area, hole, ringDir und coords).

Die verfügbaren Slots und ihre Organisation hängen davon ab, welcher Typ von Feature-Class dargestellt wird. SpatialPointsDataFrame-Objekte sind die grundlegendsten Objekte, wohingegen SpatialPolygonsDataFrame-Objekte (wie oben gezeigt) verschachtelt sind. Bei dieser verschachtelten Struktur, die jedes Polygon darstellt, muss berücksichtigt werden, dass für jedes Listenobjekt (Polygon) so etwas wie sapply verwendet wird.

In diesem Beispiel wird sapply verwendet, um die Fläche für jedes Polygon durch Iteration durch die "Polygone" und dann durch die verschachtelten "Flächen" -Slots zurückzugeben.

sapply(slot(sdat, 'polygons'), function(i) slot(i, 'area')) 

Bei Polygonobjekten können Sie alternativ die Listenindizierung verwenden, da sie als Liste für jedes Polygon gespeichert werden. Im folgenden Beispiel wird das erste Polygon zurückgegeben (was zu einem Klassenobjekt "Polygon" und nicht zu SpatialPolygonsDataFrame führt):

sdat@polygons[[1]]

In neueren Versionen von sp haben die Entwickler in einigen Fällen damit begonnen, den @ data-Slot nicht mehr direkt aufzurufen.

Zum Beispiel, um @data zu indizieren:

sdat@data[sdat@data$att >= 0.5 ,]  

und nun:

sdat[sdat$att >= 0.5 ,]

Wie bereits erwähnt, gilt dies jedoch nicht für die anderen Slots (z. B. Koordinaten, Polygone usw.). Wann [] oder $ verwendet werden, hängt immer noch von der Art der Operation ab. Klammern "[]" können zum Aufrufen eines Namens in einem Datenrahmen verwendet werden, werden jedoch hauptsächlich zum Indizieren verwendet, wohingegen $ speziell zum Aufrufen einer Spalte in einem Datenrahmen verwendet wird. Der Grund, warum ein "indirekter" Aufruf eines Spaltennamens funktioniert, besteht darin, dass die Entwickler Funktionen hinzugefügt haben, die eine rekursive Suche durch das sp-Objekt ermöglichen. Um jedoch Namenskonflikte zu vermeiden (wie in Ihrem Beispiel, wenn x-, y-Spalten in Ihrem Datenrahmen in Konflikt mit den x-, y-Namen in den @ coord-Matrixnamen stehen würden), wird eine interne Konsistenzprüfung durchgeführt, die erklärt, warum dies nur in einigen Fällen funktioniert Instanzen.

Ein praktisches Merkmal ist, dass Sie ein räumliches Objekt über einen Zeilenindex unterteilen können. Hier setze ich die ersten 10 Objekte unter.

sub.sdat <- sdat[1:10,] 

Oder alternativ eine Zufallsstichprobe (n = 10) unter Verwendung eines Zeilenindexvektors.

rs.sdat <- sdat[sample(1:nrow(sdat), 10),]

Das Verständnis der Indizierung und der Verwendung von Klammern ist beim Schreiben von R-Code von großer Bedeutung.

Bearbeiten (24.03.2017): Bitte beachten Sie, dass die einfache Feature-Class (sf) nach dem GeoJSON-Standard wahrscheinlich der neue Standard für räumliche Objekte in R wird. Eine ausführliche Beschreibung dieser Klasse finden Sie im CRAN sf Website Einfache Funktionen für R .

Jeffrey Evans
quelle
Vielen Dank für eine ausführliche Erklärung, was sich hinter den Kulissen abspielt. Es scheint, dass SpatialPointsDataFramenicht nur die @ data-Spalten, sondern auch die @ coords-Spalten mit dem $Operator abgerufen werden können, ohne dass der @ coords-Slot aufgerufen werden muss. So sdat@coords$eastingergibt sich das gleiche Ergebnis wie sdat$easting.
jirikadlec2
Anscheinend rufen Sie eine Spalte in <at> data auf. Dies ist nicht dasselbe wie der <at> -Coords-Slot. Sie werden feststellen, dass Sie beim Aufrufen von colnames (sdat <at> coords) die Matrixspaltennamen zurückgeben: "coords.x1", "coords.x2". Es ist nicht erforderlich, Koordinaten im Datenrahmen und, da dupliziert, eine Taille an Speicher zu halten.
Jeffrey Evans
Nein, ich rufe die Spalte in <at> -Daten nicht auf. Mit Hilfe der SpatialPointsDataFrame von meinem Beispielskript, colnames(locations@coords)kehrt [1] "x" "y"aber colnames(locations@data)kehrt [1] "v1" "v2". Vielleicht hängt das Verhalten davon ab, welche Funktion zum Erstellen des SpatialPointsDataFrame verwendet wurde?
jirikadlec2
Eigentlich habe ich einen Fehler in meinem ersten Kommentar. sdat@coords$eastingfunktioniert nicht, weil sdat @ coords eine Matrix ist. Ist sdat@coords[,"easting"]aber äquivalent zu sdat@coords[,1]und zu sdat$easting.
Jirikadlec2
Eine Einschränkung ist, dass colnames () verwendet wird, um Spaltennamen in einer Matrix zurückzugeben, während names () NULL zurückgibt. Allerdings funktionieren sowohl names () als auch colnames () für ein Datenrahmenobjekt wie <at> data. Der beste Weg, um Daten aus der <at> -Koordinatenmatrix abzurufen, besteht darin, sie zu indizieren: sdat <at> -Koordinaten [, 1] oder nach dem Spaltennamen sdat <at> -Koordinaten [, "coords.x1"], aber wie Sie $ notiert haben funktioniert nicht, da es sich um ein Matrixobjekt handelt.
Jeffrey Evans
4

Sie sollten versuchen str(locations), dies zu klären.

Zum Beispiel sind diese richtig:

property2 <- locations@data$v1
property5 <- locations@coords
property6 <- locations@bbox
property7 <- locations@coords[,"x"]
property8 <- locations@coords[,2]

Und dies property1 <- locations$v1funktioniert, weil es auf den data.frame-Speicherort @data verweist

Guillermo Olmedo
quelle
str(locations)gab mir ein paar gute hinweise. Jetzt verstehe ich, dass @für "Slot einer Klasse" verwendet wird. Aber ich verstehe immer noch nicht, warum property9 <- locations$xfunktioniert, wenn names(locations)keine Spalte mit dem Namenx
jirikadlec2
1
Wenn Sie den SpatialPointDataFrame erstellen, weisen Sie x und y als Koordinatennamen zu. Wenn Sie locations @ coords betrachten, sehen Sie die Matrix mit den Koordinaten. Wenn Sie versuchen, eine neue Spalte in @data mit dem Namen "x" zu erstellen, können Sie dies nicht tun, da sie bereits als Koordinatenname verwendet wird.
Guillermo Olmedo
Ich verstehe immer noch nicht genau, mit welcher Art von "Magie" das SpatialPointsDataFrameObjekt auf die Koordinaten zugreift $. Aber zumindest bin ich jetzt damit wohler. Ich habe den folgenden Code ausgeführt: colnames(locations@coords) <- c("easting","northing") Nachdem ich ihn ausgeführt habe, locations$eastingerhalte ich den x-Koordinatenvektor und locations$northingden y-Koordinatenvektor.
jirikadlec2
Ich denke, in gewisser Weise betrachtet R die zwei Spalten für die Koordinaten als zwei weitere Spalten des Datenrahmens als Teil des SpatialPointsDataFrame. Das ist der Grund, warum Sie eine Spalte mit demselben Namen im @ data-Slot haben können
Guillermo Olmedo
1
Es scheint, dass die Benennung der Spalten in der @coordsMatrix der davon SpatialPointsDataFrameabhängt, wie das SpatialPointsDataFrameObjekt erstellt wurde. Methode eins: coordinates(sdat) <- x ~ yBenennt die Spalten in um "coords.x1", "coords.x2". Methode 2: sdat <- SpatialPointsDataFrame(xy, attributes)Die ursprünglichen Spaltennamen aus der xyMatrix werden beibehalten .
jirikadlec2