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

(x > 1) and (x < 3)

给出错误信息:

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

我怎么解决这个问题?


当前回答

导致

当代码试图将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条件。

其他回答

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

... code snippet ...

if dataset == bool:
    ....

... code snippet ...

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

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

具有多个元素的数组的真值是不明确的。使用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__)。

以@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)解决了错误。

最简单的答案是用“&”而不是“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])

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

Df = Df .dropna()

在那之后,计算失败了。