2016-07-07 14 views
2

Ich habe ein Datenframe, das eine Liste von Orten und ihren geographischen Positionen in UTM (Universal Transverse Mercator) -Koordinaten hat.Finden Sie, welche Punkte innerhalb einer gegebenen Entfernung von jedem Punkt sind

Es sieht ungefähr so ​​aus:

Place X_UTM Y_UTM 
    1 574262.0 6140492 
    2 571251.2 6141669 
    3 570841.9 6142535 
    4 570233.8 6141213 
    5 578269.2 6140304 
    6 575067.1 6137444 

I, für jeden Platz (jede Zeile des Datenrahmen) identifizieren wollen, die von den anderen Orten innerhalb eines gegebenen euklidischen Abstandes sind. In diesem Fall möchte ich herausfinden, welche Orte näher als 1 Kilometer sind.

ich so etwas wie dies versucht haben:

foo <- function(x, y) dist(c(x, y), method = "euclidian") < 1000 

, die eine Funktion sein sollte, die die Punkte gibt, die näher als 1000 Meter sind. Dann:

x <- lapply(df(,c(i, x, y)), FUN = foo) 

wo i"Place" ist, x ist "X_UTM" und y ist "Y_UTM". Dies funktioniert überhaupt nicht.

Der Ausgang Ich bin nach sollte wie folgt aussehen (nicht aus den oben angegebenen Zahlen erhalten):

# Place Closest 
#  1 2, 5 
#  2  1 
#  3  NA 
#  4  5 
#  5 1, 4 
#  6  NA 
+0

korrigiert mich wenn ich falsch sein, sollte aber nicht die Abstandsfunktion zwei _points_ annehmen, das heißt zwei x und y zwei Werte? –

+0

Ja. Ich möchte den Abstand zwischen jeder Zeile berechnen. Das sollte sqr ((X_UTM [1] - X_UTM [i])^2 - (Y_UTM [1] - Y_UTM [i])^2) für alle Zeilen sein und dann aufzeichnen, welche [i] weniger als 1000 sind. –

+1

kann du machst nicht 'dst <- as.matrix (dist (d [-1])); diag (dst) <- NA; gelten (dst, 1, Funktion (x) einfügen (die (x <1000), Kollaps = ",")) ' – user20650

Antwort

2

Sie können auch sp::spDists verwenden, um eine Abstandsmatrix zurückzugeben und dann die Elemente jeder Spalte/Zeile zu finden, die Ihre Bedingung erfüllen.

Zum Beispiel:

d <- read.table(text='Place X_UTM  Y_UTM 
1  574261.98 6140492.13 
2  571251.23 6141669.26 
3  570841.92 6142534.86 
4  570233.75 6141212.5 
5  578269.25 6140303.78 
6  575067.07 6137444.36', header=TRUE) 
library(sp) 
i <- apply(spDists(as.matrix(d[, c('X_UTM', 'Y_UTM')])), 2, 
      function(x) paste(which(x < 1000 & x != 0), collapse=', ')) 

data.frame(Place=d$Place, Closest=i) 

## Place Closest 
## 1  1   
## 2  2  3 
## 3  3  2 
## 4  4   
## 5  5   
## 6  6   
+1

funktionieren perfekt. Nur um hinzuzufügen, dass spDist in Paket sp ist. Danke vielmals. –

+0

'dist' wird auch gut funktionieren, wie [hervorgehoben] (http://stackoverflow.com/questions/38246575/how-find-the-elements-of-vector-wich-distance-isless -than-ein-Wert-in-r/38257822? noredirect = 1 # comment63915843_38246575) von @ user20650. Außerdem würde meine Antwort keine zufälligen Punkte zurückgeben, dh alle Punkte mit einem Abstand von Null werden ignoriert. Eine bessere Möglichkeit, "Selbst" zu ignorieren, besteht darin, die Diagonale auf "NA" zu setzen, wie im Kommentar von user20650 erwähnt. – jbaums

0

Ich glaube, Sie zu Kreuz gehen zu müssen, kommen die Platz-Koordinaten. Der Grund dafür ist, dass jedes Paar von Orten die nächsten Nachbarn sein können, und vorausgesetzt, dass Sie keine a priori Informationen haben, die bestimmte Paare ausschließen könnten, müssen Sie alle überprüfen.

Eine Möglichkeit, die Cross-Join von Datenrahmen des Erhaltens df ist es mit sich selbst zu verschmelzen, by = NULL als Parameter in merge Einstellung: ist alles, was Sie tun müssen, um

df.cross <- merge(x = df, y = df, by = NULL) 
df.cross$distance <- apply(df.cross[, c('X_UTM.x', 'X_UTM.y', 'Y_UTM.x', 'Y_UTM.y')], 
     1, 
     function(x) dist(x[1], x[2], x[3], x[4])) 

Jetzt für den Mindestabstand finden jedes Paar Plätze.

+0

Sehr geehrte @Tim Biegeleisen, danke für Ihre Antwort. Ich habe folgendes beim Ausführen des Skripts, das Sie teilen: Fehler in dist (x [1], x [2], x [3], x [4]): ungültige Distanzmethode –

+0

Sie müssen Ihre 'dist'-Funktion neu definieren um zwei x Werte und zwei Werte für zwei kartesische Punkte zu nehmen. –