Mati Malik
Mati Malik

Reputation: 155

Removing rows from even number columns if certain value is present

I have a numpy array with the shape

(500,12) 

All I want to do is to check whether the even number columns has a positive value, eg. value > 0. In that case I want to remove the whole row in my array. I put this up:

a = a[a[:,1] < 0, :]

This eliminates the desired rows but looks at the second column. I want it to check for column 4, column 6, column 8 etc too.

Is there an way of doing that using my method above?

Upvotes: 3

Views: 493

Answers (5)

Nickil Maveli
Nickil Maveli

Reputation: 29711

If you are dealing with NumPy arrays, then you could use fancy indexing approach (indexing an array with an array sequence of integers) as shown:

mask = (a[:, np.arange(1, a.shape[1], 2)] < 0).all(axis=1)
out = a[mask]

Explanation:

To select positions of odd numbered columns whose values are to be compared:

np.arange(1, a.shape[1], 2)         # a.shape[1] gives the number of columns
# array([ 1,  3,  5,  7,  9, 11])

Next we subset the array based on these indices and see if the values under these columns are lesser than zero by providing axis=1 which performs column-wise check and returns an array containing a reduced number of rows after dropping the remaining ones.

Upvotes: 2

Roelant
Roelant

Reputation: 5119

If you don't want a loop (as it iteratively shrinks your dataframe with some associated overhead):

m = (arr > 0) # check if positive; this is what you want to keep
m = arr.ix[:,1::2] # select only the even columns
m = arr.any(axis=1) # and check if any of them is true

So in one line:

 arr[(arr > 0)[:,1::2].all(axis=1),:]

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 149065

The general way is to build a list comprehension with a condition:

a = [row for row in a if all(row[j] <= 0 for j in range(0, len(row), 2))]

Upvotes: 1

Aditya Rohilla
Aditya Rohilla

Reputation: 337

Without using a loop, there is no single command that will help you with your motive. I suggest looping over all the rows and then doing this.

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477055

Although perhaps not the most efficient way, you can use the elementwise and & for all the rows:

a = a[(a[:,1]<0)&(a[:,3]<0)&(a[:,5]<0)&(a[:,7]<0)&(a[:,9]<0)&(a[:,11]<0),:]

So you mask out all items for which there exists an even column that is positive.

You can make it more elegantly (with a minor performance penalty) by using functools.reduce:

from functools import reduce

a = a[reduce(lambda x,y:x&y,(a[:,i]<0 for i in range(1,12,2))),:]

In case the shape is not fully known in advance, you can use .shape[1]:

from functools import reduce

a = a[reduce(lambda x,y:x&y,(a[:,i]<0 for i in range(1,a.shape[1],2))),:]

Upvotes: 1

Related Questions