2016-04-24 5 views
0

Ich versuche, den euklidischen Abstand zwischen 3-dimensionalen Punkten zu berechnen, und füge diesen Abstand als zusätzliche Spalte hinzu. Ich habe versucht, durch die Reihen in einer Schleife, wie folgt aus:Berechnung zwischen benachbarten Zeilen im Datenframe ausführen

df1 <- as.data.frame(list('x'=1:5,'y'=(1:5)^2,'z'=6:10)) 

for (i in 2:nrow(df1)) { 
    df1$diff <- sqrt((df1$x[i,]-df1$x[i-1,])^2 - 
        (df1$y[i,]-df1$y[i-1,])^2 - 
        (df1$z[i,]-df1$z[i-1,])^2) 
} 

aber ich habe den Fehler:

Error in df1$x[i, ] : incorrect number of dimensions 

Wohin gehe ich falsch?

+0

Vielleicht 'sqrt (abs (Reduzieren ('-', lapply (df1, function (x) (x-lag (x, default = x [1]))^2))))' oder 'c (0, sqrt (abs (Reduce ('-', as.data.frame ((sapply (df1, diff))^2))))) ' – akrun

Antwort

2

Das Hauptproblem ist, dass Sie die Behandlung x als Array-ähnliches Objekt beim Indizieren. I.e. Sie verwenden x[row, col] Indizierung, wo Sie x[element] verwenden sollten.

Sie müssen auch beim Einfügen von Ergebnissen in df1$diff indexieren. Und Sie haben die euklidische Abstandsgleichung falsch; Sie müssen die quadrierten Differenzen addieren, nicht subtrahieren.

df1 <- data.frame(list(x = 1:5, y = (1:5)^2, z = 6:10)) 
df1$diff <- NA 

for (i in 2:nrow(df1)) { 
    df1$diff[i] <- with(df1, sqrt((x[i] - x[i-1])^2 + 
           (y[i] - y[i-1])^2 + 
           (z[i] - z[i-1])^2)) 
} 

> df1 
    x y z  diff 
1 1 1 6  NA 
2 2 4 7 3.316625 
3 3 9 8 5.196152 
4 4 16 9 7.141428 
5 5 25 10 9.110434 

Sie brauchen nicht die Schleife dafür aber können Sie auf R verlassen tun Element-für-Element-Operationen und damit dies in einem einzigen Schritt:

df1 <- data.frame(list(x = 1:5, y = (1:5)^2, z = 6:10)) 
df1$diff <- c(NA, sqrt(rowSums((df1[-1, 1:3] - df1[-5, 1:3])^2))) 

df1 

> df1 
    x y z  diff 
1 1 1 6  NA 
2 2 4 7 3.316625 
3 3 9 8 5.196152 
4 4 16 9 7.141428 
5 5 25 10 9.110434 

Sie werden wahrscheinlich möchte dies mit df1 zu einer Matrix gezwungen, wenn Ihr echtes Problem groß ist, da Datenrahmen ziemlich langsam sind.

m1 <- as.matrix(df1[, 1:3]) 
m1 <- cbind(m1, diff = c(NA, sqrt(rowSums((m1[-1, 1:3] - m1[-5, 1:3])^2)))) 

> m1 
    x y z  diff 
[1,] 1 1 6  NA 
[2,] 2 4 7 3.316625 
[3,] 3 9 8 5.196152 
[4,] 4 16 9 7.141428 
[5,] 5 25 10 9.110434 

Sie können diese in eine Funktion wickeln head() und tail() mit so müssen Sie do't kümmern, wie viele Zeilen der Originaldaten hat:

myEuc <- function(x) { 
    if (isdf <- is.data.frame(x)) { 
    x <- data.matrix(x) 
    } 
    dij <- c(NA, sqrt(rowSums((tail(x, -1) - head(x, -1))^2))) 
    x <- cbind(x, diff = dij) 
    if (isdf) { 
    x <- as.data.frame(x) 
    } 
    x 
} 

df1 <- data.frame(list(x = 1:5, y = (1:5)^2, z = 6:10)) 
myEuc(df1) 

> myEuc(df1) 
    x y z  diff 
    1 1 6  NA 
[2,] 2 4 7 3.316625 
[3,] 3 9 8 5.196152 
[4,] 4 16 9 7.141428 
[5,] 5 25 10 9.110434 
+0

Danke und danke, dass du meinen sehr dummen Fehler in der Gleichung aufgefangen hast. –

+1

Danke. Sie können dies ohne eine Schleife tun. Gib mir eine Sekunde und ich poste einfacheren Code. –

0

Ihre neue Variable hat man weniger Beobachtungen als Ihre data.frame, so benötigen Sie eine NA hinzufügen, um entweder die obere oder die untere des Vektors:

df1 <- as.data.frame(list('x'=1:5,'y'=(1:5)^2,'z'=6:10)) 

myVec <- numeric(nrow(df1)) 
myVec[1] <- NA 
for (i in 2:nrow(df1)) { 
myVec[i] <- sqrt((df1[i,"x"]-df1[i-1,"x"])^2 + 
       (df1[i,"y"]-df1[i-1,"y"])^2 + 
       (df1[i,"z"]-df1[i-1,"z"])^2) 
} 

df1$diff <- myVec 
+0

Ich erhalte einen Fehler im ersten Teil,' myVec <- ... '. Ich habe "df" in "df1" geändert, bekomme aber den Fehler "Fehler im Vektor (nrow (df1)): vector: kann keinen Vektor des Modus '5' erzeugen." –

+0

@Adam_G Ich denke, ich habe die "vielen" Tippfehler aus meiner schlampigen ersten Runde behoben. – lmo

1

Hier ist eine weitere Option

sqrt(Reduce('+',lapply(df1, function(x) (x- lag(x, default=x[1]))^2))) 
#[1] 0.000000 3.316625 5.196152 7.141428 9.110434 

Oder

c(0,sqrt(rowSums((sapply(df1, diff))^2))) 
#[1] 0.000000 3.316625 5.196152 7.141428 9.110434 
Verwandte Themen