给定value
矩阵我想将其拆分为方形m x n
(a = 3或a = 4)任意偏移矩阵(最小偏移= 1,最大偏移=块大小),如Mathematica的Partition
函数确实:
例如,给定一个4 x 4矩阵a x a
,如
A
如果我给3 x 3块并且offset = 1,我想得到4个矩阵:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
如果矩阵1 2 3
5 6 7
9 10 11
2 3 4
6 7 8
10 11 12
5 6 7
9 10 11
13 14 15
6 7 8
10 11 12
14 15 16
是A
并且我使用3 x 3块且偏移= 3,我想要输出块:
A = np.arange(1, 37).reshape((6,6))
我很好,矩阵A是一个列表列表,我认为我不需要NumPy的功能。令我感到惊讶的是1 2 3
7 8 9
3 14 15
4 5 6
10 11 12
16 17 18
19 20 21
25 26 27
31 32 33
22 23 24
28 29 30
34 35 36
和array_split
都没有提供开箱即用的偏移选项,使用切片在纯Python中编码是否更直接,或者我应该看看NumPy的步伐?我希望代码清晰易读。
答案 0 :(得分:3)
正如您所提示的,有一种方法可以使用strides
In [900]: M = np.lib.stride_tricks.as_strided(A, shape=(2,2,3,3), strides=(16,4,16,4))
In [901]: M
Out[901]:
array([[[[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]],
[[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]]],
[[[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]],
[[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]]]])
In [902]: M.reshape(4,3,3) # to get it in form you list
Out[902]:
array([[[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]],
[[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]],
[[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]],
[[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]]])
步伐的一个问题是,它是先进的,并且很难向没有多少经验的人解释。我想出了没有太多试验和错误的表格,但我已经在这里闲逛太久了。 :))。
但是这个迭代解决方案更容易解释:
In [909]: alist=[]
In [910]: for i in range(2):
...: for j in range(2):
...: alist.append(A[np.ix_(range(i,i+3),range(j,j+3))])
...:
In [911]: alist
Out[911]:
[array([[ 1, 2, 3],
[ 5, 6, 7],
[ 9, 10, 11]]),
array([[ 2, 3, 4],
[ 6, 7, 8],
[10, 11, 12]]),
array([[ 5, 6, 7],
[ 9, 10, 11],
[13, 14, 15]]),
array([[ 6, 7, 8],
[10, 11, 12],
[14, 15, 16]])]
可以将其转换为np.array(alist)
的数组。如果它更清楚,使用它没有任何问题。
有关as_strided
方法的一点要注意的是,它是一个视图,对M
的更改可能会更改A
,并且{{1}中的一个位置发生更改可以修改M
中的几个地方。但重塑M
可能会将其变成副本。总的来说,从M
读取值更安全,并将其用于M
和sum
等计算。在适当的位置,更改可能无法预测。
迭代解决方案可以生成副本。
使用mean
代替np.ogrid
的迭代解决方案(否则相同的想法):
np.ix_
np.array([A[np.ogrid[i:i+3, j:j+3]] for i in range(2) for j in range(2)])
和ix_
只是构建索引块的矢量对的简单方法:
ogrid
同样的事情,但In [970]: np.ogrid[0:3, 0:3]
Out[970]:
[array([[0],
[1],
[2]]), array([[0, 1, 2]])]
个对象:
slice
此列表版本的行为与np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(2) for j in range(2)])
解决方案类似view
行为(列表的元素是视图)。
对于具有非重叠块的6x6,请尝试:
as_strided
假设你想要连续的块,内部切片/范围不会改变,只有外部In [1016]: np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(0,6,3) for j i
...: n range(0,6,3)])
Out[1016]:
array([[[ 1, 2, 3],
[ 7, 8, 9],
[13, 14, 15]],
[[ 4, 5, 6],
[10, 11, 12],
[16, 17, 18]],
[[19, 20, 21],
[25, 26, 27],
[31, 32, 33]],
[[22, 23, 24],
[28, 29, 30],
[34, 35, 36]]])
和i
的步进
j