【问题标题】:Split a matrix in blocks of size n with offset i (vectorized method)将矩阵拆分为大小为 n 且偏移量为 i 的块(矢量化方法)
【发布时间】:2016-06-19 03:32:28
【问题描述】:

考虑到偏移量o,我想将大小为k x l 的矩阵拆分为大小为n x n 的块(就像Mathematica 的Partition 函数一样)。

例如,给定一个矩阵A

A <- matrix(seq(1:16), nrow = 4, ncol = 4)

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

和块大小 = 3,偏移量 = 1,我想输出四个子矩阵,我将从

A[1:3, 1:3]
A[1:3, 2:4]
A[2:4, 1:3]
A[2:4, 2:4]

如果偏移量等于 2 或 3,则此示例的输出应该只是我从中得到的子矩阵

A[1:3, 1:3]

如何矢量化?

【问题讨论】:

  • 您可以对负数进行索引,尽管这可能因具体情况而异:apply(combn(c(-1, -1, -4, -4), 2), 2, function(x){list(A[x[1], x[2]])})
  • 如果offset == 2我们应该有什么?
  • @Psidom,2 行 2 列的偏移量。在上面示例的 4 x 4 矩阵中,偏移量 2 和 3 都给出了子矩阵 A[1:3, 1:3]
  • 这可能是相似的 - stackoverflow.com/questions/24299171/… - 特别是如果简化到数组部分被删除

标签: r matrix vectorization


【解决方案1】:

可能有更优雅的方式。这是我通过编写一个模拟mathematica Partition 函数的myPartition 函数来做到这一点的方法。首先使用Map沿行轴和列轴构造可能的索引,我们使用seq考虑offset,然后使用purrr中的cross2构造子集的所有可能组合的列表指数。最后使用lapply对矩阵进行子集化,返回子集矩阵列表;

在偏移量123 上的测试结果如下,似乎符合预期:

library(purrr)
ind <- function(k, n, o) Map(`:`, seq(1, k-n+1, by = o), seq(n, k, by = o))

# this is a little helper function that generates subset index according to dimension of the 
# matrix, the first sequence construct the starting point of the subset index with an interval 
# of o which is the offset while the second sequence construct the ending point of the subset index
# use Map to construct vector from start to end which in OP's case will be 1:3 and 2:4. 

myPartition <- function(mat, n, o) {
    lapply(cross2(ind(nrow(mat),n,o), ind(ncol(mat),n,o)), function(i) mat[i[[1]], i[[2]]])
}

# This is basically an lapply. we use cross2 to construct combinations of all subset index
# which will be 1:3 and 1:3, 1:3 and 2:4, 2:4 and 1:3 and 2:4 and 2:4 in OP's case. Use lapply
# to loop through the index and subset.

# Testing case for offset = 1
myPartition(A, 3, 1)

# [[1]]
#      [,1] [,2] [,3]
# [1,]    1    5    9
# [2,]    2    6   10
# [3,]    3    7   11

# [[2]]
#      [,1] [,2] [,3]
# [1,]    2    6   10
# [2,]    3    7   11
# [3,]    4    8   12

# [[3]]
#      [,1] [,2] [,3]
# [1,]    5    9   13
# [2,]    6   10   14
# [3,]    7   11   15

# [[4]]
#      [,1] [,2] [,3]
# [1,]    6   10   14
# [2,]    7   11   15
# [3,]    8   12   16

# Testing case for offset = 2
myPartition(A, 3, 2)
# [[1]]
#      [,1] [,2] [,3]
# [1,]    1    5    9
# [2,]    2    6   10
# [3,]    3    7   11

# Testing case for offset = 3
myPartition(A, 3, 3)
# [[1]]
#      [,1] [,2] [,3]
# [1,]    1    5    9
# [2,]    2    6   10
# [3,]    3    7   11

【讨论】:

    【解决方案2】:

    如何使用base R,其想法是生成大小为n*n 的所有可能的窗口(即winds),同时考虑offset。然后在矩阵A(即perms)中打印winds 元素的所有可能排列。它适用于任何大小为k*lA

    A <- matrix(seq(1:16), nrow = 4, ncol = 4)
    c <- ncol(A); r <- nrow(A)
    offset <- 1; size <- 3
    sq <- seq(1, max(r,c), offset)
    winds <- t(sapply(sq, function(x) c(x,(x+size-1))))
    winds <- winds[winds[,2]<=max(r, c),] # check the range
    if (is.vector(winds)) dim(winds) <- c(1,2) # vector to matrix
    perms <- expand.grid(list(1:nrow(winds), 1:nrow(winds)))
    out=apply(perms, 1, function(x) {
       a11 <- winds[x[1],1];a12 <- winds[x[1],2];a21 <- winds[x[2],1];a22 <- winds[x[2],2]
       if (ifelse(r<c, a12<=r, a22<=c)) { # check the range
           cat("A[", a11, ":", a12, ", ", a21, ":", a22, "]", sep="", "\n")
           print(A[a11:a12, a21:a22])
       }
    })
    
    # A[1:3, 1:3]
         # [,1] [,2] [,3]
    # [1,]    1    5    9
    # [2,]    2    6   10
    # [3,]    3    7   11
    # A[2:4, 1:3]
         # [,1] [,2] [,3]
    # [1,]    2    6   10
    # [2,]    3    7   11
    # [3,]    4    8   12
    # A[1:3, 2:4]
         # [,1] [,2] [,3]
    # [1,]    5    9   13
    # [2,]    6   10   14
    # [3,]    7   11   15
    # A[2:4, 2:4]
         # [,1] [,2] [,3]
    # [1,]    6   10   14
    # [2,]    7   11   15
    # [3,]    8   12   16
    

    对于size=3offset=2offset=3

    # A[1:3, 1:3]
         # [,1] [,2] [,3]
    # [1,]    1    5    9
    # [2,]    2    6   10
    # [3,]    3    7   11
    

    对于offset=2size=2

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多