Reputation: 155
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
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
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
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
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
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