Mark Corrigan
Mark Corrigan

Reputation: 554

Remove sequential NumPy array index in a loop over it's content

I'm iterating over a NumPy (nd) array of OpenCV lines. I want to remove all lines which are outwith 8 degrees of vertical. I realise the numpy array is immutable and what I'm doing in the code is not right but it demonstrates the idea of what I'm trying to do;

index = 0
for line in self.lines[0]:
    if (line[1]*180)/np.pi > 8:                                      
        self.lines[0] = np.delete(self.lines[0], index, axis=0)
    index+=1

How can I go about removing these NumPy array indexes?

Thanks!

Upvotes: 1

Views: 4463

Answers (2)

sebix
sebix

Reputation: 3240

I guess you are missing indentation in your code, so I interpret it like this:

index = 0
for line in self.lines[0]:
    if (line[1]*180)/np.pi > 8:                                      
        self.lines[0] = np.delete(self.lines[0], index, axis=0)
    index+=1

You can do that of course without a loop. First we do the check to build the boolean indexing array (True/False values for every item in the array):

index = self.lines[0,:,1]*180/np.pi > 8

Then we select the lines, where the condition is false:

a[~a%2==0]

Where np.nonzero converts from a boolean array to an array, where all indices with True-values are listed.

For example:

>>> a  = np.arange(10)
>>> a[~a%2==0]
array([1, 3, 5, 7, 9])

Upvotes: 1

Irshad Bhat
Irshad Bhat

Reputation: 8709

You cannot delete array indexes while iterating over that array. It will give wrong results. Say you are at iteration 5 and this index satisfies if condition and needs to be deleted, but if we delete this it will cause array element at index 6 to come at index 5 and next element selected will be 7 which comes to index 6 after deletion and thus condition is never checked for element initially at index 6 i.e., before deletion.

Basic idea to deal with this issue is to append these indices to a list and delete them outside lope. So your code is:

index = 0
idx = []
for line in self.lines[0]:
    if (line[1]*180)/np.pi > 8:     
       idx.append(index)         
    index+=1

self.lines[0] = np.delete(self.lines[0], idx, axis=0)

Upvotes: 4

Related Questions