Ich habe eine SpatialPointsDataFrame
mit einigen zusätzlichen Daten. Ich möchte diese Punkte in einem Polygon extrahieren und gleichzeitig das SPDF
Objekt und die entsprechenden Daten beibehalten .
Bisher hatte ich wenig Glück und habe versucht, eine gemeinsame ID abzugleichen und zusammenzuführen. Dies funktioniert jedoch nur, weil ich Daten mit individuellen IDs gerastert habe.
Hier ist ein kurzes Beispiel, ich suche nach Punkten innerhalb des roten Quadrats.
library(sp)
set.seed(357)
pts <- data.frame(x = rnorm(100), y = rnorm(100), var1 = runif(100), var2 = sample(letters, 100, replace = TRUE))
coordinates(pts) <- ~ x + y
class(pts)
plot(pts)
axis(1); axis(2)
ply <- matrix(c(-1,-1, 1,-1, 1,1, -1,1, -1,-1), ncol = 2, byrow = TRUE)
ply <- SpatialPolygons(list(Polygons(list(Polygon(ply)), ID = 1)))
ply <- SpatialPolygonsDataFrame(Sr = ply, data = data.frame(polyvar = 357))
plot(ply, add = TRUE, border = "red")
Der naheliegendste Ansatz wäre, over
die Daten aus dem Polygon zurückzugeben.
> over(pts, ply)
polyvar
1 NA
2 357
3 357
4 NA
5 357
6 357
Antworten:
Aus der
sp::over
Hilfe:Wenn Sie also Ihre
SpatialPolygonsDataFrame
in konvertieren , erhaltenSpatialPolygons
Sie einen Vektor von Indizes zurück, und Sie können Ihre Punkte aufNA
folgende Werte setzen :Für die Zweifler ist hier der Beweis, dass der Konvertierungsaufwand kein Problem ist:
Zwei Funktionen - zuerst Jeffrey Evans 'Methode, dann mein Original, dann meine gehackte Konvertierung, dann eine Version,
gIntersects
die auf Josh O'Briens Antwort basiert:Für ein reales Beispiel habe ich nun einige zufällige Punkte über den
columbus
Datensatz verteilt:Sieht gut aus
Überprüfen Sie, ob die Funktionen dasselbe tun:
Und 500 Mal für das Benchmarking ausführen:
Meiner Intuition nach ist dies kein großer Aufwand, sondern möglicherweise ein geringerer Aufwand, als alle Zeilenindizes in Zeichen und zurück zu konvertieren oder na.omit auszuführen, um fehlende Werte abzurufen. Was übrigens zu einem anderen Fehlermodus der
evans
Funktion führt ...Wenn eine Zeile des Polygondatenrahmens alle ist
NA
(was vollkommen gültig ist), dann erzeugt die Überlagerung mitSpatialPolygonsDataFrame
für Punkte in diesem Polygon einen Ausgabedatenrahmen mit allenNA
s, derevans()
dann abfällt:ABER
gIntersects
ist schneller, selbst wenn die Matrix gewobbelt werden muss, um Schnittpunkte in R statt in C-Code zu prüfen. Ich vermute, es liegt an denprepared geometry
Fähigkeiten von GEOS, räumliche Indizes zu erstellen - ja,prepared=FALSE
es dauert etwas länger, ungefähr 5,5 Sekunden.Ich bin überrascht, dass es keine Funktion gibt, um die Indizes oder die Punkte direkt zurückzugeben. Als ich vor
splancs
20 Jahren schrieb, hatten die Point-in-Polygon-Funktionen beide ...quelle
sp
Bietet eine kürzere Form zum Auswählen von Features basierend auf der räumlichen Überschneidung gemäß dem OP-Beispiel:ab:
Hinter den Kulissen ist dies eine Abkürzung für
Zu beachten ist, dass es eine
geometry
Methode gibt, die Attribute löscht:over
Ändert das Verhalten, wenn das zweite Argument Attribute enthält oder nicht (dies war die Verwirrung von OP). Dies funktioniert accross alle Spatial * Klassensp
, obwohl einigeover
Methoden erfordernrgeos
, sehen diese Vignette für Details, zB bei mehrfacher Übereinstimmungen für überlappende Polygone.quelle
Sie waren auf dem richtigen Weg mit über. Die Rownamen des zurückgegebenen Objekts entsprechen dem Zeilenindex der Punkte. Sie können Ihren genauen Ansatz mit nur wenigen zusätzlichen Codezeilen implementieren.
quelle
Ist es das was du suchst?
Ein Hinweis zum Bearbeiten: Der Wrapping-Aufruf für
apply()
wird benötigt, damit dies mit beliebigenSpatialPolygons
Objekten funktioniert , die möglicherweise mehr als ein Polygon-Feature enthalten. Vielen Dank an @Spacedman, der mich dazu gebracht hat, zu zeigen, wie dies auf den allgemeineren Fall angewendet werden kann.quelle
ply
mehr als ein Feature vorhanden ist, dagIntersects
für jedes Feature eine Matrix mit einer Zeile zurückgegeben wird. Wahrscheinlich können Sie die Zeilen nach einem WAHREN Wert durchsuchen.apply(gIntersects(pts, ply, byid=TRUE), 2, any)
. Tatsächlich werde ich die Antwort darauf umstellen, da sie auch den Fall eines einzelnen Polygons umfasst.any
. Das ist vielleicht etwas schneller als die Version, die ich gerade getestet habe.obrien
undrowlings2
Lauf Hals und Nacken, mitobrien
vielleicht 2% schneller.pp
sollte ein haben,ID
das angibt, in welchem Polygon die Punkte liegen.Hier ist ein möglicher Ansatz mit dem
rgeos
Paket. Grundsätzlich wird diegIntersection
Funktion verwendet, mit der Sie zweisp
Objekte schneiden können. Durch Extrahieren der IDs der Punkte, die innerhalb des Polygons liegen, können Sie anschließend Ihr OriginalSpatialPointsDataFrame
unter Beibehaltung aller entsprechenden Daten unterteilen. Der Code ist fast selbsterklärend, aber wenn Sie Fragen haben, können Sie diese gerne stellen!quelle
tmp
seinpts.intersect
? Das Parsen der zurückgegebenen Dimnames hängt auch vom undokumentierten Verhalten ab.tmp
, vergessen, es zu entfernen, wenn der Code fertig ist. Sie haben auch Recht mit dem Parsen vondimnames
. Dies war eine schnelle Lösung, um dem Fragesteller eine schnelle Antwort zu geben, und es gibt sicherlich bessere (und universellere) Ansätze, zum Beispiel Ihren :-)Es gibt eine äußerst einfache Lösung für die Verwendung der
spatialEco
Bibliothek.Überprüfen Sie das Ergebnis:
quelle