简体   繁体   中英

How to fix “index is out of bounds” error in python, working with numpy?

I'm trying to build a function that removes any negative numbers out of an array, but gets a error message. What do I need to change?

This is for python 3 using the numpy library The code I've tried so far is:

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

I'm trying to make this assert work:

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

But i get this error message: IndexError: index -5 is out of bounds for axis 0 with size 4

The mistake is in the assignment b = a . b is then not a copy, just a(nother) view into a : any chances in b are reflected in a . If you use b = a.copy() (or b = a[:] ) in your function, your code will work.

With NumPy, however, it's clearer and faster to think vector(array)-wise: use, for example,

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

and you don't need your function anymore.

In your for loop you iterate over the array a number of times, if you then remove -3, you only have 4 items in the array. You then get to -5 and you try to remove that item, but that would be item 5 (4, when you start on 0) which means that your index is invalid as there isn't an item 5 in your array any more.

You want to make a copy of the array at the start, then iterate over one list and remove from another

Look in detail at what happens with each delete:

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 makes a new array each time. That makes it slower than similar list methods. But it does mean that a does not get changed.

np.delete takes an index, not a value (it's not the same as the list del ). a[2] just happens to work because a[-3] is [-3] . a[4] is -5 which isn't a valid index in the size 4 b .

If we specify the index rather than value, the deletes work correctly:

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

But a repeated delete is slow; better to delete all negative numbers at once:

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

We can use where to get the indices:

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

But we can use the mask directly:

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

for a list, a simple list comprehension works nicely:

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

Another well known trick with lists, is to iterate from the end, so that any deletions won't mess up the remaining list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM