python如何用零填充numpy数组

新手上路,请多包涵

我想知道如何使用带有 numpy 版本 1.5.0 的 python 2.6.6 用零填充 2D numpy 数组。但这些都是我的局限。因此我不能使用 np.pad 。例如,我想用零填充 a 使其形状匹配 b 。我想这样做的原因是我可以这样做:

 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

原文由 user2015487 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

非常简单,您可以使用参考形状创建一个包含零的数组:

 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)

原文由 MSeifert 发布,翻译遵循 CC BY-SA 3.0 许可协议

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.]])

在这种情况下,我使用 0mode='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.]])

以防万一第二个参数( [(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.

在这种情况下,第一轴和第二轴的填充是相同的,因此也可以只传入二元组:

 >>> 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 只检查参数的长度(或者如果它没有长度)和每个项目的长度(或者如果它有长度)!

原文由 MSeifert 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏