python如何用零填充numpy数组

use*_*487 57 python arrays numpy pad

我想知道如何使用python 2.6.6和numpy 1.5.0版本用零填充2D numpy数组.抱歉! 但这些是我的局限.所以我不能用np.pad.例如,我想a用零填充,使其形状匹配b.我之所以这样做是因为我能做到:

b-a
Run Code Online (Sandbox Code Playgroud)

这样的

>>> 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]])
Run Code Online (Sandbox Code Playgroud)

我能想到的唯一方法就是追加,但这看起来很难看.是否有可能使用的清洁解决方案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
Run Code Online (Sandbox Code Playgroud)

MSe*_*ert 105

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

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
Run Code Online (Sandbox Code Playgroud)

然后将数组插入所需的位置:

result[:a.shape[0],:a.shape[1]] = a
Run Code Online (Sandbox Code Playgroud)

瞧,你填补了它:

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.]])
Run Code Online (Sandbox Code Playgroud)

如果定义应该插入左上角元素的位置,也可以使它更通用一些

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.]])
Run Code Online (Sandbox Code Playgroud)

但是要小心你没有超过允许的偏移量.例如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
Run Code Online (Sandbox Code Playgroud)

还有一些测试用例:

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)
Run Code Online (Sandbox Code Playgroud)


MSe*_*ert 95

NumPy 1.7.0(当numpy.pad被添加时)已经很老了(它于2013年发布)所以即使问题没有使用该功能,我也认为了解如何使用它可能是有用的numpy.pad.

它实际上非常简单:

>>> 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.]])
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我使用的0是默认值mode='constant'.但它也可以通过显式传递来指定:

>>> 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.]])
Run Code Online (Sandbox Code Playgroud)

以防第二个参数([(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.
Run Code Online (Sandbox Code Playgroud)

在这种情况下,第一和第二轴的填充是相同的,因此也可以只传入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.]])
Run Code Online (Sandbox Code Playgroud)

如果之前和之后的填充相同,甚至可以省略元组(虽然在这种情况下不适用):

>>> 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.]])
Run Code Online (Sandbox Code Playgroud)

或者,如果前后填充相同但轴不同,则还可以省略内部元组中的第二个参数:

>>> 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.]])
Run Code Online (Sandbox Code Playgroud)

但是我倾向于总是使用明确的一个,因为它只是容易出错(当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.]])
Run Code Online (Sandbox Code Playgroud)

在这里,NumPy认为你想要在每个轴之前填充1个元素并且在每个轴之后填充2个元素!即使您打算在轴1中填充1个元素,也为轴2填充2个元素.

我使用了元组列表作为填充,注意这只是"我的约定",你也可以使用列表或元组元组,甚至是元组元组.NumPy只检查参数的长度(或者如果它没有长度)和每个项目的长度(或者如果它有长度)!

  • 真的很好解释了。远胜于原始文档。谢谢。 (3认同)

Jua*_*eni 6

我知道你的主要问题是你需要计算,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
Run Code Online (Sandbox Code Playgroud)

输出:

[[ 2.  2.  2.  2.  2.  3.]
 [ 2.  2.  2.  2.  2.  3.]
 [ 2.  2.  2.  2.  2.  3.]
 [ 3.  3.  3.  3.  3.  3.]]
Run Code Online (Sandbox Code Playgroud)