有没有很好的方法可以“扩展”numpy ndarray?说我有这样的ndarray:
[[1 2]
[3 4]]
我希望每行通过填充零来包含更多元素:
[[1 2 0 0 0]
[3 4 0 0 0]]
我知道必须有一些蛮力的方法(比如用零构造一个更大的数组,然后从旧的小数组中复制元素),只是想知道有没有这样做的pythonic方法。试过numpy.reshape
但没有效果:
import numpy as np
a = np.array([[1, 2], [3, 4]])
np.reshape(a, (2, 5))
Numpy抱怨:ValueError: total size of new array must be unchanged
答案 0 :(得分:48)
您可以使用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]])
这里np.pad
说,"取数组a
并在其上方添加0行,在其下方0行,左侧为0列,右侧为3列它。使用constant
"。
constant_values
填写这些列
答案 1 :(得分:39)
索引技巧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]])
如果这是性能关键代码,您可能更喜欢使用等效的np.concatenate
而不是索引技巧。
>>> np.concatenate((a,z), axis=1)
array([[1, 2, 0, 0, 0],
[3, 4, 0, 0, 0]])
还有np.resize
和np.ndarray.resize
,但它们有一些限制(由于numpy在内存中放置数据的方式)所以请阅读那些文档字符串。您可能会发现简单连接更好。
顺便说一句,当我需要这样做时,我通常只是按照你已经提到的基本方式(创建一个零数组并在其中分配较小的数组)来做,我没有看到任何错误接着就,随即!
答案 2 :(得分:10)
需要明确的是:扩展NumPy阵列没有“好”的方法,因为NumPy阵列不可扩展。一旦定义了数组,它在内存中占用的空间,其元素数量和每个元素的大小的组合是固定的,不能更改。你唯一能做的就是创建一个新数组并用原始数组的元素替换它的一些元素。
为方便起见,我们提供了许多功能(np.concatenate
功能及其np.*stack
快捷方式,np.column_stack
,索引例程np.r_
和np.c_
。 ..),但只有:便利功能。其中一些在C级优化(np.concatenate
和其他我认为),有些则不是。
请注意,您最初的建议是“手动”创建一个大型数组(可能用零填充),然后自己用初始数组填充它。更复杂的解决方案可能更具可读性。
答案 3 :(得分:8)
您应该使用np.column_stack
或append
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]])
Append似乎更快了:
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
与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
和np.concatenate
[比append
更快一点:
In [307]: timeit np.concatenate((p, z), axis=1)
100000 loops, best of 3: 11.6 us per loop
答案 4 :(得分:4)
# 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.]])
从https://stackoverflow.com/a/35751427/1637673借用,稍作修改。
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
答案 5 :(得分:2)
也有类似的方法,如np.vstack,np.hstack,np.dstack。我喜欢np.concatente这些,因为它清楚地说明了什么样的维度"扩展"。
temp = np.array([[1, 2], [3, 4]])
np.hstack((temp, np.zeros((2,3))))
它很容易记住,因为numpy的第一个轴是垂直的,所以vstack扩展第一个轴,第二个轴是水平的,所以hstack。