【问题标题】:Taking the transpose of square blocks in a rectangular matrix r对矩形矩阵 r 中的方块进行转置
【发布时间】:2016-09-28 17:16:39
【问题描述】:

假设我有两个绑定在一起的方阵(实际上更多):

mat = matrix(1:18,nrow=3,ncol=6)

mat
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    4    7   10   13   16
[2,]    2    5    8   11   14   17
[3,]    3    6    9   12   15   18

我想对每个 (3x3) 矩阵进行转置并将它们并排粘在一起,所以结果是:

mat2
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    2    3   10   11   12
[2,]    4    5    6   13   14   15
[3,]    7    8    9   16   17   18

我不想手动执行此操作,因为它是许多矩阵 c 绑定在一起,而不仅仅是 2 个。

我想要一个避免循环或应用的解决方案(这只是循环的包装器)。我需要高效的解决方案,因为这必须运行数万次。

【问题讨论】:

  • 我不知道如何在不循环的情况下执行此操作,因此我没有解决方案...
  • 哈哈,如果你有更好的标题,也请随意编辑。我无法通过搜索找到解决方案,但我什至不确定描述我正在尝试做的事情的准确语言。
  • “真正的”问题中是否有三行,还是有更多行?
  • 真实有5-6个
  • matrix(t(m), nrow=nrow(m))[, c(matrix(1:ncol(m), nrow(m), byrow=T)) ]

标签: r matrix dataframe


【解决方案1】:

这可能会做到:

mat = matrix(1:18,nrow=3,ncol=6)
mat

output <- lapply(seq(3, ncol(mat), 3), function(i) { t(mat[, c((i - 2):i)]) } )
output

do.call(cbind, output)

#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1    2    3   10   11   12
#[2,]    4    5    6   13   14   15
#[3,]    7    8    9   16   17   18

很好奇并计时了这两种方法。 user20650 使用的matrix 方法比我使用的lapply 方法快得多:

library(microbenchmark)

mat = matrix(1:1600, nrow=4, byrow = FALSE)

lapply.function <- function(x) {

     step1 <- lapply(seq(nrow(mat), ncol(mat), nrow(mat)), function(i) {
                     t(mat[, c((i - (nrow(mat) - 1) ):i)])
              } )

     l.output <- do.call(cbind, step1)
     return(l.output)
}

lapply.output <- lapply.function(mat)

matrix.function <- function(x) { 
     m.output <- matrix(t(mat), nrow=nrow(mat))[, c(matrix(1:ncol(mat), nrow(mat), byrow=TRUE)) ] 
}

matrix.output <- matrix.function(mat)

identical(lapply.function(mat), matrix.function(mat))

microbenchmark(lapply.function(mat), matrix.function(mat), times = 1000)

#Unit: microseconds
#                 expr     min      lq      mean  median      uq      max neval
# lapply.function(mat) 735.602 776.652 824.44917 791.443 809.856 2260.834  1000
# matrix.function(mat)  32.298  35.619  37.75495  36.826  37.732   78.481  1000

【讨论】:

    【解决方案2】:

    一种方法是使用矩阵索引

    matrix(t(m), nrow=nrow(m))[, c(matrix(1:ncol(m), nrow(m), byrow=T)) ]
    

    这采用转置矩阵并按所需顺序重新排列列。

    m <- matrix(1:18,nrow=3,ncol=6)
    matrix(t(m), nrow=nrow(m))
    #      [,1] [,2] [,3] [,4] [,5] [,6]
    # [1,]    1   10    2   11    3   12
    # [2,]    4   13    5   14    6   15
    # [3,]    7   16    8   17    9   18
    

    所以我们希望将第 1、3、5 列以及第 2、4 和 6 列放在一起。 一种方法是用

    索引这些
    c(matrix(1:ncol(m), nrow(m), byrow=T))
    #[1] 1 3 5 2 4 6
    

    作为替代方案,您可以使用

    idx <- rep(1:ncol(m), each=nrow(m), length=ncol(m)) ;
    do.call(cbind, split.data.frame(t(m), idx))
    

    尝试新矩阵

    (m <- matrix(1:50, nrow=5))
    #      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    # [1,]    1    6   11   16   21   26   31   36   41    46
    # [2,]    2    7   12   17   22   27   32   37   42    47
    # [3,]    3    8   13   18   23   28   33   38   43    48
    # [4,]    4    9   14   19   24   29   34   39   44    49
    # [5,]    5   10   15   20   25   30   35   40   45    50
    
    matrix(t(m), nrow=nrow(m))[, c(matrix(1:ncol(m), nrow(m), byrow=T)) ]
    #      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    # [1,]    1    2    3    4    5   26   27   28   29    30
    # [2,]    6    7    8    9   10   31   32   33   34    35
    # [3,]   11   12   13   14   15   36   37   38   39    40
    # [4,]   16   17   18   19   20   41   42   43   44    45
    # [5,]   21   22   23   24   25   46   47   48   49    50
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-09
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多