首页 > 解决方案 > R中矩阵对象之间的Dist函数

问题描述

我有一个非常简单的问题。

给定一个由 表示的 N 维点(例如,一个向量,其中每个元素代表一个维)x和一个由 表示的 MxN 维矩阵(或一组具有 N 维的 M 点!)y

set.seed(999)
data <- matrix(runif(1100), nrow = 11, ncol = 10)

x <- data[1, ]
y <- data[2:nrow(data), ]

我想计算x每个点之间的距离度量y。我知道这样做的一个简单方法是:

distances <- dist(rbind(x, y))

但是,我认为这对于这种特定情况不是很有效,原因如下:

  1. 我需要使用 rbind,这非常耗费内存。
  2. dist计算每个点之间的距离,但我只对其中的 10 个距离感兴趣,或者只是xy. 我对y点之间的内部距离不感兴趣。
  3. 因为 (2) 我需要手动选择 dist 矩阵的最后一行来获得我实际需要的距离。

我想到的一种可能的解决方案是手动循环应用距离测量y

distances <- apply(y, MARGIN = 1, function(a, b = x) {
   sqrt(sum((a - b)^2))
})

但是,当对这两种方法进行计时时,我得到:

func1 <- function(x, y) {
  apply(y, MARGIN = 1, function(a, b = x) {
    sqrt(sum((a - b)^2))
  })
}

func2 <- function(x, y) {
  dist(rbind(x, y))
}

microbenchmark::microbenchmark(
  func1(x, y),
  func2(x, y)
)

Unit: microseconds
        expr    min     lq     mean median      uq      max neval
 func1(x, y) 29.602 30.450 61.21791 31.301 32.3510 2916.101   100
 func2(x, y) 15.101 15.801 28.55304 17.201 17.7015 1143.001   100

所以我的问题是:有没有办法比使用更快地解决这个问题dist

标签: r

解决方案


一种选择dapply来自collapse

 library(collapse)
 func3 <- function(x, y) {
     dapply(y, function(a, b = x) {
             sqrt(sum((a-b)^2))
          }, MARGIN = 1)
  }

或者可以使用vapply

func4 <- function(x, y) {
  vapply(seq_len(nrow(y)), function(i, b = x) sqrt(sum((y[i,]-b)^2)), numeric(1))
 }

或者可以复制向量并rowSums在减去后使用

func7 <- function(x, y) sqrt(rowSums((y-x[col(y)])^2))
microbenchmark::microbenchmark(func1(x, y), func3(x, y), func4(x, y), func7(x, y))
#Unit: microseconds
#        expr    min      lq     mean  median      uq      max neval cld
# func1(x, y) 37.605 39.7475 61.17471 40.7595 42.1865 1955.888   100   a
# func3(x, y) 22.212 23.5945 68.63660 24.8320 25.8670 4333.933   100   a
# func4(x, y) 21.089 22.7930 24.11542 23.5945 24.2315   58.050   100   a
# func7(x, y)  7.731  8.9135 44.45935 10.0615 10.9500 3415.959   100   a

推荐阅读