在R中从距离矩阵中提取对角线

4
我想知道如何从距离矩阵中提取第一对角线的值。
例如:
> mymatrix
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    6    4
[4,]    8    6

> dist(mymatrix)

         1        2        3
2 2.828427                  
3 5.385165 3.000000         
4 8.062258 5.385165 2.828427

我想在一个向量中获取这些值:2.828427、3.000000、2.828427

谢谢!


2
可能是这个的重复问题。 - akrun
2个回答

14

一个解决方法是将 dist 对象转换为 matrix,然后提取行索引比列索引大一的元素:

一个解决方法是将 dist 对象转换为 matrix,然后提取行索引比列索引大一的元素:

mat = as.matrix(dist(mymatrix))
mat[row(mat) == col(mat) + 1]
# [1] 2.828427 3.000000 2.828427

2

这是一种看似复杂但极其高效的方法,用于提取“dist”矩阵的第d个次对角线。

subdiag <- function (dist_obj, d) {
  if (!inherits(dist_obj, "dist")) stop("please provide a 'dist' object!")
  n <- attr(dist_obj, "Size")
  if (d < 1 || d > (n - 1)) stop(sprintf("'d' needs be between 1 and %d", n - 1L))
  j_1 <- c(0, seq.int(from = n - 1, by = -1, length = n - d - 1))
  subdiag_ind <- d + cumsum(j_1)
  dist_obj[subdiag_ind]
  }

请参见R - 如何从距离矩阵中获取匹配元素的行和列下标,了解“dist”对象的紧凑存储细节。在此函数内部,“j_1”是第“(j-1)”列中“X”的数量。cumsum提供主对角线的一维索引(其值均为零)。进一步通过d进行偏移,可得到第d个次对角线的一维索引。
set.seed(0)
x <- dist(matrix(runif(10), 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

subdiag(x, 1)
#[1] 0.9401067 0.1162289 0.3476762 0.3368478

lapply(1:4, subdiag, dist_obj = x)
#[[1]]
#[1] 0.9401067 0.1162289 0.3476762 0.3368478
#
#[[2]]
#[1] 0.9095143 0.3884722 0.6220650
#
#[[3]]
#[1] 0.5618382 0.6968296
#
#[[4]]
#[1] 0.4275871

适用于大型“dist”矩阵的良好性能。

## mimic a "dist" object without actually calling function `dist`
n <- 2000
x <- structure(numeric(n * (n - 1) / 2), class = "dist", Size = n)

library(bench)
bench::mark("Psidom" = {mat = as.matrix(x); mat[row(mat) == col(mat) + 1]},
            "zheyuan" = subdiag(x, 1))
## A tibble: 2 x 14
#  expression      min     mean  median      max `itr/sec` mem_alloc  n_gc n_itr
#  <chr>      <bch:tm> <bch:tm> <bch:t> <bch:tm>     <dbl> <bch:byt> <dbl> <int>
#1 Psidom        553ms    553ms   553ms 552.74ms      1.81   251.8MB     5     1
#2 zheyuan       106µs    111µs   108µs   3.85ms   9045.      62.7KB     2  4519
## ... with 5 more variables: total_time <bch:tm>, result <list>, memory <list>,
##   time <list>, gc <list>

subdiag 的速度快了5120倍(553毫秒/108微秒),且内存使用效率提高了4112倍(251.8MB/62.7KB)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接