给定一个m x n矩阵我想把它分成a x a任意偏移的矩形(a = 3或a = 4)矩阵(最小偏移= 1,最大偏移=块大小),就像Mathematica的Partition函数一样:
例如,给定的4×4矩阵A状
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Run Code Online (Sandbox Code Playgroud)
如果我给3 x 3块并且offset = 1,我想获得4个矩阵:
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
Run Code Online (Sandbox Code Playgroud)
如果矩阵A是A = np.arange(1, 37).reshape((6,6)),我使用3 x 3块,偏移= 3,我想要输出块:
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
Run Code Online (Sandbox Code Playgroud)
我很好,矩阵A是一个列表列表,我认为我不需要NumPy的功能.令我感到惊讶的是,既array_split没有numpy.split开箱即用也没有提供这种偏移选项,是否可以通过切片在纯Python中编写代码更直接,还是应该研究NumPy的步伐?我希望代码高度清晰.
正如你所暗示的,有一种方法可以做到这一点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]]])
Run Code Online (Sandbox Code Playgroud)
跨步的一个问题是它是高级的,并且很难向没有太多麻木经验的人解释。我没有经过太多的尝试和错误就想出了这个表格,但我已经在这里闲逛太久了。:) )。
但这个迭代解决方案更容易解释:
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]])]
Run Code Online (Sandbox Code Playgroud)
可以将其转换为数组np.array(alist)。如果更清楚的话,使用这个并没有什么问题。
关于该方法需要记住的一件事as_strided是,它是一种视图,对 的更改M可能会更改A,并且 中的一个位置的更改M可能会修改 中的多个位置M。但这种重塑M可能会将其变成副本。因此,总的来说,从 读取值并将其用于和 等M计算会更安全。现场变化可能是不可预测的。summean
迭代解决方案会在各处生成副本。
迭代解决方案用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)])
Run Code Online (Sandbox Code Playgroud)
和都是构建用于索引块的向量对的简单方法ix_:ogrid
In [970]: np.ogrid[0:3, 0:3]
Out[970]:
[array([[0],
[1],
[2]]), array([[0, 1, 2]])]
Run Code Online (Sandbox Code Playgroud)
相同的事情,但是slice对象:
np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(2) for j in range(2)])
Run Code Online (Sandbox Code Playgroud)
其列表版本将具有view与解决方案类似的行为as_strided(列表的元素是视图)。
对于具有非重叠块的 6x6,请尝试:
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]]])
Run Code Online (Sandbox Code Playgroud)
假设您想要连续的块,内部切片/范围不会改变,只是外部i和外部的步进j
In [1017]: np.arange(0,6,3)
Out[1017]: array([0, 3])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
204 次 |
| 最近记录: |