【问题标题】:Distance matrix from two separate data frames来自两个单独数据帧的距离矩阵
【发布时间】:2017-01-26 10:11:12
【问题描述】:

我想创建一个矩阵,其中包含一个数据帧的行与另一个数据帧的行的欧几里德距离。例如,假设我有以下数据框:

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 中的行的距离。

所以 matrix[2,1] 应该是 df1[2,] 和 df2[1,] 之间的欧式距离。 matrix[3,2] df[3,] 和 df2[2,] 的距离等

有谁知道如何做到这一点?

【问题讨论】:

    标签: r matrix dataframe euclidean-distance


    【解决方案1】:

    也许你可以使用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
    

    【讨论】:

    • 这看起来很有用,但不是答案。您应该展示如何对问题中的数据实施答案;仅链接的答案在 SO 上表现不佳。
    • @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)
    

    总和超过向量ab 对于i=[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 分别为df1df2 中的每个a 计算sum_i(a[i]*a[i])sum_i(b[i]*b[i])
    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 &gt; 1。在你的情况下,n=3

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 2018-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-09
      相关资源
      最近更新 更多