python如何用零填充numpy数组

问题描述:

我想知道如何用numpy 1.5.0版使用python 2.6.6填充二维numpy数组。抱歉!但这些是我的限制。所以我不能使用np.pad。例如,我想用零填充a,使其形状匹配b。为什么我想这样做的原因是,所以我可以做的:python如何用零填充numpy数组

b-a 

这样

>>> a 
array([[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.]]) 
>>> b 
array([[ 3., 3., 3., 3., 3., 3.], 
     [ 3., 3., 3., 3., 3., 3.], 
     [ 3., 3., 3., 3., 3., 3.], 
     [ 3., 3., 3., 3., 3., 3.]]) 
>>> c 
array([[1, 1, 1, 1, 1, 0], 
     [1, 1, 1, 1, 1, 0], 
     [1, 1, 1, 1, 1, 0], 
     [0, 0, 0, 0, 0, 0]]) 

我认为这样做是追加的唯一途径,然而,这似乎是相当难看。有没有更清洁的解决方案可能使用b.shape

编辑, 谢谢MSeiferts的回答。我不得不把它清理干净了一下,这是我得到了什么:

def pad(array, reference_shape, offsets): 
    """ 
    array: Array to be padded 
    reference_shape: tuple of size of ndarray 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 
    """ 

    # Create an array of zeros with the reference shape 
    result = np.zeros(reference_shape) 
    # 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 
+0

我可以建议你一个办法做到这一点没有填充? – purpletentacle

很简单,你创建一个使用参照形状包含零的数组:

result = np.zeros(b.shape) 
# actually you can also use result = np.zeros_like(b) 
# but that also copies the dtype not only the shape 

,然后将数组,其中你需要它:

result[:a.shape[0],:a.shape[1]] = a 

,瞧你软垫它:

print(result) 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

您也可以使它有点如果你定义了更一般的在您的左上元素应该被插入

result = np.zeros_like(b) 
x_offset = 1 # 0 would be what you wanted 
y_offset = 1 # 0 in your case 
result[x_offset:a.shape[0]+x_offset,y_offset:a.shape[1]+y_offset] = a 
result 

array([[ 0., 0., 0., 0., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1.], 
     [ 0., 1., 1., 1., 1., 1.], 
     [ 0., 1., 1., 1., 1., 1.]]) 

但随后要小心,你没有偏移大于允许的。例如,对于x_offset = 2,这将失败。


如果您有任意数量的维度,您可以定义切片的列表以插入原始数组。我发现玩这个游戏很有趣,并且创建了一个填充函数,只要数组和参考的维数相同并且偏移量不是很大,就可以填充(使用偏移量)任意形状的数组。

def pad(array, reference, offsets): 
    """ 
    array: Array to be padded 
    reference: Reference array with the desired shape 
    offsets: list of offsets (number of elements must be equal to the dimension of the array) 
    """ 
    # Create an array of zeros with the reference shape 
    result = np.zeros(reference.shape) 
    # Create a list of slices from offset to offset + shape in each dimension 
    insertHere = [slice(offset[dim], offset[dim] + array.shape[dim]) for dim in range(a.ndim)] 
    # Insert the array in the result at the specified offsets 
    result[insertHere] = a 
    return result 

及一些测试情况:

import numpy as np 

# 1 Dimension 
a = np.ones(2) 
b = np.ones(5) 
offset = [3] 
pad(a, b, offset) 

# 3 Dimensions 

a = np.ones((3,3,3)) 
b = np.ones((5,4,3)) 
offset = [1,0,0] 
pad(a, b, offset) 
+0

啊很好看。这可以推广到1D数组或任何数组? – user2015487

+0

@ user2015487 - 您的意思是接受任意维度的函数,还是只针对另一维度的函数? – MSeifert

我明白你的主要问题是,你需要计算d=b-a但你的阵列有不同的尺寸。有没有需要中间填充c

就可以解决这个不填充:

import numpy as np 

a = np.array([[ 1., 1., 1., 1., 1.], 
       [ 1., 1., 1., 1., 1.], 
       [ 1., 1., 1., 1., 1.]]) 

b = np.array([[ 3., 3., 3., 3., 3., 3.], 
       [ 3., 3., 3., 3., 3., 3.], 
       [ 3., 3., 3., 3., 3., 3.], 
       [ 3., 3., 3., 3., 3., 3.]]) 

d = b.copy() 
d[:a.shape[0],:a.shape[1]] -= a 

print d 

输出:现在

[[ 2. 2. 2. 2. 2. 3.] 
[ 2. 2. 2. 2. 2. 3.] 
[ 2. 2. 2. 2. 2. 3.] 
[ 3. 3. 3. 3. 3. 3.]] 
+0

的确,对于他的具体情况,他不一定需要填充,但这是填充和您的方法等效的极少数算术运算之一。不过不错的答案! – MSeifert

NumPy的1.7(当加入np.pad)是很老的(它于2013年发布),所以即使这个问题需要一种没有这种功能的方式,我认为了解如何使用np.pad可以实现这一点可能是有用的。

这其实很简单:在这种情况下,我使用了0mode='constant'默认值

>>> import numpy as np 
>>> a = np.array([[ 1., 1., 1., 1., 1.], 
...    [ 1., 1., 1., 1., 1.], 
...    [ 1., 1., 1., 1., 1.]]) 
>>> np.pad(a, [(0, 1), (0, 1)], mode='constant') 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

>>> np.pad(a, [(0, 1), (0, 1)], mode='constant', constant_values=0) 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

万一第二个参数([(0, 1), (0, 1)])显得扑朔迷离:但它也可以通过在传递明确指定每个列表项(在这种情况下,元组)对应于一维和项目其中代表填充之前(第一元件)和(第二元件)。所以:

[(0, 1), (0, 1)] 
     ^^^^^^------ padding for second dimension 
^^^^^^-------------- padding for first dimension 

    ^------------------ no padding at the beginning of the first axis 
    ^--------------- pad with one "value" at the end of the first axis. 

在这种情况下,用于第一和第二轴的填补是相同的,所以一个还可以只通过在2元组:

>>> np.pad(a, (0, 1), mode='constant') 
array([[ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0.]]) 

在壳体之前的填充和后同样一个甚至可以忽略元组(不适用在这种情况下,虽然):

>>> np.pad(a, 1, mode='constant') 
array([[ 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0.]]) 

或者,如果之前和之后的填充是相同的,但不同的轴,你也可以忽略第二个参数在内部的元组:

>>> np.pad(a, [(1,), (2,)], mode='constant') 
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) 

不过,我更愿意总是使用明确的一个,因为它只是容易犯错误时(NumPys期望从你的意图有所不同):

>>> np.pad(a, [1, 2], mode='constant') 
array([[ 0., 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 1., 1., 1., 1., 1., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0.]]) 

这里NumPy认为你想用1个元素填充所有的轴,每个轴之后填充2个元素!即使你打算在1轴上添加1个元素,在2轴上添加2个元素。

我使用了用于填充的元组列表,注意这只是“我的约定”,您也可以使用列表列表或者元组的元组,或者甚至是数组的元组。 NumPy只是检查参数的长度(或者它没有长度)和每个项目的长度(或者它是否有长度)!

如果您需要1秒的围栏添加到一个数组:

mat = np.zeros((4,4), np.int32) mat array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) mat[0,:] = mat[:,0] = mat[:,-1] = mat[-1,:] = 1 mat array([[1, 1, 1, 1], [1, 0, 0, 1], [1, 0, 0, 1], [1, 1, 1, 1]])

谢谢。