设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条件。

其他回答

出现异常的原因是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文档中找到:

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

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

如果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__)。

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

Df = Df .dropna()

在那之后,计算失败了。

导致

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