3

我编写了一个简短的“for”循环来查找数据帧中每一行与所有其他行之间的最小欧几里德距离(并记录哪一行最接近)。从理论上讲,这避免了与尝试计算非常大矩阵的距离度量相关的错误。然而,虽然没有多少保存在内存中,但对于大型矩阵来说非常非常慢(我的约 150K 行的用例仍在运行)。

我想知道是否有人可以就矢量化我的函数、使用 apply 或类似方法向我提出建议或指出正确的方向。为看似简单的问题道歉,但我仍在努力以矢量化的方式思考。

在此先感谢(以及您的耐心等待)。

require(proxy)

df<-data.frame(matrix(runif(10*10),nrow=10,ncol=10), row.names=paste("site",seq(1:10)))

min.dist<-function(df) {  
 #df for results
 all.min.dist<-data.frame()
 #set up for loop 
 for(k in 1:nrow(df)) {
     #calcuate dissimilarity between each row and all other rows
     df.dist<-dist(df[k,],df[-k,])
     # find minimum distance
     min.dist<-min(df.dist)
     # get rowname for minimum distance (id of nearest point)
     closest.row<-row.names(df)[-k][which.min(df.dist)]
     #combine outputs
     all.min.dist<-rbind(all.min.dist,data.frame(orig_row=row.names(df)[k],
     dist=min.dist, closest_row=closest.row))
    }
 #return results
 return(all.min.dist)
                        } 
 #example
 min.dist(df)
4

2 回答 2

3

这应该是一个好的开始。它使用快速矩阵运算并避免增长的对象构造,两者都在评论中提出。

min.dist <- function(df) {

  which.closest <- function(k, df) {
    d <- colSums((df[, -k] - df[, k]) ^ 2)
    m <- which.min(d)
    data.frame(orig_row    = row.names(df)[k],
               dist        = sqrt(d[m]),
               closest_row = row.names(df)[-k][m])
  }

  do.call(rbind, lapply(1:nrow(df), which.closest, t(as.matrix(df))))
}

如果这仍然太慢,作为建议的改进,您可以一次计算k个点的距离,而不是单个点。k的大小需要在速度和内存使用之间进行折衷。

编辑:另请阅读https://stackoverflow.com/a/16670220/1201032

于 2013-05-10T02:53:30.263 回答
0

通常,内置函数比自己编码更快(因为用 Fortran 或 C/C++ 编码并进行了优化)。

似乎函数 dist {stats} 回答了您的问题:

说明 此函数计算并返回通过使用指定的距离度量计算出的距离矩阵,以计算数据矩阵的行之间的距离。

于 2013-05-10T03:08:40.513 回答