设x为NumPy数组。以下几点:
(x > 1) and (x < 3)
给出错误信息:
ValueError:包含多个元素的数组的真值为 模糊。使用a.any()或a.all()
我怎么解决这个问题?
设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__)。
其他回答
导致
当代码试图将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条件。
如果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__)。
通常,当比较两个单个数字时,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!")
我也遇到了同样的问题(即多条件索引,这里是在某个日期范围内查找数据)。(a-b).any()或(a-b).all()似乎不起作用,至少对我来说是这样。
或者,我找到了另一个解决方案,它完美地满足了我想要的功能(当尝试索引数组时,具有多个元素的数组的真值是不明确的)。
与其使用上面建议的代码,不如使用:
numpy.logical_and(a, b)
以@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)解决了错误。