如何使用numpy修复python中的“索引超出范围”错误?

时间:2019-05-15 13:49:10

标签: python numpy

我正在尝试构建一个函数,该函数将从数组中删除所有负数,但会收到错误消息。我需要更改什么?

这是使用numpy库的python 3的 到目前为止,我尝试过的代码是:

def drop_negative_numbers(a):
    b = a
    for i in range(a.size): 
        if a[i] < 0:
            b = np.delete(b, a[i])       
    return b

我正在尝试使该断言起作用:

a = np.array([1, 2, -3, 4, -5])
b = drop_negative_numbers(a)
npt.assert_equal(b, [1, 2, 4])

但是我收到此错误消息:IndexError:索引-5超出了轴4尺寸4的范围

3 个答案:

答案 0 :(得分:0)

错误出在分配b = a中。 b不是副本,而只是a的(另一种)视图:b中的任何机会都将反映在a中。如果您在函数中使用b = a.copy()(或b = a[:]),则代码将起作用。

但是,使用NumPy,更明智地思考矢量(数组)方式:例如,使用

a = np.array([1, 2, -3, 4, -5])
b = a[a >= 0]

您不再需要功能。

答案 1 :(得分:0)

在for循环中,您需要多次遍历数组,如果再删除-3,则数组中只有4个项目。然后,您进入-5并尝试删除该项目,但这将是项目5(从0开始时为4),这意味着您的索引无效,因为数组中不再有项目5。

您想在开始时复制数组,然后遍历一个列表,然后从另一个列表中删除

答案 2 :(得分:0)

详细查看每次删除会发生什么情况

In [43]: a                                                                      
Out[43]: array([ 1,  2, -3,  4, -5])
In [44]: b=a                                                                    
In [45]: a[2]                                                                   
Out[45]: -3
In [46]: b=np.delete(b, a[2])                                                   
In [47]: b                                                                      
Out[47]: array([ 1,  2,  4, -5])
In [48]: a[4]                                                                   
Out[48]: -5
In [49]: b=np.delete(b, a[4])                                                   
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-49-a326bbe5d5c9> in <module>
----> 1 b=np.delete(b, a[4])

/usr/local/lib/python3.6/dist-packages/numpy/lib/function_base.py in delete(arr, obj, axis)
   4374             raise IndexError(
   4375                 "index %i is out of bounds for axis %i with "
-> 4376                 "size %i" % (obj, axis, N))
   4377         if (obj < 0):
   4378             obj += N

IndexError: index -5 is out of bounds for axis 0 with size 4

delete每次都会创建一个新数组。这使其比类似的列表方法慢。但这确实意味着a不会被更改。

np.delete接受索引,而不是值(与列表del不同)。 a[2]恰好起作用,因为a[-3][-3]a[4]-5,它不是大小为4 b的有效索引。

如果我们指定索引而不是值,则删除工作正常:

In [51]: b=a                                                                    
In [52]: b=np.delete(b, 2)                                                      
In [53]: b                                                                      
Out[53]: array([ 1,  2,  4, -5])
In [54]: b=np.delete(b, 3)                                                      
In [55]: b                                                                      
Out[55]: array([1, 2, 4])

但是重复的delete很慢;最好一次删除所有负数:

In [56]: a                                                                      
Out[56]: array([ 1,  2, -3,  4, -5])
In [57]: np.delete(a,[2,4])                                                     
Out[57]: array([1, 2, 4])

我们可以使用where来获取索引:

In [65]: a<0                                                                    
Out[65]: array([False, False,  True, False,  True])
In [66]: np.where(a<0)                                                          
Out[66]: (array([2, 4]),)
In [67]: np.delete(a, np.where(a<0))                                            
Out[67]: array([1, 2, 4])

但是我们可以直接使用蒙版:

In [68]: a[~(a<0)]                                                              
Out[68]: array([1, 2, 4])

对于列表,一个简单的列表理解就可以很好地工作:

In [69]: b = a.tolist()                                                         
In [70]: [i for i in b if not i<0]                                              
Out[70]: [1, 2, 4]

列表的另一个众所周知的技巧是从末尾进行迭代,以使任何删除都不会弄乱其余列表。