【问题标题】:Numpy stack with unequal shapes形状不等的 Numpy 堆栈
【发布时间】:2017-12-10 14:54:50
【问题描述】:

我注意到combining 2D arrays to 3D arraysnp.stacknp.dstack 的解决方案,或者只是传递数组列表仅在数组具有相同的.shape[0] 时才有效。

例如,假设我有:

print(arr)
[[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]

很容易到达:

print(np.array([arr[2:4], arr[3:5]])) # same shape
[[[4 5]
  [6 7]]

 [[6 7]
  [8 9]]]

但是,如果我传递一个长度不等的数组列表,我会得到:

print(np.array([arr[:2], arr[:3]]))
[array([[0, 1],
       [2, 3]])
 array([[0, 1],
       [2, 3],
       [4, 5]])]

我怎样才能简单:

[[[0, 1]
  [2, 3]]
 [[0, 1]
  [2, 3]
  [4, 5]]]

我尝试过的:其他一些Array manipulation routines

注意:最终希望对超过 2 个数组执行此操作,因此 np.append 可能并不理想。

【问题讨论】:

  • 您到底期待什么?列表数组?清单清单? regular 数组是不可能的,因为形状不相等。

标签: python python-3.x numpy


【解决方案1】:

函数np.stack 沿新轴连接多个数组,而不是现有轴。见:

>>> import numpy as np
>>> arr = np.array(range(10)).reshape((5,2))
>>> print arr
[[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]
>>> t1 = np.array([arr[2:4], arr[3:5]])
>>> print t1.shape
(2, 2, 2)

它不是创建一个新的形状数组(4,2),我认为你打算这样做。看看np.concatenate

请注意,如果您真的想使用堆栈,文档要求所有输入数组的形状相同:

参数:arrays:array_like的序列每个数组必须有 相同的形状。

所以你正在做的事情将有未定义的行为。

编辑:我读得太快了。您正在尝试添加轴。不过,您不能将不均匀的形状传递给堆栈。您必须将它们全部填充为相同的形状。示例:

arr = np.array(range(10)).reshape((5,2))
print arr
arr_p1 = np.zeros(arr[0:3].shape)
arr_p1_src = arr[0:2]
arr_p1[:arr_p1_src.shape[0],:arr_p1_src.shape[1]] = arr_p1_src
t2 = np.array([arr_p1, arr[0:3]])
print t2

输出:

[[[ 0.  1.]
  [ 2.  3.]
  [ 0.  0.]]

 [[ 0.  1.]
  [ 2.  3.]
  [ 4.  5.]]]

【讨论】:

    【解决方案2】:

    我已经制作了一个可以解决这个问题的函数,假设您愿意填充以使形状为矩形,并且您有任意更高的多维数组。它可能会进一步优化,但还不错。

    import numpy as np
    def stack_uneven(arrays, fill_value=0.):
        '''
        Fits arrays into a single numpy array, even if they are
        different sizes. `fill_value` is the default value.
    
        Args:
                arrays: list of np arrays of various sizes
                    (must be same rank, but not necessarily same size)
                fill_value (float, optional):
    
        Returns:
                np.ndarray
        '''
        sizes = [a.shape for a in arrays]
        max_sizes = np.max(list(zip(*sizes)), -1)
        # The resultant array has stacked on the first dimension
        result = np.full((len(arrays),) + tuple(max_sizes), fill_value)
        for i, a in enumerate(arrays):
          # The shape of this array `a`, turned into slices
          slices = tuple(slice(0,s) for s in sizes[i])
          # Overwrite a block slice of `result` with this array `a`
          result[i][slices] = a
        return result
    

    使用它的唯一警告是输入必须能够被处理为一个 numpy 数组序列。所以对于你的例子

    arr = np.array([[0, 1],
                    [2, 3],
                    [4, 5],
                    [6, 7],
                    [8, 9]])
    stack_uneven([arr[:2], arr[:3]], 0)
    

    这会给你

    array([[[0, 1],
        [2, 3],
        [0, 0]],
    
       [[0, 1],
        [2, 3],
        [4, 5]]])
    

    但这同样适用于更高维度的事物,例如:

    arr = [np.ones([3, 2, 2]), np.ones([2, 3, 2]), np.ones([2, 2, 3])]
    

    【讨论】:

      【解决方案3】:

      Numpy 数组必须是矩形的,所以你想要得到的结果是不可能用 numpy 数组实现的。

      您需要不同的数据结构。哪一个合适取决于您要如何处理这些数据。

      【讨论】:

        【解决方案4】:

        最终 np.vstack 或 np.hstack 会很有用,如果你的垂直或水平堆栈对你来说足够了,并且你至少有一个相等的维度。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-28
          • 2022-01-10
          • 2011-07-18
          • 2016-05-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多