【问题标题】:How to fill off-diagonals and ignore diagonals in matrix in R?如何在R中填充非对角线并忽略矩阵中的对角线?
【发布时间】:2020-02-18 19:27:20
【问题描述】:

我正在尝试在 R 中填充一个矩阵,其中最终结果将忽略对角线条目,并且值将填充在对角线周围。我的意思的一个简单示例是,如果我采用如下所示的简单 3x3 矩阵:

ab <- c(1:9)
mat <- matrix(ab,nrow=3,ncol=3)
colnames(mat)<- paste0("x", 1:3)
rownames(mat)<- paste0("y", 1:3)
mat

    x1 x2 x3
y1  1  4  7
y2  2  5  8
y3  3  6  9

我想要实现的是用 0 填充对角线并围绕对角线移动所有其他值。因此,例如,如果我只使用 diag(mat)&lt;-0 会导致:

   x1 x2 x3
y1  0  4  7
y2  2  0  8
y3  3  6  0

然而,我正在寻找的结果是这样的(值围绕对角线缠绕):

   x1 x2 x3
y1  0  3  5
y2  1  0  6
y3  2  4  0

我不担心从矩阵中推出的值(即 7、8、9)。

有什么建议吗?

谢谢

编辑:下面赞成的解决方案似乎已经解决了问题

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    这对于您的示例来说可以。不确定我需要n1n2,如果总是对称的,可以更改为一个值

    # original data
    ab <- c(1:9)
    n1 <- 3
    n2 <- 3
    
    # You could add the 0's to the diagonal, by adding a 0 before every n1 split
    # of the data e.g. 0,1,2,3 & 0,4,5,6 & 0,7,8,9
    split_ab <- split(ab, ceiling((1:length(ab))/n1))
    update_split_ab <- lapply(split_ab, function(x){
      c(0, x)
    }) 
    new_ab <- unlist(update_split_ab)
    
    mat <- matrix(new_ab, nrow=n1, ncol=n2)
    colnames(mat)<- paste0("x", 1:n2)
    rownames(mat)<- paste0("y", 1:n1)
    mat
    
    # turn this in to a function
    
    makeShiftedMatrix <- function(ab=1:9, n1=3, n2=3){
    
      split_ab <- split(ab, ceiling((1:length(ab))/n1))
      update_split_ab <- lapply(split_ab, function(x){
        c(0, x)
      }) 
      new_ab <- unlist(update_split_ab)
    
      mat <- matrix(new_ab, nrow=n1, ncol=n2)
      colnames(mat)<- paste0("x", 1:n2)
      rownames(mat)<- paste0("y", 1:n1)
      mat
      return(mat)
    }
    
    # default
    makeShiftedMatrix()
    
    # to read in original matrix and shift:
    old_mat <- matrix(ab, nrow=n1, ncol=n2)
    makeShiftedMatrix(ab=unlist(old_mat))
    

    【讨论】:

      【解决方案2】:

      你可能需要一个循环:

      n <- 9
      seqs <- seq(1:n)
      mats <- matrix(0, nrow = 3, ncol = 3)
      ind <- 0
      for(i in 1:nrow(mats)){
           for(j in 1:nrow(mats)){
      
               if(i == j) {
                   mats[i,j] <- 0 }
                   else {
                       ind <- ind + 1
                       mats[j,i] <- seqs[ind]
                   }
               }
           }
      

      导致:

      >mats
           [,1] [,2] [,3]
      [1,]    0    3    5
      [2,]    1    0    6
      [3,]    2    4    0
      

      【讨论】:

        【解决方案3】:

        适用于您的示例的一种解决方案是首先声明一个除对角线以外的全为 1 的矩阵:

        M <- 1 - diag(3)
        

        然后用所需的非对角线值替换所有的值

        M[M == 1] <- 1:6
        M
        #      [,1] [,2] [,3]
        # [1,]    0    3    5
        # [2,]    1    0    6
        # [3,]    2    4    0
        

        更复杂的场景(例如,非 0 的对角线系数,或未知数量的非对角线元素)可能需要一些额外的工作。

        【讨论】:

        • 虽然这确实适用于简单的 3x3 示例,但在使用一组值填充 off-diag 时似乎无法正常工作。我已编辑问题以反映您的建议
        • 我不明白为什么它不起作用。是否可以在编辑中粘贴您用于获得错误结果的确切代码?
        • 抱歉,它完全有效...我在测试时使用了错误的值集...当我使用正确的值时,您的方法有效。我将重新编辑问题以反映这一点。谢谢
        • 谢谢,这真的救了我的命@Vincent Guillemot
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-15
        • 2020-02-05
        • 2014-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多