【问题标题】:How to efficiently extract a row or column from a "dist" distance matrix如何有效地从“dist”距离矩阵中提取行或列
【发布时间】:2019-12-08 12:08:22
【问题描述】:

我正在处理 39000+ 个数据点,我正在计算一个点与其中每个点之间的距离,从而产生一个消耗 11GB 的 (39000+)^2 矩阵(我不能在内存中分配它)。

很棒的是,我们有 dist 函数,可以让我将其减少到略低于 6GB。但是现在,我需要计算以 2 为动力的反距离,然后对每一行进行正则化,使它们总和为 1。这是必要的,因为我稍后将矩阵的每一行乘以一个向量并存储这个结果。所以,大矩阵其实是暂时的东西。

我的问题是,如何提取这个dist 矩阵的行?

使用dist(cbind(runif(5),runif(5)) 获得的样本“dist”矩阵

       1    2    3    4    
2   0.47                                                                                                                                  
3   0.63 0.72                                                                                                                             
4   0.79 0.62 0.37                                                                                                                        
5   0.53 0.15 0.62 0.48                                                                                                                   


我正在寻找的是提取整个第一行,例如:

0  0.47  0.63  0.79  0.53

【问题讨论】:

  • 第一行很简单,c(0, d[1:attr(d, "Size")]),但之后就变得更复杂了。可能有人会展示一个非常聪明的解决方案。
  • 感谢您的回答。
  • 也许查看 {bigdist} 包可能会有所帮助 (talegari.github.io/bigdist) -> 将您的数据存储在磁盘上。

标签: r performance matrix distance


【解决方案1】:

求助于f in my old answer here

f <- function (i, j, dist_obj) {
  if (!inherits(dist_obj, "dist")) stop("please provide a 'dist' object")
  n <- attr(dist_obj, "Size")
  valid <- (i >= 1) & (j >= 1) & (i > j) & (i <= n) & (j <= n)
  k <- (2 * n - j) * (j - 1) / 2 + (i - j)
  k[!valid] <- NA_real_
  k
  }

提取单行/列(切片)的辅助函数。

SliceExtract_dist <- function (dist_obj, k) {
  if (length(k) > 1) stop("The function is not 'vectorized'!")
  n <- attr(dist_obj, "Size")
  if (k < 1 || k > n) stop("k out of bound!")
  ##
  i <- 1:(k - 1)
  j <- rep.int(k, k - 1)
  v1 <- dist_obj[f(j, i, dist_obj)]
  ## 
  i <- (k + 1):n
  j <- rep.int(k, n - k)
  v2 <- dist_obj[f(i, j, dist_obj)]
  ## 
  c(v1, 0, v2)
  }

例子

set.seed(0)
( d <- dist(cbind(runif(5),runif(5))) )
#          1         2         3         4
#2 0.9401067                              
#3 0.9095143 0.1162289                    
#4 0.5618382 0.3884722 0.3476762          
#5 0.4275871 0.6968296 0.6220650 0.3368478

SliceExtract_dist(d, 1)
#[1] 0.0000000 0.9401067 0.9095143 0.5618382 0.4275871

SliceExtract_dist(d, 2)
#[1] 0.9401067 0.0000000 0.1162289 0.3884722 0.6968296

SliceExtract_dist(d, 3)
#[1] 0.9095143 0.1162289 0.0000000 0.3476762 0.6220650

SliceExtract_dist(d, 4)
#[1] 0.5618382 0.3884722 0.3476762 0.0000000 0.3368478

SliceExtract_dist(d, 5)
#[1] 0.4275871 0.6968296 0.6220650 0.3368478 0.0000000

完整性检查

as.matrix(d)
#          1         2         3         4         5
#1 0.0000000 0.9401067 0.9095143 0.5618382 0.4275871
#2 0.9401067 0.0000000 0.1162289 0.3884722 0.6968296
#3 0.9095143 0.1162289 0.0000000 0.3476762 0.6220650
#4 0.5618382 0.3884722 0.3476762 0.0000000 0.3368478
#5 0.4275871 0.6968296 0.6220650 0.3368478 0.0000000

注意:Function to extract diagonals readily exists.

【讨论】:

  • 这似乎效果惊人,但需要稍作修正。在SliceExtract_dist 定义上,需要将d[] 更改为dist_obj[]`。非常感谢。
猜你喜欢
  • 2020-09-08
  • 1970-01-01
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
相关资源
最近更新 更多