使用偏移量i(矢量化方法)拆分大小为n的块中的矩阵

时间:2016-06-19 03:32:28

标签: r matrix vectorization

我想将大小为k x l的矩阵拆分为大小为n x n的块,考虑到o(就像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]

如果offset等于2或3,则此示例的输出应该只是我从

获得的子矩阵
A[1:3, 1:3]

如何对此进行矢量化?

2 个答案:

答案 0 :(得分:3)

可能有更优雅的方式。这是我通过编写模拟mathematica myPartition函数的Partition函数来实现的。首先使用Map在行和列轴上构建可能的索引,我们使用seq来考虑offset,然后使用cross2中的purrr来构建子集索引的所有可能组合的列表。最后使用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

答案 1 :(得分:2)

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

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