设x为NumPy数组。以下几点:

(x > 1) and (x < 3)

给出错误信息:

ValueError:包含多个元素的数组的真值为 模糊。使用a.any()或a.all()

我怎么解决这个问题?


如果a和b是布尔NumPy数组,&操作返回它们的元素:

a & b

返回一个布尔数组。要将其减少为一个布尔值,可以使用其中任何一个

(a & b).any()

or

(a & b).all()

注意:如果a和b是非布尔数组,请考虑(a - b).any()或(a - b).all()。


基本原理

NumPy开发人员认为,在布尔上下文中没有一种普遍理解的方法来计算数组:如果任何元素为True,它可能意味着True;如果所有元素都为True,它可能意味着True;如果数组长度非零,它可能意味着True,仅举三种可能性。

由于不同的用户可能有不同的需求和不同的假设,因此 NumPy开发人员拒绝猜测,而是决定在任何时候尝试在布尔上下文中计算数组时引发ValueError。对两个numpy数组应用和会导致这两个数组在布尔上下文中求值(通过在Python3中调用__bool__或在Python2中调用__nonzero__)。


我也遇到了同样的问题(即多条件索引,这里是在某个日期范围内查找数据)。(a-b).any()或(a-b).all()似乎不起作用,至少对我来说是这样。

或者,我找到了另一个解决方案,它完美地满足了我想要的功能(当尝试索引数组时,具有多个元素的数组的真值是不明确的)。

与其使用上面建议的代码,不如使用:

numpy.logical_and(a, b)

出现异常的原因是and隐式调用bool。首先在左操作数上,然后(如果左操作数为True)在右操作数上。所以x和y等价于bool(x)和bool(y)

但是,numpy上的bool类型。Ndarray(如果它包含多个元素)将抛出你所看到的异常:

>>> import numpy as np
>>> arr = np.array([1, 2, 3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

bool()调用在and中是隐式的,但在if、while和or中也是隐式的,因此以下任何示例也会失败:

>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> if arr: pass
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> while arr: pass
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> arr or arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Python中还有更多隐藏bool调用的函数和语句,例如2 < x < 10就是2 < x和x < 10的另一种写法。And将调用bool: bool(2 < x)和bool(x < 10)。

和的元素等效形式是np。Logical_and函数,类似地,您可以使用np。Logical_or等价于或。

对于布尔数组——以及NumPy数组上的<、<=、==、!=、>=和>等比较返回布尔NumPy数组——您还可以使用按元素的位函数(和操作符):np。Bitwise_and(&运算符)

>>> np.logical_and(arr > 1, arr < 3)
array([False,  True, False], dtype=bool)

>>> np.bitwise_and(arr > 1, arr < 3)
array([False,  True, False], dtype=bool)

>>> (arr > 1) & (arr < 3)
array([False,  True, False], dtype=bool)

和bitwise_or(|操作符):

>>> np.logical_or(arr <= 1, arr >= 3)
array([ True, False,  True], dtype=bool)

>>> np.bitwise_or(arr <= 1, arr >= 3)
array([ True, False,  True], dtype=bool)

>>> (arr <= 1) | (arr >= 3)
array([ True, False,  True], dtype=bool)

一个完整的逻辑和二进制函数列表可以在NumPy文档中找到:

“逻辑功能” “二进制操作”


如果你与熊猫一起工作,为我解决的问题是,当我有NA值时,我试图做计算,解决方案是运行:

Df = Df .dropna()

在那之后,计算失败了。


这个类型化的错误消息还显示了当存在数组(例如bool或int类型)时执行if语句比较。请看例子:

... code snippet ...

if dataset == bool:
    ....

... code snippet ...

这个子句有dataset作为数组,bool是euhm的“打开的门”…对或错。

如果函数被包装在try-statement中,你将接收到带有except Exception的错误:没有error-type的消息:

具有多个元素的数组的真值是不明确的。使用a.any()或a.all()


以@ZF007的回答为例,这并不是在整体上回答你的问题,但可以作为同样错误的解决方案。我把它贴在这里,因为我还没有找到一个直接的解决方案来回答这个错误消息在Stack Overflow的其他地方。

当您检查数组是否为空时,会出现此错误。

if np.array([1,2]): print(1) --> ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all(). if np.array([1,2])[0]: print(1) --> no ValueError, but: if np.array([])[0]: print(1) --> IndexError: index 0 is out of bounds for axis 0 with size 0. if np.array([1]): print(1) --> no ValueError, but again will not help at an array with many elements. if np.array([]): print(1) --> DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use 'array.size > 0' to check that an array is not empty. if np.array([]).size is not None: print(1): Taking up a comment by this user, this does not work either. This is since no np.array can ever be the same object as None - that object is unique - and thus will always match is not None (i.e. never match is None) whether or not it's empty.

这样做:

如果np.array([])。大小:打印(1)解决了错误。


对我来说,这个错误发生在测试中,代码错误如下:

pixels = []
self.pixels = numpy.arange(1, 10)
self.assertEqual(self.pixels, pixels)

这段代码返回:

ValueError:具有多个元素的数组的真值是不明确的。使用a.any()或a.all()

因为我不能用列表断言numpy方法排列返回的对象。

解决方案是将numpy的排列对象转换为列表,我的选择是使用toList()方法,如下所示:

pixels = []
self.pixels = numpy.arange(1, 10).toList()
self.assertEqual(self.pixels, pixels)

通常,当比较两个单个数字时,Python常规代码可以正常工作,但在数组中,有一些数字(不止一个数字)应该并行处理。

例如,让我们假设如下:

a = np.array([1, 2, 3])
b = np.array([2, 3, 4])

你想检查b >= a: ?

因为,a和b不是个位数,你的意思是,如果b的每个元素都大于a中相似的数字,那么你应该使用以下命令:

if (b >= a).all():
 print("b is greater than a!")

最简单的答案是用“&”而不是“and”。

>>> import numpy as np
>>> arr = np.array([1, 4, 2, 7, 5])
>>> arr[(arr > 3) and (arr < 6)]   # this will fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> arr[(arr > 3) & (arr < 6)]   # this will succeed
array([4, 5])

导致

当代码试图将Numpy数组转换为布尔值(即检查其真值,如错误消息中所述)时,就会发生此错误。对于给定的数组a,可以发生以下情况:

Explicitly, by using bool(a). Implicitly with boolean logical operators: a and a, a or a, not a. Implicitly using the built-in any and all functions. (These can accept a single array, regardless of how many dimensions it has; but cannot accept a list, tuple, set etc. of arrays.) Implicitly in an if statement, using if a:. While it's normally possible to use any Python object in an if statement, Numpy arrays deliberately break this feature, because it could easily be used to write incorrect code by mistake otherwise.

Numpy数组和比较 (==, !=, <, >, <=, >=)

比较对于Numpy数组有特殊的意义。这里我们将考虑==运算符;其余的表现类似。假设我们有

import numpy as np
>>> a = np.arange(9)
>>> b = a % 3
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> b
array([0, 1, 2, 0, 1, 2, 0, 1, 2])

那么,a == b并不意味着“给出一个正确或错误的答案:a是否等于b?”,就像它通常的意思一样。相反,它将逐个元素比较这些值,并为这些比较的布尔结果数组求值:

>>> a == b
array([ True,  True,  True, False, False, False, False, False, False])

换句话说,它执行与数学运算符(如b = a % 3)相同的广播。

对于if语句使用这个结果是没有意义的,因为它不清楚要做什么:我们是否应该输入if块,因为一些值匹配?或者我们应该进入else块,因为有些值不匹配?在这里,Numpy应用了Python禅宗中的一个重要原则:“在模棱两可的情况下,拒绝猜测的诱惑。”

因此,Numpy只允许将数组转换为bool类型,前提是该数组恰好包含一个元素。(在一些旧版本中,对于空数组,它也会转换为False;但也有很好的逻辑理由来解释为什么这也应该被视为模棱两可。)

类似地,比较a == 4将不会检查数组是否等于整数(当然,没有数组可以等于任何整数)。相反,它会在数组中传播比较,给出类似的结果数组:

>>> a == 4
array([False, False, False, False,  True, False, False, False, False])

修正表达式

If the code is explicitly converting to bool, choose between applying .any or .all to the result, as appropriate. As the names suggest, .any will collapse the array to a single boolean, indicating whether any value was truthy; .all will check whether all values were truthy. >>> (a == 4).all() # `a == 4` contains some `False` values False >>> (a == 4).any() # and also some `True` values True >>> a.all() # We can check `a` directly as well: `0` is not truthy, False >>> a.any() # but other values in `a` are. True If the goal is to convert a to boolean element-wise, use a.astype(bool), or (only for numeric inputs) a != 0. If the code is using boolean logic (and/or/not), use bitwise operators (&/|/~, respectively) instead: >>> ((a % 2) != 0) & ((a % 3) != 0) # N.B. `&`, not `and` array([False, True, False, False, False, True, False, True, False]) Note that bitwise operators also offer access to ^ for an exclusive-or of the boolean inputs; this is not supported by logical operators (there is no xor). For a list (or other sequence) of arrays that need to be combined in the same way (i.e., what the built-ins all and any do), instead build the corresponding (N+1)-dimensional array, and use np.all or np.any along axis 0: >>> a = np.arange(100) # a larger array for a more complex calculation >>> sieves = [a % p for p in (2, 3, 5, 7)] >>> all(sieves) # won't work Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() >>> np.all(np.array(sieves), axis=0) # instead: array([False, True, False, False, False, False, False, False, False, False, False, True, False, True, False, False, False, True, False, True, False, False, False, True, False, False, False, False, False, True, False, True, False, False, False, False, False, True, False, False, False, True, False, True, False, False, False, True, False, False, False, False, False, True, False, False, False, False, False, True, False, True, False, False, False, False, False, True, False, False, False, True, False, True, False, False, False, False, False, True, False, False, False, True, False, False, False, False, False, True, False, False, False, False, False, False, False, True, False, False])

修复if语句

首先,请记住,如果代码中有一个if语句使用了一个损坏的表达式(如if (a % 3 == 0)或(a % 5 == 0):),那么这两个问题都需要修复。

通常,显式转换为bool类型(使用上面提到的.all()或.any())将避免异常:

>>> a = np.arange(20) # enough to illustrate this
>>> if ((a % 3 == 0) | (a % 5 == 0)).any():
...     print('there are fizzbuzz values')
... 
there are fizzbuzz values

但它可能做不到我们想要的:

>>> a = np.arange(20) # enough to illustrate this
>>> if ((a % 3 == 0) | (a % 5 == 0)).any():
...     a = -1
... 
>>> a
-1

如果目标是对每个条件为真的值进行操作,那么自然的方法是将掩码用作掩码。例如,要在条件为真的地方赋一个新值,只需将计算出的掩码索引到原始数组中,并赋值:

>>> a = np.arange(20)
>>> a[(a % 3 == 0) | (a % 5 == 0)] = -1
>>> a
array([-1,  1,  2, -1,  4, -1, -1,  7,  8, -1, -1, 11, -1, 13, 14, -1, 16,
       17, -1, 19])

这种索引技术对于查找满足条件的值也很有用。建立在前面的筛子的例子:

>>> a = np.arange(100)
>>> sieves = [a % p for p in (2, 3, 5, 7)]
>>> a[np.all(np.array(sieves), axis=0)]
array([ 1, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
       73, 79, 83, 89, 97])

(练习:研究代码并理解为什么这个结果不是一个小于100的质数列表;然后修复它。)

使用熊猫

Pandas库有Numpy作为依赖项,并在Numpy的数组类型之上实现了它的DataFrame类型。所有相同的推理都适用,例如Pandas Series(和DataFrame)对象不能用作布尔值:参见一个Series的真值是不明确的。使用a.empty a.bool (), a.item (), a.any()或所有()。

用于解决该问题的Pandas界面稍微复杂一些——最好通过阅读问答来理解。这个问题特别涵盖了系列,但逻辑通常也适用于数据框架。如果需要更具体的指导,请参阅带有数据框架的If条件。