2017-05-17 1 views
2

Ich habe eine zweiDatenRahmen:Assign Polygon-Datenpunkt in R Datenrahmen

  • points eine Reihe von Punkten mit Koordinaten x, y enthält.
  • poly enthält Koordinaten von zwei Polygonen (ich habe über 100 in Wirklichkeit, aber behalte es hier einfach).

Ich möchte die Datenrahmen hinzufügen können points eine zusätzliche Spalte Area genannt, die den Namen des Polygons enthält der Punkt befindet.

poly <- data.frame(
pol= c("P1", "P1","P1","P1","P1","P2","P2","P2","P2", "P2"), 
x=c(4360, 7273, 7759, 4440, 4360, 8720,11959, 11440,8200, 8720), 
y=c(1009, 9900,28559,28430,1009,9870,9740,28500,28040,9870)) 

points <- data.frame(
     object = c("P1", "P1","P1","P2","P2","P2"), 
     timestamp= c(1485670023468,1485670023970, 1485670024565, 1485670025756,1485670045062, 1485670047366), 
     x=c(6000, 6000, 6050, 10000, 10300, 8000), 
     y=c(10000, 20000,2000,5000,20000,2000)) 

plot(poly$x, poly$y, type = 'l') 
text(points$x, points$y, labels=points$object) 

So im Wesentlichen in diesem Beispiel die ersten zwei Reihen sollte Area= "P1" haben, während der letzte Punkt leer sein sollte, da der Punkt in keinem Polygon enthalten ist.

Ich habe versucht, die Funktion in.out zu verwenden, aber war nicht in der Lage, meinen Datenrahmen wie ich beschrieben zu bauen.

Jede Hilfe wird sehr geschätzt!

Antwort

1

gibt zwar eine for Schleife verwendet, es praktisch ist recht schnell.

library(mgcv) 

x <- split(poly$x, poly$pol) 
y <- split(poly$y, poly$pol) 

todo <- 1:nrow(points) 
Area <- rep.int("", nrow(points)) 
pol <- names(x) 

# loop through polygons 
for (i in 1:length(x)) { 
    # the vertices of i-th polygon 
    bnd <- cbind(x[[i]], y[[i]]) 
    # points to allocate 
    xy <- with(points, cbind(x[todo], y[todo])) 
    inbnd <- in.out(bnd, xy) 
    # allocation 
    Area[todo[inbnd]] <- pol[i] 
    # update 'todo' 
    todo <- todo[!inbnd] 
    } 

points$Area <- Area 

Zwei Gründe für seine Effizienz:

  • for Schleife der Polygone ist durch, keine Punkte. Wenn Sie also 100 Polygone und 100000 Punkte zuweisen möchten, hat die Schleife nur 100 Iterationen, nicht 100000. Innerhalb jeder Iteration wird die Vektorisierungsstärke der C-Funktion in.out ausgenutzt;
  • Es funktioniert auf eine progressive Art und Weise. Sobald ein Punkt zugewiesen wurde, wird er später von der Zuweisung ausgeschlossen. todo Variable steuert die Punkte, die durch die Schleife zugewiesen werden sollen. Wie es geht, reduziert sich das Arbeitssatz.
+1

Das ist perfekt, vielen Dank. Läuft auch sehr schnell auf meiner großen Probe. – Elly

+0

danke für die Klarstellung – Elly

1

Sie könnten die Funktion point.in.polygon von Paket verwenden sp:

points$Area = apply(points, 1, function(p)ifelse(point.in.polygon(p[3], p[4], poly$x[which(poly$pol==p[1])], poly$y[which(poly$pol==p[1])]), p[1], NA)) 

Sie

object timestamp  x  y Area 
1  P1 1.48567e+12 6000 10000 P1 
2  P1 1.48567e+12 6000 20000 P1 
3  P1 1.48567e+12 6050 2000 <NA> 
4  P2 1.48567e+12 10000 5000 <NA> 
5  P2 1.48567e+12 10300 20000 P2 
6  P2 1.48567e+12 8000 2000 <NA> 
+1

Vielen Dank. Es hat gut funktioniert. Vereinbart, dass auf dem größeren Datensatz die Schleife eine schnellere Lösung ist, aber danke für Ihre Hilfe – Elly