【问题标题】:Create a similarity matrix of integers, using R创建一个整数相似矩阵,使用 R
【发布时间】:2011-04-19 14:55:34
【问题描述】:

我有一个对角线等于 0 且非对角线都等于 1 的矩阵(单位矩阵的逆矩阵):

mat1 <- matrix(c(0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0), 5, 5)

我还有一个向量,它的长度始终与矩阵的暗角相同,并且始终从零开始:

vec1 <- c(0,1,2,3,4)

使用这两个对象,我想创建一个如下所示的矩阵:

mat2 <- matrix(c(0,1,2,3,4,1,0,1,2,3,2,1,0,1,2,3,2,1,0,1,4,3,2,1,0), 5, 5)

     [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    2    3    4
[2,]    1    0    1    2    3
[3,]    2    1    0    1    2
[4,]    3    2    1    0    1
[5,]    4    3    2    1    0

我想要一个可以泛化的操作,例如,如果我有一个 9 x 9 的暗矩阵和一个 0:8 的向量,我可以得到等效的结果。关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    由于 vec1 以零开头,那么您可以这样做:

    MakeMatrix <- function(x){
      n <- length(x)
      id <- abs(rep(1:n,n)-rep(1:n,each=n)) + 1
      matrix(x[id],ncol=n)
    }
    
    MakeMatrix(vec1)
    

    所以没有必要在输入中使用 mat1,因为那实际上是多余的。您可以在函数内构造矩阵。

    诀窍在于提供一系列 id 值以从向量中进行选择,然后将所有内容转换为矩阵。


    编辑:如果你只打算使用序列,你也可以这样做:

    MakeMatrix <- function(n){
      id <- abs(rep(1:n,n)-rep(1:n,each=n))
      matrix(id,ncol=n)
    }
    
    MakeMatrix(7)
    

    【讨论】:

    • 我喜欢这种方法的简单性。非常感谢!
    【解决方案2】:

    下面的解决方案利用upper.trilower.tri来隔离上下三角矩阵。此外,它还利用sequence 来创建所需的向量序列。

    n <- 9
    vec <- (1:n)-1
    m <- matrix(0, n, n)
    m[lower.tri(m, diag=TRUE)] <- vec[sequence(n:1)]  #### Edit
    m <- t(m)
    m[lower.tri(m, diag=TRUE)] <- vec[sequence(n:1)]  #### Edit
    m
    
          [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
     [1,]    0    1    2    3    4    5    6    7    8
     [2,]    1    0    1    2    3    4    5    6    7
     [3,]    2    1    0    1    2    3    4    5    6
     [4,]    3    2    1    0    1    2    3    4    5
     [5,]    4    3    2    1    0    1    2    3    4
     [6,]    5    4    3    2    1    0    1    2    3
     [7,]    6    5    4    3    2    1    0    1    2
     [8,]    7    6    5    4    3    2    1    0    1
     [9,]    8    7    6    5    4    3    2    1    0
    

    【讨论】:

    • +1 表示序列和 lower.tri()。不错,尽管您应该使用 m 作为索引来从输入向量中进行选择。没有什么可以保证 OP 会使用序列作为 vec1...
    • @Joris 好评论。我现在做了一个非常小的修改:使用 sequence() 作为提供向量的索引。这现在应该适用于任何 n 和 vec。
    【解决方案3】:

    怎么样:

    genMat <- function(n){
      mat <- outer(1:n,1:n,"-")%%n
      tmp <- mat[lower.tri(mat)]
      mat <- t(mat)
      mat[lower.tri(mat)] <- tmp
      mat
    }
    
    > genMat(5)
         [,1] [,2] [,3] [,4] [,5]
    [1,]    0    1    2    3    4
    [2,]    1    0    1    2    3
    [3,]    2    1    0    1    2
    [4,]    3    2    1    0    1
    [5,]    4    3    2    1    0
    

    编辑

    对于任意vec1

    genMat2 <- function(vec){
      n <- length(vec)
      mat <- outer(1:n,1:n,"-")%%n
      tmp <- mat[lower.tri(mat)]
      mat <- t(mat)
      mat[lower.tri(mat)] <- tmp
      matrix(vec[mat+1],n,n)
    }
    
    > genMat2(c(0,2,4,3,9))
         [,1] [,2] [,3] [,4] [,5]
    [1,]    0    2    4    3    9
    [2,]    2    0    2    4    3
    [3,]    4    2    0    2    4
    [4,]    3    4    2    0    2
    [5,]    9    3    4    2    0
    

    编辑 2 事实上,没有必要使用模数然后玩矩阵,abs 可以很好地使原始矩阵定义成为 1-liner:

    abs(outer(1:n,1:n,"-"))
    

    所以,

    genMat <- function(n){
      abs(outer(1:n,1:n,"-"))
    }
    

    genMat2 <- function(vec){
      n <- length(vec)
      matrix(vec[abs(outer(1:n,1:n,"-"))+1],n,n)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 2018-08-10
      • 2020-03-21
      • 1970-01-01
      • 2021-01-09
      • 2017-06-13
      相关资源
      最近更新 更多