Python Numpy where 函数多个条件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16343752/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Numpy where function multiple conditions
提问by user1654183
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:
我有一系列称为 dist 的距离。我想选择两个值之间的 dist。我编写了以下代码行来做到这一点:
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
干杯
采纳答案by askewchan
The best way in your particular casewould 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 distwithin a dror r?(Though I'd redefine rto be the center of your region of interest instead of the beginning, so r = r + dr/2.) But that doesn't answer your question.
它仅创建一个布尔数组,在我看来是更易于阅读,因为它说,是dist内部的dr还是r?(虽然我会重新定义r为您感兴趣的区域的中心,而不是起点,所以r = r + dr/2.)但这并不能回答您的问题。
The answer to your question:
You don't actually need whereif you're just trying to filter out the elements of diststhat don't fit your criteria:
您的问题的答案:如果您只是想过滤掉不符合您标准的元素,您
实际上并不需要:wheredists
dists[(dists >= r) & (dists <= r+dr)]
Because the &will give you an elementwise and(the parentheses are necessary).
因为&会给你一个元素and(括号是必要的)。
Or, if you do want to use wherefor some reason, you can do:
或者,如果您where出于某种原因确实想使用,则可以执行以下操作:
dists[(np.where((dists >= r) & (dists <= r + dr)))]
Why:
The reason it doesn't work is because np.wherereturns a list of indices, not a boolean array. You're trying to get andbetween two lists of numbers, which of course doesn't have the True/Falsevalues that you expect. If aand bare both Truevalues, then a and breturns b. So saying something like [0,1,2] and [2,3,4]will just give you [2,3,4]. Here it is in action:
为什么:
它不起作用的原因是因为np.where返回一个索引列表,而不是一个布尔数组。您正试图and在两个数字列表之间切换,这当然没有您期望的True/False值。如果a和b都是True值,则a and b返回b。所以说类似的话[0,1,2] and [2,3,4]只会给你[2,3,4]。这是在行动:
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.whereon the combined boolean array:
现在您可以调用np.where组合的布尔数组:
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. ])
回答by kiriloff
I have worked out this simple example
我已经制定了这个简单的例子
import numpy as np
ar = np.array([3,4,5,14,2,4,3,7])
print [X for X in list(ar) if (X >= 3 and X <= 6)]
>>>
[3, 4, 5, 4, 3]
回答by Xin Wang
Try:
尝试:
np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0])
回答by Kasramvd
The accepted answer explained the problem well enough. However, the the more Numpythonic approach for applying multiple conditions is to use numpy logical functions. In this ase you can use np.logical_and:
接受的答案很好地解释了这个问题。但是,应用多个条件的更 Numpythonic 方法是使用numpy 逻辑函数。在这种情况下,您可以使用np.logical_and:
np.where(np.logical_and(np.greater_equal(dists,r),np.greater_equal(dists,r + dr)))
回答by Kasramvd
I like to use np.vectorizefor such tasks. Consider the following:
我喜欢np.vectorize用于此类任务。考虑以下:
>>> # function which returns True when constraints are satisfied.
>>> func = lambda d: d >= r and d<= (r+dr)
>>>
>>> # Apply constraints element-wise to the dists array.
>>> result = np.vectorize(func)(dists)
>>>
>>> result = np.where(result) # Get output.
You can also use np.argwhereinstead of np.wherefor clear output. But that is your call :)
您也可以使用np.argwhere代替np.where清除输出。但那是你的电话:)
Hope it helps.
希望能帮助到你。
回答by Qhan
This should work:
这应该有效:
dists[((dists >= r) & (dists <= r+dr))]
The most elegant way~~
最优雅的方式~~
回答by Xiong-Hui Chen
Try:
尝试:
import numpy as np
dist = np.array([1,2,3,4,5])
r = 2
dr = 3
np.where(np.logical_and(dist> r, dist<=r+dr))
Output: (array([2, 3]),)
输出:(array([2, 3]),)
You can see Logic functionsfor more details.
您可以查看逻辑函数了解更多详细信息。
回答by Amit Amola
One interesting thing to point here; the usual way of using ORand ANDtoo will work in this case, but with a small change. Instead of "and" and instead of "or", rather use Ampersand(&)and Pipe Operator(|)and it will work.
这里要指出一件有趣的事情;在这种情况下,使用OR和AND的常用方法也可以使用,但需要稍作改动。而不是“和”和“或”,而是使用与号(&)和管道运算符(|),它会起作用。
When we use 'and':
当我们使用'and' 时:
ar = np.array([3,4,5,14,2,4,3,7])
np.where((ar>3) and (ar<6), 'yo', ar)
Output:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
When we use Ampersand(&):
当我们使用& 符号(&) 时:
ar = np.array([3,4,5,14,2,4,3,7])
np.where((ar>3) & (ar<6), 'yo', ar)
Output:
array(['3', 'yo', 'yo', '14', '2', 'yo', '3', '7'], dtype='<U11')
And this is same in the case when we are trying to apply multiple filters in case of pandas Dataframe. Now the reasoning behind this has to do something with Logical Operators and Bitwise Operators and for more understanding about same, I'd suggest to go through this answeror similar Q/A in stackoverflow.
这与我们尝试在 Pandas Dataframe 的情况下应用多个过滤器的情况相同。现在,这背后的原因必须与逻辑运算符和位运算符有关,为了更多地了解相同的内容,我建议在 stackoverflow 中查看此答案或类似的问答。
UPDATE
更新
A user asked, why is there a need for giving (ar>3) and (ar<6) inside the parenthesis. Well here's the thing. Before I start talking about what's happening here, one needs to know about Operator precedence in Python.
有用户问,为什么需要在括号内给出 (ar>3) 和 (ar<6)。嗯,事情就是这样。在我开始谈论这里发生的事情之前,需要了解 Python 中的运算符优先级。
Similar to what BODMAS is about, python also gives precedence to what should be performed first. Items inside the parenthesis are performed first and then the bitwise operator comes to work. I'll show below what happens in both the cases when you do use and not use "(", ")".
与 BODMAS 类似,python 也优先考虑应该首先执行的操作。首先执行括号内的项目,然后按位运算符开始工作。我将在下面展示当你使用和不使用 "(", ")" 时在这两种情况下会发生什么。
Case1:
情况1:
np.where( ar>3 & ar<6, 'yo', ar)
np.where( np.array([3,4,5,14,2,4,3,7])>3 & np.array([3,4,5,14,2,4,3,7])<6, 'yo', ar)
Since there are no brackets here, the bitwise operator(&) is getting confused here that what are you even asking it to get logical AND of, because in the operator precedence table if you see, &is given precedence over <or >operators. Here's the table from from lowest precedence to highest precedence.
由于这里没有括号,因此按位运算符 ( &) 在这里变得很困惑,您甚至要求它进行逻辑 AND 运算,因为在运算符优先级表中,如果您看到的话,&它的优先级高于<or>运算符。这是从最低优先级到最高优先级的表格。
It's not even performing the <and >operation and being asked to perform a logical AND operation. So that's why it gives that error.
它甚至不执行<与>操作并被要求执行逻辑与操作。所以这就是它给出错误的原因。
One can check out the following link to learn more about: operator precedence
可以查看以下链接以了解更多信息:运算符优先级
Now to Case 2:
现在到案例 2:
If you do use the bracket, you clearly see what happens.
如果您确实使用了支架,您会清楚地看到会发生什么。
np.where( (ar>3) & (ar<6), 'yo', ar)
np.where( (array([False, True, True, True, False, True, False, True])) & (array([ True, True, True, False, True, True, True, False])), 'yo', ar)
Two arrays of True and False. And you can easily perform logical AND operation on them. Which gives you:
两个 True 和 False 数组。您可以轻松地对它们执行逻辑与运算。这给了你:
np.where( array([False, True, True, False, False, True, False, False]), 'yo', ar)
And rest you know, np.where, for given cases, wherever True, assigns first value(i.e. here 'yo') and if False, the other(i.e. here, keeping the original).
剩下的你知道,np.where,对于给定的情况,无论在哪里为 True,都分配第一个值(即这里的 'yo'),如果为 False,则分配另一个值(即这里,保留原始值)。
That's all. I hope I explained the query well.
就这样。我希望我能很好地解释查询。


