Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy where function multiple conditions

Tags:

python

numpy

I have an array of distances called dists. I want to select dists which are between two values. I wrote the following line of code to do that:

 dists[(np.where(dists >= r)) and (np.where(dists <= r + dr))] 

However this selects only for the condition

 (np.where(dists <= r + dr)) 

If I do the commands sequentially by using a temporary variable it works fine. Why does the above code not work, and how do I get it to work?

Cheers

like image 998
user1654183 Avatar asked May 02 '13 17:05

user1654183


People also ask

How to use multiple conditions for np where?

where() with multiple conditions. Call numpy. where(condition) with condition as multiple boolean expressions involving the array combined using | (or) or & (and). Use arr[x] with x as the previous results to get a new array containing only the elements of arr for which each conditions is True .

Can NP where be nested?

We can use nested np. where() condition checks ( like we do for CASE THEN condition checking in other languages).

Where is Numpy function?

The numpy. where() function returns the indices of elements in an input array where the given condition is satisfied.


1 Answers

The best way in your particular case would just be to change your two criteria to one criterion:

dists[abs(dists - r - dr/2.) <= dr/2.] 

It only creates one boolean array, and in my opinion is easier to read because it says, is dist within a dr or r? (Though I'd redefine r to be the center of your region of interest instead of the beginning, so r = r + dr/2.) But that doesn't answer your question.


The answer to your question:
You don't actually need where if you're just trying to filter out the elements of dists that don't fit your criteria:

dists[(dists >= r) & (dists <= r+dr)] 

Because the & will give you an elementwise and (the parentheses are necessary).

Or, if you do want to use where for some reason, you can do:

 dists[(np.where((dists >= r) & (dists <= r + dr)))] 

Why:
The reason it doesn't work is because np.where returns a list of indices, not a boolean array. You're trying to get and between two lists of numbers, which of course doesn't have the True/False values that you expect. If a and b are both True values, then a and b returns b. So saying something like [0,1,2] and [2,3,4] will just give you [2,3,4]. Here it is in action:

In [230]: dists = np.arange(0,10,.5) In [231]: r = 5 In [232]: dr = 1  In [233]: np.where(dists >= r) Out[233]: (array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),)  In [234]: np.where(dists <= r+dr) Out[234]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),)  In [235]: np.where(dists >= r) and np.where(dists <= r+dr) Out[235]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),) 

What you were expecting to compare was simply the boolean array, for example

In [236]: dists >= r Out[236]:  array([False, False, False, False, False, False, False, False, False,        False,  True,  True,  True,  True,  True,  True,  True,  True,         True,  True], dtype=bool)  In [237]: dists <= r + dr Out[237]:  array([ True,  True,  True,  True,  True,  True,  True,  True,  True,         True,  True,  True,  True, False, False, False, False, False,        False, False], dtype=bool)  In [238]: (dists >= r) & (dists <= r + dr) Out[238]:  array([False, False, False, False, False, False, False, False, False,        False,  True,  True,  True, False, False, False, False, False,        False, False], dtype=bool) 

Now you can call np.where on the combined boolean array:

In [239]: np.where((dists >= r) & (dists <= r + dr)) Out[239]: (array([10, 11, 12]),)  In [240]: dists[np.where((dists >= r) & (dists <= r + dr))] Out[240]: array([ 5. ,  5.5,  6. ]) 

Or simply index the original array with the boolean array using fancy indexing

In [241]: dists[(dists >= r) & (dists <= r + dr)] Out[241]: array([ 5. ,  5.5,  6. ]) 
like image 102
askewchan Avatar answered Sep 21 '22 13:09

askewchan