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

R 用偏移量i将矩阵拆分为大小为n的块(矢量化方法),r,matrix,vectorization,R,Matrix,Vectorization,我想将大小为kxl的矩阵拆分为大小为nxn的块,考虑一组o(就像Mathematica的函数那样) 例如,给定一个矩阵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 如果offset等于2或3,

我想将大小为
kxl
的矩阵拆分为大小为
nxn
的块,考虑一组
o
(就像Mathematica的函数那样)

例如,给定一个矩阵
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
如果offset等于2或3,那么本例的输出应该只是我从中得到的子矩阵

A[1:3, 1:3]

如何将其矢量化?

可能有一种更优雅的方法。下面是通过编写一个模拟mathematica
Partition
函数的
myPartition
函数来实现的。首先使用
Map
沿行轴和列轴构建可能的索引,其中使用
seq
考虑
offset
,然后使用
cross2
from
purrr
构建子集索引的所有可能组合的列表。最后使用
lappy
对矩阵进行子集,并返回子集矩阵列表

偏移量
1
2
3
的测试结果如下所示,其表现似乎与预期相符:

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
库(purrr)

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

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
对于
offset=2
size=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

您可以使用负索引,尽管这可能是特定于大小写的:
apply(combn(c(-1,-1,-4,-4),2),2,function(x){list(A[x[1],x[2]])
如果
offset==2
,我们应该有什么?@Psidom,一个两行两列的偏移量。在上述示例的4 x 4矩阵中,偏移量2和偏移量3都给出了子矩阵
A[1:3,1:3]
,这可能是类似的-特别是如果删除了对阵列部分的简化
# A[1:3, 1:3]
     # [,1] [,2] [,3]
# [1,]    1    5    9
# [2,]    2    6   10
# [3,]    3    7   11
# 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