Numpy删除对象数组中的数组行

时间:2017-06-07 13:56:11

标签: python arrays numpy

我试图从numpy中存储在对象数组中的数组中删除行。但是你可以看到它抱怨它不能将较小的数组广播到较大的数组中。直接对阵列完成时工作正常。这是什么问题?除了制作一个新的对象数组并逐个复制直到我要修改的数组之外,还有什么干净的解决这个错误的方法?

In [1]: import numpy as np

In [2]: x = np.zeros((3, 2))

In [3]: x = np.delete(x, 1, axis=0)

In [4]: x
Out[4]: 
array([[ 0.,  0.],
       [ 0.,  0.]])

In [5]: x = np.array([np.zeros((3, 2)), np.zeros((3, 2))], dtype=object)

In [6]: x[0] = np.delete(x[0], 1, axis=0)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-1687d284d03c> in <module>()
----> 1 x[0] = np.delete(x[0], 1, axis=0)

ValueError: could not broadcast input array from shape (2,2) into shape (3,2)

编辑:当阵列形状不同时,显然可行。这很烦人。有哪些方法可以通过np.array禁用自动连接?

In [12]: x = np.array([np.zeros((3, 2)), np.zeros((5, 8))], dtype=object)

In [13]: x[0] = np.delete(x[0], 1, axis=0)

In [14]: x = np.array([np.zeros((3, 2)), np.zeros((3, 2))], dtype=object)

In [15]: x.shape
Out[15]: (2, 3, 2)

In [16]: x = np.array([np.zeros((3, 2)), np.zeros((5, 8))], dtype=object)

In [17]: x.shape
Out[17]: (2,)

这是一种非常不一致的行为。

2 个答案:

答案 0 :(得分:1)

np.array在SO上多次讨论了尽可能多地创建一个维数组的事实。如果元素大小不同,则会将它们分开,或者在某些情况下会引发错误。

在你的例子中

In [201]: x = np.array([np.zeros((3, 2)), np.zeros((3, 2))], dtype=object)
In [202]: x
Out[202]: 
array([[[0.0, 0.0],
        [0.0, 0.0],
        [0.0, 0.0]],

       [[0.0, 0.0],
        [0.0, 0.0],
        [0.0, 0.0]]], dtype=object)

制作具有确定大小的对象数组的安全方法是初始化它然后填充它:

In [203]: x=np.empty(2, dtype=object)
In [204]: x
Out[204]: array([None, None], dtype=object)
In [205]: x[...] = [np.zeros((3, 2)), np.zeros((3, 2))]
In [206]: x
Out[206]: 
array([array([[ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.]]),
       array([[ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.]])], dtype=object)

像这样的1d对象数组,对于大多数实际来说是一个列表。元素的操作使用Python级迭代,隐式或显式执行(与列表推导一样)。多维数字数组的大部分计算能力都消失了。

In [207]: x.shape         
Out[207]: (2,)
In [208]: [xx.shape for xx in x]   # shape of the elements
Out[208]: [(3, 2), (3, 2)]
In [209]: [xx[:2,:] for xx in x]    # slice the elements
Out[209]: 
[array([[ 0.,  0.],
        [ 0.,  0.]]), array([[ 0.,  0.],
        [ 0.,  0.]])]

您可以重塑这样的数组,但不能将其作为列表追加。一些数学运算跨越“对象”边界,但它是偶然的。总而言之,当列表也能正常工作时,不要使用对象数组。

Understanding non-homogeneous numpy arrays

答案 1 :(得分:0)

在我看来,这是非常hacky和丑陋,但它是我能想到的唯一解决方案。使用list comprehension将对象数组转换为list(使用.tolist()不起作用,因为它将子数组拆分为列表),修改元素并转换回对象数组。

In [37]: x = np.array([np.zeros((3, 2)), np.zeros((3, 2))], dtype=object)

In [38]: xx = [z for z in x]

In [39]: xx[0] = np.delete(xx[0], 1, axis=0)

In [40]: x = np.array(xx, dtype=object)

In [41]: x
Out[41]: 
array([array([[0.0, 0.0],
       [0.0, 0.0]], dtype=object),
       array([[0.0, 0.0],
       [0.0, 0.0],
       [0.0, 0.0]], dtype=object)], dtype=object)

我想我会在numpy github上发布一个问题,以了解对象数组的一致行为