2016-09-18 46 views
4

我想创建一个矩阵,其中包含来自一个数据帧的行与其他行的欧几里得距离。例如,假设我有以下的数据帧:R - 来自两个独立数据帧的距离矩阵

a <- c(1,2,3,4,5) 
b <- c(5,4,3,2,1) 
c <- c(5,4,1,2,3) 
df1 <- data.frame(a,b,c) 

a2 <- c(2,7,1,2,3) 
b2 <- c(7,6,5,4,3) 
c2 <- c(1,2,3,4,5) 
df2 <- data.frame(a2,b2,c2) 

我想创建与每行的DF1 DF2与各行的距离的矩阵。

所以矩阵[2,1]应该是df1 [2,]和df2 [1,]之间的欧氏距离。矩阵[3,2] df [3,]与df2 [2,]之间的距离等。

有没有人知道如何实现?谢谢。

回答

5

也许你可以使用fields包:功能rdist可能会做你想要什么:

rdist:欧氏距离矩阵
说明:由于两套位置计算出所有配对中的欧氏距离矩阵。

> rdist(df1, df2) 
    [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] 4.582576 6.782330 2.000000 1.732051 2.828427 
[2,] 4.242641 5.744563 1.732051 0.000000 1.732051 
[3,] 4.123106 5.099020 3.464102 3.316625 4.000000 
[4,] 5.477226 5.000000 4.358899 3.464102 3.316625 
[5,] 7.000000 5.477226 5.656854 4.358899 3.464102 

类似的是与pdist包的情况下

pdist:观测之间的距离为一个分块矩阵
明计算的另一矩阵X的行和列之间的欧几里德距离矩阵Y.

> pdist(df1, df2) 
An object of class "pdist" 
Slot "dist": 
[1] 4.582576 6.782330 2.000000 1.732051 2.828427 4.242640 5.744563 1.732051 
[9] 0.000000 1.732051 4.123106 5.099020 3.464102 3.316625 4.000000 5.477226 
[17] 5.000000 4.358899 3.464102 3.316625 7.000000 5.477226 5.656854 4.358899 
[25] 3.464102 
attr(,"Csingle") 
[1] TRUE 

Slot "n": 
[1] 5 

Slot "p": 
[1] 5 

Slot ".S3Class": 
[1] "pdist" 

注意:如果你正在寻找行之间的欧几里得范,你可能会想尝试:

a <- c(1,2,3,4,5) 
b <- c(5,4,3,2,1) 
c <- c(5,4,1,2,3) 
df1 <- rbind(a, b, c) 

a2 <- c(2,7,1,2,3) 
b2 <- c(7,6,5,4,3) 
c2 <- c(1,2,3,4,5) 
df2 <- rbind(a2,b2,c2) 

rdist(df1, df2) 

这给:

> rdist(df1, df2) 
     [,1]  [,2]  [,3] 
[1,] 6.164414 7.745967 0.000000 
[2,] 5.099020 4.472136 6.324555 
[3,] 4.242641 5.291503 5.656854 
+0

这看起来很有用,但不是答案。你应该展示如何在问题中的数据上实现答案;所以只有链接的答案在SO上不会很好。 – alistaire

+0

@alistaire感谢您的评论。这是它应该看起来如何? – Diego

+1

是的,那太好了! – alistaire

2

这是从my previous answer here调整。

对于一般n维欧几里得距离,我们可以利用等式(未R,但是代数):

square_dist(b,a) = sum_i(b[i]*b[i]) + sum_i(a[i]*a[i]) - 2*inner_prod(b,a) 

其中总和超过矢量abi=[1,n]的尺寸。这里,ab分别是来自df1df2的一对列。这里的关键是这个方程可以写成df1df2中所有对的矩阵方程。

在代码:

d <- sqrt(matrix(rowSums(expand.grid(rowSums(df1*df1),rowSums(df2*df2))), 
       nrow=nrow(df1)) - 
      2. * as.matrix(df1) %*% t(as.matrix(df2))) 

注:

  1. rowSums计算sum_i(a[i]*a[i])sum_i(b[i]*b[i])用于df1每个abdf2,分别。
  2. expand.grid然后生成df1df2之间的所有对。
  3. 外部的rowSums计算所有这些对的sum_i(a[i]*a[i]) + sum_i(b[i]*b[i])
  4. 此结果然后被重新整形为matrix。请注意,此矩阵的行数是df1的行数。
  5. 然后减去所有对的内积的两倍。这个内积可以写成矩阵乘以df1 %*% t(df2),其中为了清楚起见,我忽略了对矩阵的强制。
  6. 最后,取平方根。

使用此代码与您的数据:

print(d) 
##   [,1]  [,2]  [,3]  [,4]  [,5] 
##[1,] 4.582576 6.782330 2.000000 1.732051 2.828427 
##[2,] 4.242641 5.744563 1.732051 0.000000 1.732051 
##[3,] 4.123106 5.099020 3.464102 3.316625 4.000000 
##[4,] 5.477226 5.000000 4.358899 3.464102 3.316625 
##[5,] 7.000000 5.477226 5.656854 4.358899 3.464102 

注意这个代码将任何n > 1工作。在你的情况下,n=3