"扩大"numpy ndarray的好方法?

clw*_*wen 37 python numpy multidimensional-array

是否有很好的方法可以"扩展"numpy ndarray?说我有这样的ndarray:

[[1 2]
 [3 4]]
Run Code Online (Sandbox Code Playgroud)

并且我希望每行通过填充零来包含更多元素:

[[1 2 0 0 0]
 [3 4 0 0 0]]
Run Code Online (Sandbox Code Playgroud)

我知道必须有一些蛮力的方法(比如用零构造一个更大的数组,然后从旧的小数组中复制元素),只是想知道有没有这样做的pythonic方法.尝试numpy.reshape但没有奏效:

import numpy as np
a = np.array([[1, 2], [3, 4]])
np.reshape(a, (2, 5))
Run Code Online (Sandbox Code Playgroud)

Numpy抱怨说: ValueError: total size of new array must be unchanged

Ric*_*ard 52

你可以使用numpy.pad,如下:

>>> import numpy as np
>>> a=[[1,2],[3,4]]
>>> np.pad(a, ((0,0),(0,3)), mode='constant', constant_values=0)
array([[1, 2, 0, 0, 0],
       [3, 4, 0, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

这里np.pad说,"取数组a并在其上方添加0行,在其下方0行,在其左侧为0列,在其右侧为3列.使用constant指定的constant_values" 填充这些列".

  • 作为个人经验,我使用np.pad来动态扩展阵列的大小,并注意到非常差的时间性能.在我改为np.concatenate之后,运行时间减少了~x10次. (6认同)

wim*_*wim 40

有索引技巧r_c_.

>>> import numpy as np
>>> a = np.array([[1, 2], [3, 4]])
>>> z = np.zeros((2, 3), dtype=a.dtype)
>>> np.c_[a, z]
array([[1, 2, 0, 0, 0],
       [3, 4, 0, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

如果这是性能关键代码,您可能更喜欢使用等效代码np.concatenate而不是索引技巧.

>>> np.concatenate((a,z), axis=1)
array([[1, 2, 0, 0, 0],
       [3, 4, 0, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

也有np.resizenp.ndarray.resize,但他们有一定的局限性(由于numpy的方式在内存中勾画出的数据),所以阅读文档字符串中那些人.您可能会发现简单连接更好.

顺便说一句,当我需要这样做时,我通常只是按照你已经提到的基本方式(创建一个零数组并在其中分配较小的数组)来做,我没有看到任何错误!


Pie*_* GM 11

需要明确的是:扩展NumPy阵列没有"好"方法,因为NumPy阵列不可扩展.一旦定义了数组,它在内存中占用的空间,其元素数量和每个元素的大小的组合是固定的,不能更改.您唯一能做的就是创建一个新数组,并用原始数组的元素替换它的一些元素.

为方便起见,有很多函数可用(np.concatenate函数及其np.*stack快捷方式,np.column_stack索引例程np.r_np.c_...),但只有:便利函数.其中一些在C级进行了优化(np.concatenate我认为是其他的),有些则不是.

请注意,您最初的建议是"手动"创建一个大型数组(可能用零填充)并用自己的初始数组填充它,这一点都没有.更复杂的解决方案可能更具可读性.


roo*_*oot 8

你应该使用np.column_stackappend

import numpy as np

p = np.array([ [1,2] , [3,4] ])

p = np.column_stack( [ p , [ 0 , 0 ],[0,0] ] )

p
Out[277]: 
array([[1, 2, 0, 0],
       [3, 4, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

追加似乎更快:

timeit np.column_stack( [ p , [ 0 , 0 ],[0,0] ] )
10000 loops, best of 3: 61.8 us per loop

timeit np.append(p, [[0,0],[0,0]],1)
10000 loops, best of 3: 48 us per loop
Run Code Online (Sandbox Code Playgroud)

与[ np.c_np.hstack追加似乎仍然是最快]的比较:

In [295]: z=np.zeros((2, 2), dtype=a.dtype)

In [296]: timeit np.c_[a, z]
10000 loops, best of 3: 47.2 us per loop

In [297]: timeit np.append(p, z,1)
100000 loops, best of 3: 13.1 us per loop

In [305]: timeit np.hstack((p,z))
10000 loops, best of 3: 20.8 us per loop
Run Code Online (Sandbox Code Playgroud)

并且np.concatenate[比这更快append]:

In [307]: timeit np.concatenate((p, z), axis=1)
100000 loops, best of 3: 11.6 us per loop
Run Code Online (Sandbox Code Playgroud)


ott*_*erb 6

还有类似的方法,如 np.vstack、np.hstack、np.dstack。我喜欢这些而不是 np.concatente,因为它清楚地表明正在“扩展”的维度。

temp = np.array([[1, 2], [3, 4]])
np.hstack((temp, np.zeros((2,3))))
Run Code Online (Sandbox Code Playgroud)

这很容易记住,因为 numpy 的第一个轴是垂直的,所以 vstack 扩展了第一个轴,而第二个轴是水平的,所以 hstack 。


Mit*_*ril 5

一种简单的方法:

# what you want to expand
x = np.ones((3, 3))

# expand to what shape 
target = np.zeros((6, 6))

# do expand
target[:x.shape[0], :x.shape[1]] = x

# print target
array([[ 1.,  1.,  1.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.]])
Run Code Online (Sandbox Code Playgroud)

功能方式:

/sf/answers/2502599921/借用,稍作修改。

def pad(array, reference_shape, offsets=None):
    """
    array: Array to be padded
    reference_shape: tuple of size of narray to create
    offsets: list of offsets (number of elements must be equal to the dimension of the array)
    will throw a ValueError if offsets is too big and the reference_shape cannot handle the offsets
    """

    if not offsets:
        offsets = np.zeros(array.ndim, dtype=np.int32)

    # Create an array of zeros with the reference shape
    result = np.zeros(reference_shape, dtype=np.float32)
    # Create a list of slices from offset to offset + shape in each dimension
    insertHere = [slice(offsets[dim], offsets[dim] + array.shape[dim]) for dim in range(array.ndim)]
    # Insert the array in the result at the specified offsets
    result[insertHere] = array
    return result
Run Code Online (Sandbox Code Playgroud)