在R中与等于2D矩阵索引的dist矩阵(1D向量)中的索引

时间:2016-01-19 12:59:16

标签: r matrix vector distance

我们假设我有一个看起来像这样的矩阵,然后将其转换为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 /行的一个元素,因为对角线被移除)。

我如何以后访问向量mdv中的等效元素?所以例如如何在对象m[3,2]中访问等效的mdv(值3)? (不是值,因为可能有重复的值,但是通过索引)相关Q& A解决了dist对象上as.matrix的类似问题,但这对我来说没有(因为我需要处理矢量)。

2 个答案:

答案 0 :(得分:0)

这个功能怎么样:

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的案例。为方便起见,您可以编写另一个函数来处理这种情况。

答案 1 :(得分:0)

拥有lower.tri(, diag = FALSE)距离 - 矢量(“mdv”)你可以(1)find the respective dimensions距离 - 矩阵(“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]]
}

E.g:

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

等...