2017-08-10 3 views
-3

berechnen Wenn ich einen Datenrahmen wie diese:Wie euklidischen Abstand innerhalb der Gruppe in R

ID GroupID X Y 
1 a  772.7778 226.5 
1 a  806.5645 35.3871 
1 a  925.5714 300.9286 
1 b  708.0909 165.5455 
1 b  630.8235 167.4118 
2 a  555.3333 151.875 
2 a  732.8947 462.3158 

Hier ist das Ergebnis, das ich haben will:

ID GroupID X  Y  Distance 
1 a  772.7778 226.5 NA 
1 a  806.5645 35.3871 dist between((772.7778,226.5),(806.5645,35.3871)) 
1 a  925.5714 300.9286 dist between((925.5714,300.9286),(806.5645,35.3871)) 
1 b  708.0909 165.5455 NA 
1 b  630.8235 167.4118 dist between((708.0909,165.5455),(630.8235,167.4118)) 
2 a  555.3333 151.875 NA 
2 a  732.8947 462.3158 dist between((732.8947,462.3158),(555.3333,151.875)) 

Grundsätzlich ist der Abstand innerhalb ID und Gruppen-ID. NA bedeutet hier, dass in jeder Untergruppe (z. B. ID = 1; GroupID = a) der erste Abstand NA ist. Kann mir jemand helfen? Vielen Dank!!!

+2

Was haben Sie bisher versucht? –

+0

'dist' ist nett. – alistaire

+0

@ycw, sie sind numerische Werte, x1 x2 hier nur um zu zeigen, dass sie unterschiedliche Werte sind. – coco

Antwort

2

nie ein dist vor, aber hier ist eine for Schleife, die für Sie arbeiten könnte:

> for(i in 1:nrow(df)) { 
    if(i > 1 && df$GroupID[i] == df$GroupID[i-1]) { 
    df$Distance[i] <- sqrt(((df$X[i] - df$X[i-1])^2) + ((df$Y[i] - df$Y[i-1])^2)) 
    } else { 
    df$Distance[i] <- NA 
    } 
    } 

> df 
    ID GroupID  X  Y Distance 
1 1  a 772.7778 226.5000  NA 
2 1  a 806.5645 35.3871 194.07648 
3 1  a 925.5714 300.9286 290.98957 
4 1  b 708.0909 165.5455  NA 
5 1  b 630.8235 167.4118 77.28994 
6 2  a 555.3333 151.8750  NA 
7 2  a 732.8947 462.3158 357.63325 
+0

Danke für diese Lösung. Aber wenn der euklidische Abstand ist, sollte er etwa so aussehen: sqrt ((df $ X [i] - df $ X [i-1])^2 + (df $ Y [i] - df $ Y [i-1)^2). Und für den NA-Wert habe ich versucht, es auf die erste Entfernung in jeder Untergruppe zu setzen, nicht auf die geraden Zahlenreihen. Kannst du mir helfen, diesen Teil zu ändern? – coco

+0

@ycw, coco - Mein schlechtes. Ich hätte die euklidische Distanz erforschen sollen. Ich nahm einfache Zahlen und wandte mich an den Beispieldatenrahmen, der früher in der Frage gepostet wurde. Ich werde meine Antwort bearbeiten, sobald ich es herausgefunden habe. – Sagar

+0

@ycw, coco - Die aktualisierte "loop" gibt den richtigen Abstand zurück. – Sagar

2

Dies ist eine Lösung mit dplyr und mit dist den euklidischen Abstand zu berechnen:

library(dplyr) 

df <- read.table(text = " 
    ID GroupID X  Y 
    1 a  772.7778 226.5 
    1 a  806.5645 35.3871 
    1 a  925.5714 300.9286 
    1 b  708.0909 165.5455 
    1 b  630.8235 167.4118 
    2 a  555.3333 151.875 
    2 a  732.8947 462.3158", header = T, stringsAsFactors = F) 

df %>% 
    group_by(ID, GroupID) %>% 
    mutate(rows = row_number()) %>% 
    left_join(df, by = c('ID', 'GroupID')) %>% 
    rowwise() %>% 
    mutate(Distance = ifelse(dist(rbind(c(X.x, Y.x), c(X.y, Y.y))) != 0, 
          dist(rbind(c(X.x, Y.x), c(X.y, Y.y))), 
          NA)) %>% 
    filter(rows == 1) %>% 
    select(ID, GroupID, X = X.y, Y= Y.y, Distance) 

##  ID GroupID  X  Y Distance 
## <int> <chr> <dbl> <dbl>  <dbl> 
## 1  1  a 772.7778 226.5000  NA 
## 2  1  a 806.5645 35.3871 194.07648 
## 3  1  a 925.5714 300.9286 169.95735 
## 4  1  b 708.0909 165.5455  NA 
## 5  1  b 630.8235 167.4118 77.28994 
## 6  2  a 555.3333 151.8750  NA 
## 7  2  a 732.8947 462.3158 357.63325 
+0

Danke! Ich habe gerade meine Frage Beschreibung aktualisiert, die NA hier ist nicht für jede gerade Zeile, es ist der Wert für jede Untergruppe, wie id = 1 mit groupid = a. Kannst du mir bitte helfen, dieses Teil zu reparieren? – coco

+0

Ich machte Änderungen basierend auf den neuen Informationen. Lassen Sie mich wissen, ob dies immer noch nicht das ist, was Sie wollen. –

+0

Es gibt einige falsche Daten in der Spalte X, aber immer noch danke für Ihre Hilfe! – coco

1

Warum nicht versuchen, etwas wie:

Aufteilen der Daten auf der Grundlage einer Kombination der IDs, zutreffen eine Abstandsfunktion, und dann ungeteilt?

splitted <- split(dat[,c("X","Y")], paste(dat$ID,dat$GroupID)) 

distances <- lapply(splitted, function(x) { 
if(nrow(x) > 2){ # diag() is useless for <= 2x2 matrix 
    c(NA,diag(as.matrix(dist(x))[,-1])) 
} else { 
    c(NA,dist(x)[1]) 
} 
}) 

dat$distances <- unsplit(distances, paste(dat$ID,dat$GroupID)) 

dat 
ID GroupID  X  Y distances 
1 1  a 772.7778 226.5000  NA 
2 1  a 806.5645 35.3871 194.07648 
3 1  a 925.5714 300.9286 290.98957 
4 1  b 708.0909 165.5455  NA 
5 1  b 630.8235 167.4118 77.28994 
6 2  a 555.3333 151.8750  NA 
7 2  a 732.8947 462.3158 357.63325 

side note: wenn jede Gruppe über 10k Zeilen, wird dist langsam bekommen.

Verwandte Themen