2016-04-24 24 views
0

3次元点間のユークリッド距離を計算し、その距離を追加列として追加しようとしています。私はこのように、行をループしてみました:データフレーム内の隣接する行の間で計算を実行

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) 
} 

が、私はエラーを取得:

私は間違っているつもりです
Error in df1$x[i, ] : incorrect number of dimensions 

+0

おそらく 'sqrt(abs(Reduce( ' - '、lapply(df1、function(x)(x-デフォルト= x [1]))^ 2))))'または 'c (abs(Reduce( ' - '、as.data.frame((sapply(df1、diff))^ 2)))))) ' – akrun

答えて

2

主な問題は、あなたが扱っているということですxは、インデックス作成時に配列のようなオブジェクトとして表示されます。私。 x[element]を使用する必要がある場合は、x[row, col]インデックスを使用しています。

結果を挿入する際には、df1$diffにもインデックスを設定する必要があります。ユークリッド距離方程式が間違っています。差を2乗して差し引く必要はありません。

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 

あなたはRは、要素ごとの操作を行うに依存しているため、単一のステップでこれを行うことができ、このかかわらずのためのループを必要としません:

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 

おそらくよ実際の問題が大きい場合は、データフレームが非常に遅いため、df1をマトリックスに強制したいと考えています。

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 

あなたはあなたが元のデータが持っているどのように多くの行を心配する必要はdo't head()tail()を使用して関数にこれをラップすることができます:ここでは

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

ありがとう、私の非常に間違った方法で間違いをキャッチしてくれてありがとう。 –

+1

ありがとうございます。これはループなしで行うことができます。私にもう少し私を与えて、私は簡単なコードを投稿します。 –

0

新しい変数を使用すると、上部またはベクトルの下部のいずれかにNAを追加する必要があるので、あなたのdata.frameより1つの少ない観測を持っている:

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

最初の部分でエラーが発生しました、' myVec < - ... '。私は "df"を "df1"に変更しましたが、エラー "ベクトルのエラー(nrow(df1)):ベクトル:モード '5'のベクトルを作ることができません。 –

+0

@Adam_G私は、控えめな第1ラウンドから「多くの」タイプミスを修正したと思う。 – lmo

1

は別のオプション

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

または

c(0,sqrt(rowSums((sapply(df1, diff))^2))) 
#[1] 0.000000 3.316625 5.196152 7.141428 9.110434 
関連する問題