水平和垂直拆分一个 numpy 数组

Nic*_*nov 7 python split numpy matrix

将 NumPy 矩阵(二维数组)垂直和水平拆分为相等块的最pythonic 方法是什么?

例如 :

aa = np.reshape(np.arange(270),(18,15)) # a 18x15 matrix
Run Code Online (Sandbox Code Playgroud)

然后是一个“功能”,比如

ab = np.split2d(aa,(2,3))
Run Code Online (Sandbox Code Playgroud)

将产生一个由 6 个矩阵组成的列表,每个矩阵形状为 (9,5)。第一个猜测是结合 hsplit、map 和 vsplit,但是如果要为其定义两个参数,则必须如何应用 mar,例如:

map(np.vsplit(@,3),np.hsplit(aa,2))
Run Code Online (Sandbox Code Playgroud)

Div*_*kar 5

这是留在 NumPy 环境中的一种方法 -

def view_as_blocks(arr, BSZ):
    # arr is input array, BSZ is block-size
    m,n = arr.shape
    M,N = BSZ
    return arr.reshape(m//M, M, n//N, N).swapaxes(1,2).reshape(-1,M,N)
Run Code Online (Sandbox Code Playgroud)

样品运行

1)验证形状的实际大案例:

In [41]: aa = np.reshape(np.arange(270),(18,15))

In [42]: view_as_blocks(aa, (9,5)).shape
Out[42]: (6, 9, 5)
Run Code Online (Sandbox Code Playgroud)

2)手动验证值的小案例:

In [43]: aa = np.reshape(np.arange(36),(6,6))

In [44]: aa
Out[44]: 
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35]])

In [45]: view_as_blocks(aa, (2,3)) # Blocks of shape (2,3)
Out[45]: 
array([[[ 0,  1,  2],
        [ 6,  7,  8]],

       [[ 3,  4,  5],
        [ 9, 10, 11]],

       [[12, 13, 14],
        [18, 19, 20]],

       [[15, 16, 17],
        [21, 22, 23]],

       [[24, 25, 26],
        [30, 31, 32]],

       [[27, 28, 29],
        [33, 34, 35]]])
Run Code Online (Sandbox Code Playgroud)

如果您愿意与其他图书馆合作,scikit-image可以在这里使用,就像这样 -

from skimage.util import view_as_blocks as viewB

out = viewB(aa, tuple(BSZ)).reshape(-1,*BSZ)
Run Code Online (Sandbox Code Playgroud)

运行时测试 -

In [103]: aa = np.reshape(np.arange(270),(18,15))

# @EFT's soln
In [99]: %timeit split_2d(aa, (2,3))
10000 loops, best of 3: 23.3 µs per loop

# @glegoux's soln-1
In [100]: %timeit list(get_chunks(aa, 2,3))
100000 loops, best of 3: 3.7 µs per loop

# @glegoux's soln-2
In [111]: %timeit list(get_chunks2(aa, 9, 5))
100000 loops, best of 3: 3.39 µs per loop

# Proposed in this post
In [101]: %timeit view_as_blocks(aa, (9,5))
1000000 loops, best of 3: 1.86 µs per loop
Run Code Online (Sandbox Code Playgroud)

请注意,我已经使用了(2,3)forsplit_2d并且get_chunks根据他们的定义,他们将其用作块数。在我的情况下view_as_blocks,我有BSZ指示块大小的参数。所以,我(9,5)有。get_chunks2遵循相同的格式view_as_blocks。输出应该在那里表示相同。


EFT*_*EFT 4

您可以使用np.split& np.concatenate,后者允许在一个步骤中进行第二次分割:

def split_2d(array, splits):
    x, y = splits
    return np.split(np.concatenate(np.split(array, y, axis=1)), x*y)

ab = split_2d(aa,(2,3))

ab[0].shape
Out[95]: (9, 5)

len(ab)
Out[96]: 6
Run Code Online (Sandbox Code Playgroud)

这似乎也应该相对简单地推广到 n 维的情况,尽管我还没有完全遵循这个想法。

编辑:

对于单个数组作为输出,只需添加np.stack

np.stack(ab).shape
Out[99]: (6, 9, 5)
Run Code Online (Sandbox Code Playgroud)