【问题标题】:Diagonal of a 3D array3D 阵列的对角线
【发布时间】:2016-05-10 22:47:03
【问题描述】:

如何从 R 中的三维数组中提取“对角线”?对于矩阵(二维数组),可以使用diag(...) 函数。类似地,给定一个 N x N x M 数组,一个自然的操作是通过从每个 N x N 切片中获取对角线并将其作为矩阵返回来将其转换为 N x M 矩阵。

使用循环很容易做到这一点,但这不是惯用的 R 并且速度很慢。另一种可能性是使用稍微复杂的索引(请参阅我自己对这个问题的回答),但它有点难以阅读。还有哪些其他选择?有标准的 R 方法吗?

【问题讨论】:

    标签: r multidimensional-array


    【解决方案1】:

    虽然我不喜欢用“3d.diagonal”这个词来表示这个结果,但可以通过这个简单的函数(直到恒等模转置)来实现:

    arr <- array(1:27,c(3,3,3)  )
    apply(arr, 3, function(x) x[row(x)==col(x)] )
    # returns same value as diag.3d (arr)
         [,1] [,2] [,3]
    [1,]    1   10   19
    [2,]    5   14   23
    [3,]    9   18   27
    

    我认为“真正的对角线”应该是arr[ cbind(1:3,1:3,1:3) ]

    【讨论】:

      【解决方案2】:

      一种可能的方法是使用索引,其中索引是具有三列的矩阵。例如:

      diag.3d <- function(A) {
        # Expect a N x N x M array
      
        stopifnot(length(dim(A)) == 3)
        n <- nrow(A)
        stopifnot(n == ncol(A))
        m <- dim(A)[3]
      
        IXS <- cbind(1:n, 1:n, rep(1:m, each = n))
        cn <- colnames(A)
        rn <- dimnames(A)[[3]]
        matrix(A[IXS], ncol = n, byrow = T, dimnames = list(rn, cn))
      }
      

      虽然索引(在变量 IXS 中)似乎难以阅读。

      【讨论】:

        【解决方案3】:

        创建一个数组并用一些值填充它:

        > a=array(0,c(10,10,5))
        > for (i in 1:10) for (j in 1:10) for (k in 1:5) a[i,j,k]=100*i+10*j+k-111
        

        运行apply函数:

        > apply(a,3,diag)
              [,1] [,2] [,3] [,4] [,5]
         [1,]    0    1    2    3    4
         [2,]  110  111  112  113  114
         [3,]  220  221  222  223  224
         [4,]  330  331  332  333  334
         [5,]  440  441  442  443  444
         [6,]  550  551  552  553  554
         [7,]  660  661  662  663  664
         [8,]  770  771  772  773  774
         [9,]  880  881  882  883  884
        [10,]  990  991  992  993  994
        

        【讨论】:

          【解决方案4】:

          各种对角线:

          A = array(1:12, c(2, 2, 3))
          
          apply(A, 1, diag)
          #     [,1] [,2]
          #[1,]    1    2
          #[2,]    7    8
          apply(A, 2, diag)
          #     [,1] [,2]
          #[1,]    1    3
          #[2,]    6    8
          apply(A, 3, diag)
          #     [,1] [,2] [,3]
          #[1,]    1    5    9
          #[2,]    4    8   12
          

          【讨论】:

            【解决方案5】:

            另一种方法是使用 2 维矩阵对 3 维数组进行子集化:

            a <- array(1:100,dim = c(5,5,4))
            ref <- cbind(1:5,1:5,rep(1:4,each= 5))
            a[ref]
            

            输出是向量而不是矩阵。在我的电脑上它比apply() 效率更高,你也可以填充对角线值。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-11-12
              相关资源
              最近更新 更多