【问题标题】:Index in a dist matrix (1D vector) equivalent to 2D matrix indices, in R在 R 中等效于 2D 矩阵索引的 dist 矩阵(1D 向量)中的索引
【发布时间】:2016-04-24 23:11:55
【问题描述】:

假设我有一个如下所示的矩阵,我将其转换为 dist 类对象(无对角线),然后转换为向量以供以后使用。

m  = matrix(c(0,1,2,3, 1,0,3,4, 2,3,0,5, 3,4,5,0), nrow=4)
#m:
     [,1] [,2] [,3] [,4]
[1,]    0    1    2    3
[2,]    1    0    3    4
[3,]    2    3    0    5
[4,]    3    4    5    0
md = as.dist(m, diag=F)
# md:
   1  2  3
2  1      
3  2  3   
4  3  4  5

mdv = as.vector(md)
# 1 2 3 3 4 5

我可以像往常一样使用[] 访问原始矩阵,并且我可以使用m[ 3+((2-1)*4) ] 轻松访问一维索引(例如,第 3 行,第 2 列)。 dist 对象(和向量)是一维的,但仅由原始矩阵的下三角形组成(并且由于删除了对角线,因此每个原始 col/row 中也缺少一个元素)。

我以后如何访问向量mdv 中的等效元素?所以例如我怎样才能访问对象mdv 中的m[3,2](值3)的等价物? (不是按值,因为可以有重复的值,而是按索引)相关问答解决了 dist 对象上as.matrix 的类似问题,但这对我来说不起作用(因为我需要处理向量)。

【问题讨论】:

  • 您可以使用as.matrixdist 转换为matrix

标签: r matrix vector distance


【解决方案1】:

拥有lower.tri(, diag = FALSE) distances-vector ("mdv") 你可以 (1) find the respective dimensions of the distances-matrix ("m") 和 (2) 通过减去等价的缺失相应地转换 i + (j - 1)*nrow 索引"upper.tri"。

ff = function(x, i, j) 
{
    #assumes that 'x' is a valid distances vector that results in correct 'n'
    n = (1 + sqrt(1 + 8 * length(x))) / 2 

    #make sure i >= j
    ii = pmax(i, j); jj = pmin(i, j)

    #insert 0s to handle 'i == j'
    x = c(unlist(lapply(split(x, rep(seq_len(n - 1), (n - 1):1)), 
                        function(X) c(0, X)), FALSE, FALSE), 0)

    #subtract the missing `upper.tri` elements
    x[(ii + (jj - 1L) * n) - cumsum(0:(n - 1))[jj]]
}

例如:

n = 3
m = matrix(0, n, n); m[lower.tri(m)] = runif(choose(n, 2)); m = m + t(m); x = c(as.dist(m))
m
#          [,1]      [,2]      [,3]
#[1,] 0.0000000 0.3796833 0.5199015
#[2,] 0.3796833 0.0000000 0.4770344
#[3,] 0.5199015 0.4770344 0.0000000
m[cbind(c(2, 2, 3, 1), c(3, 2, 1, 2))]
#[1] 0.4770344 0.0000000 0.5199015 0.3796833
ff(x, c(2, 2, 3, 1), c(3, 2, 1, 2))
#[1] 0.4770344 0.0000000 0.5199015 0.3796833

n = 23
m = matrix(0, n, n); m[lower.tri(m)] = runif(choose(n, 2)); m = m + t(m); x = c(as.dist(m))
i = sample(seq_len(n), 25, TRUE); j = sample(seq_len(n), 25, TRUE)
all.equal(m[cbind(i, j)], ff(x, i, j))
#[1] TRUE

等等……

【讨论】:

    【解决方案2】:

    这个功能怎么样:

    fun <- function(r, c){
      stopifnot(r != c)
      if(r > c) (r-2)*(r-1)/2 + c
      else (c-2)*(c-1)/2 + r
    }
    
    mdv[fun(1, 2)] # 1
    mdv[fun(2, 3)] # 3
    mdv[fun(3, 4)] # 5
    mdv[fun(2, 1)] # 1
    mdv[fun(3, 2)] # 3
    mdv[fun(1, 1)] # stop
    

    r == c 的情况应在申请fun 之前处理。为方便起见,您可以编写另一个函数来处理这种情况。

    【讨论】:

      猜你喜欢
      • 2019-10-20
      • 1970-01-01
      • 2018-06-01
      • 2015-07-30
      • 2016-05-18
      • 1970-01-01
      • 2012-05-28
      • 2010-12-22
      • 1970-01-01
      相关资源
      最近更新 更多