使用填充堆叠不同长度的 Numpy 数组

Jse*_*mol 1 python numpy

a = np.array([1,2,3])
b = np.array([4,5])

l = [a,b]
Run Code Online (Sandbox Code Playgroud)

我想要一个stack_padding这样的功能:

assert(stack_padding(l) == np.array([[1,2,3],[4,5,0]])
Run Code Online (Sandbox Code Playgroud)

在 numpy 中是否有标准的实现方式

编辑:l可能有更多的元素

sac*_*cuL 5

我认为itertools.zip_longestwithfill_value=0可以为你工作:

import itertools

a = np.array([1,2,3])
b = np.array([4,5])

l = [a,b]

def stack_padding(l):
    return np.column_stack((itertools.zip_longest(*l, fillvalue=0)))

>>> stack_padding(l)
array([[1, 2, 3],
       [4, 5, 0]])
Run Code Online (Sandbox Code Playgroud)

  • `column_stack` 是没有添加维度的 `dstack` (2认同)

小智 2

如果您不想使用itertoolsand column_stacknumpy.ndarray.resize也可以完美完成这项工作。正如 jtweeder 所提到的,您只需要知道每行的结果大小。使用的优点resizenumpy.ndarray在内存中是连续的。当每行大小差异很大时,调整大小会更快。两种方法之间的性能差异是显而易见的。

import numpy as np
import timeit
import itertools

def stack_padding(it):

    def resize(row, size):
        new = np.array(row)
        new.resize(size)
        return new

    # find longest row length
    row_length = max(it, key=len).__len__()
    mat = np.array( [resize(row, row_length) for row in it] )

    return mat

def stack_padding1(l):
    return np.column_stack((itertools.zip_longest(*l, fillvalue=0)))


if __name__ == "__main__":
    n_rows = 200
    row_lengths = np.random.randint(30, 50, size=n_rows)
    mat = [np.random.randint(0, 100, size=s) for s in row_lengths]

    def test_stack_padding():
        global mat
        stack_padding(mat)

    def test_itertools():
        global mat
        stack_padding1(mat)

    t1 = timeit.timeit(test_stack_padding, number=1000)
    t2 = timeit.timeit(test_itertools, number=1000)
    print('With ndarray.resize: ', t1)
    print('With itertool and vstack: ', t2)
Run Code Online (Sandbox Code Playgroud)

resize方法在上面的比较中获胜:

>>> With ndarray.resize:  0.30080295499647036
>>> With itertool and vstack:  1.0151802329928614
Run Code Online (Sandbox Code Playgroud)