我真的很难在不使用1或2用于循环的情况下复制R代码中的DIST()函数的输出。 (如果您想知道我为什么这样做,那就是我可以进行距离计算,并提高我的R技能 - 因此,请仅涉及R!)

概述:矩阵传递给DIST(),该()计算欧几里得距离行,并输出每行之间距离的完整距离矩阵(例如,第1和50行之间的距离将在DistanceMatrix [1,50]和DistanceMatrix [ 50,1])。快速代码看起来像这样:

distancematrix <- as.matrix(dist(myMatrix, method="euclidean", diag = T, upper = T))

我使用以下代码成功地在R中成功产生了相同的输出:

for (i in 1:nrow(myMatrix)) {
  for (j in 1:nrow(myMatrix)) {
    distancematrix[i, j] <- sum(abs(myMatrix[i,] - myMatrix[j,])) 
  }
}

但是,使用两个嵌套的环比使用DIST()要慢得多。我已经阅读了很多有关使用apply()来优化较慢的循环的信息,但是到目前为止,我还没有让自己围绕它。我相信,只要输出矢量并在最后处理它,至少可以避免使用其中之一。但是,我无法生存一生,如何删除两个循环。

有人有想法吗?

有帮助吗?

解决方案

首先,应该注意的是,您发布的代码实际上并未复制 dist 功能,因为该行:

distancematrix[i, j] <- sum(abs(myMatrix[i,] - myMatrix[j,]))

不计算欧几里得距离;它应该是:

distancematrix[i, j] <- sqrt(sum((myMatrix[i,] - myMatrix[j,]) ^ 2))

这是两个依赖的解决方案 apply. 。它们被简化了,尤其是不利用距离矩阵的对称性(如果考虑的话会导致2倍速度)。首先,生成一些测试数据:

# Number of data points
N <- 2000
# Dimensionality
d <- 10
# Generate data
myMatrix = matrix(rnorm(N * d), nrow = N)

为方便起见,定义:

# Wrapper for the distance function
d_fun <- function(x_1, x_2) sqrt(sum((x_1 - x_2) ^ 2))

第一种方法是组合 applysapply:

system.time(
    D_1 <- 
        apply(myMatrix, 1, function(x_i) 
            sapply(1:nrow(myMatrix), function(j) d_fun(x_i, myMatrix[j, ]))
    )
)

   user  system elapsed 
 14.041   0.100  14.001 

第二个仅使用 apply (但要浏览索引,这些索引是使用 expand.grid):

system.time(
    D_2 <- 
        matrix(apply(expand.grid(i = 1:nrow(myMatrix), j = 1:nrow(myMatrix)), 1, function(I) 
            d_fun(myMatrix[I[["i"]], ], myMatrix[I[["j"]], ])
        )
    )
)

   user  system elapsed 
 39.313   0.498  39.561 

但是,正如预期的那样,两者都比 dist:

system.time(
    distancematrix <- as.matrix(
        dist(myMatrix, method = "euclidean", diag = T, upper = T)
    )
)

   user  system elapsed 
  0.337   0.054   0.388
许可以下: CC-BY-SA归因
scroll top