首页 > 解决方案 > 以保持元素索引/位置相同的方式更改 numpy 数组的形状

问题描述

假设我有以下 numpy 数组

[[[1 2 3]
  [4 5 6]
  [7 8 9]]

 [[1 2 3]
  [4 5 6]
  [7 8 9]]

 [[1 2 3]
  [4 5 6]
  [7 8 9]]]

我希望能够调整此数组的大小(使其沿轴变小或变大),但现有元素具有与调整大小之前相同的索引。因此,如果我将轴 2 的大小减少一个元素,它会如下所示:

[[[1 2]
  [4 5]
  [7 8]]

 [[1 2]
  [4 5]
  [7 8]]

 [[1 2]
  [4 5]
  [7 8]]]

如果我增加轴 1 的大小,它看起来像这样:

[[[1 2 3]
  [4 5 6]
  [7 8 9]
  [0 0 0]]

 [[1 2 3]
  [4 5 6]
  [7 8 9]
  [0 0 0]]

 [[1 2 3]
  [4 5 6]
  [7 8 9]
  [0 0 0]]]

如果不自己实现所有循环和所有内容,我将如何做到这一点?


作为参考,如果我使用 Numpy resize() 函数,并将np.resize(my_array, (3, 3, 2))轴 2 的大小从 3 减小到 2,Numpy 只会更改维度的大小并且不会重新组织数组数据本身,这意味着元素的索引不保存:

[[[1 2]
  [3 4]
  [5 6]]

 [[7 8]
  [9 1]
  [2 3]]

 [[4 5]
  [6 7]
  [8 9]]]

标签: pythonarraysnumpy

解决方案


我会使用np.padnp.zeros

  1. 使用 np.pad:

构建示例数组:

>>> import numpy as np               
>>> 
>>> A = np.resize(np.r_[1:10],(3,3,3))
>>> A
array([[[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]],

       [[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]],

       [[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]]])

定义函数

>>> def recut_pad(A,shp):
...     return np.pad(A[tuple(map(slice,shp))],[(0,max(0,sn-so)) for sn,so in zip(shp,A.shape)])

试试看:

>>> recut_pad(A,(2,4,5))
array([[[1, 2, 3, 0, 0],
        [4, 5, 6, 0, 0],
        [7, 8, 9, 0, 0],
        [0, 0, 0, 0, 0]],

       [[1, 2, 3, 0, 0],
        [4, 5, 6, 0, 0],
        [7, 8, 9, 0, 0],
        [0, 0, 0, 0, 0]]])
>>> recut_pad(A,(4,2,2))
array([[[1, 2],
        [4, 5]],

       [[1, 2],
        [4, 5]],

       [[1, 2],
        [4, 5]],

       [[0, 0],
        [0, 0]]])
  1. 使用np.zeros和切片:

定义函数:

>>> def recut_zeros(A,shp):                                           
...     out = np.zeros(shp,A.dtype)                              
...     out[tuple(map(slice,A.shape))] = A[tuple(map(slice,shp))]
...     return out

核实:

>>> np.all(recut_pad(A,(1,5,4))==recut_zeros(A,(1,5,4)))
True
>>> np.all(recut_pad(A,(7,2,3))==recut_zeros(A,(7,2,3)))
True

推荐阅读