ValueError:具有多个元素的数组的真值不明确。请使用 a.any() 或 a.all()
- 2024-11-19 08:38:00
- admin 原创
- 15
问题描述:
设为x
NumPy 数组。以下内容:
(x > 1) and (x < 3)
给出错误信息:
ValueError:具有多个元素的数组的真值不明确。请使用 a.any() 或 a.all()
我该如何修复这个问题?
解决方案 1:
如果a
和b
是布尔 NumPy 数组,则该&
操作返回它们的元素与:
a & b
这将返回一个布尔数组。要将其缩减为单个布尔值,请使用
(a & b).any()
或者
(a & b).all()
注意:如果a
和b
是非布尔数组,则考虑使用(a - b).any()
或(a - b).all()
代替。
基本原理
NumPy 开发人员认为,没有一种普遍理解的方法来在布尔上下文中评估数组:它可能意味着任何元素是否为True
,或者它可能意味着所有元素是否为,或者数组是否具有非零长度,仅列举三种可能性。True
`TrueTrue
True`
由于不同的用户可能有不同的需求和不同的假设,NumPy 开发人员拒绝猜测,而是决定在ValueError
尝试在布尔上下文中评估数组时引发。应用于两个 numpy 数组会导致这两个数组在布尔上下文中进行评估(通过在 Python3 或Python2 中and
调用)。__bool__
`__nonzero__`
解决方案 2:
我遇到了同样的问题(即使用多条件索引,这里是在特定日期范围内查找数据)。(a-b).any()
或(a-b).all()
似乎不起作用,至少对我来说是这样。
另外,我找到了另一个解决方案,它完全可以满足我的需求(当尝试索引数组时,具有多个元素的数组的真值是不明确的)。
不要使用上面建议的代码,而是使用:
numpy.logical_and(a, b)
解决方案 3:
出现异常的原因是and
隐式调用bool
。首先对左操作数执行 ,True
然后(如果左操作数是 )对右操作数执行 。因此x and y
等同于bool(x) and bool(y)
。
但是bool
,numpy.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 and x < 10
。 并且and
将调用bool
:bool(2 < x) and bool(x < 10)
。
的元素等价物and
是np.logical_and
函数,同样地,你可以使用np.logical_or
来等价于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 文档中找到逻辑和二元函数的完整列表:
“逻辑函数”
“二元运算”
解决方案 4:
原因
每当代码尝试将 Numpy 数组转换为布尔值(即检查其真值,如错误消息中所述)时,就会发生此错误。对于给定的数组a
,可能会发生以下情况:
明确地,通过使用
bool(a)
。隐式使用布尔逻辑运算符:
a and a
,,a or a
。not a
隐式使用内置
any
和all
函数。(这些函数可以接受单个数组,无论它有多少维;但不能接受数组的列表、元组、集合等。)在
if
语句中隐式地使用if a:
。虽然通常可以在语句中使用任何 Python 对象if
,但 Numpy 数组故意破坏了此功能 - 以帮助避免逻辑错误。
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
并不意味着“给出True
或False
回答: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])
修复表达式
如果代码明确转换为
bool
,则根据需要选择将.any
或.all
应用于结果。顾名思义,.any
将数组折叠为单个布尔值,指示任何值是否为真;.all
将检查所有值是否为真。
>>> (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
如果目标是a
逐个元素转换为布尔值,请使用a.astype(bool)
、 或 (仅适用于数字输入)a != 0
。
如果代码使用布尔逻辑(
and
/or
/not
),则分别
使用按位运算符(&
/|
/ ):~
>>> ((a % 2) != 0) & ((a % 3) != 0) # N.B. `&`, not `and`
array([False, True, False, False, False, True, False, True, False])
请注意,按位运算符还提供^
对布尔输入的排他或的访问;逻辑运算符不支持这一点(没有xor
)。
对于需要以相同方式组合的数组列表(或其他序列)(即内置函数
all
和any
函数的作用),请构建相应的(N+1)维数组,并沿轴 0
使用np.all
或:np.any
>>> 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) or (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])
此索引技术对于查找满足条件的值也很有用。基于上一个sieves
示例:
>>> 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
Pandas 库依赖 Numpy,并DataFrame
在 Numpy 的数组类型之上实现其类型。所有相同的推理都适用,因此 Pandas Series
(和DataFrame
)对象不能用作布尔值:请参阅系列的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。
用于解决该问题的 Pandas 界面有点复杂 - 最好通过阅读该问答来理解。该问题具体涉及 Series,但逻辑通常也适用于 DataFrames。另请参阅带有数据框的 If 条件,以获取有关将条件逻辑应用于 DataFrame 的更具体指导。
解决方案 5:
如果您使用的方法可以pandas
为我解决问题,那么当我有 NA 值时我试图进行计算,解决方案是运行:
df = df.dropna()
此后计算失败。
解决方案 6:
谈到@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)
--> 没有 ValueError,但是: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)
--> 没有 ValueError,但是对于包含许多元素的数组同样没有帮助。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)
:引用此用户的评论,这也行不通。这是因为 nonp.array
永远不可能与 是同一个对象None
- 该对象是唯一的 - 因此无论它是否为空,它总是会匹配None
(即永远不会匹配)。is None
这样做:
if np.array([]).size: print(1)
解决了错误。
解决方案 7:
在对数组和 bool 或 int 进行比较时,也会显示此类型的错误消息if-statement
。例如:
... code snippet ...
if dataset == bool:
....
... code snippet ...
此子句将数据集作为数组,并且 bool 是 euhm“打开门”......True
或False
。
如果函数被包装在try-statement
您将收到except Exception as error:
不带错误类型的消息中:
具有多个元素的数组的真值不明确。请使用 a.any() 或 a.all()
解决方案 8:
通常,当比较两个单个数字时,Python 常规代码可以正常工作,但在数组内部有一些数字(多个数字)需要并行处理。
例如,我们假设以下情况:
a = np.array([1, 2, 3])
b = np.array([2, 3, 4])
您想检查一下吗if b >= a:
?
因为a
和b
不是一位数,而您实际上的意思是如果b
中的每个元素都大于中的相似数字a
,那么您应该使用以下命令:
if (b >= a).all():
print("b is greater than a!")
解决方案 9:
有一些例子可以完美地回答这个问题。但我仍然想更深入地了解这个错误以及这个错误的根源。
在这个表达式中,我们在两个数组之间(x > 1) and (x < 3)
执行操作,因此我们假设返回的数组是,类似地,我们得到之后,可以将其写成。logical and
`NumPyNumPy
(x > 1)numpy_array1
(x < 3)numpy_array2
numpy_array1 and numpy_array2`
当我们在logical and
两个对象之间执行操作时,它们会被传递给bool
函数以获取boolean
值。因此numpy_array1 and numpy_array2
计算结果为bool(numpy_array1) and bool(numpy_array2)
bool(numpy_array1)
将调用数组__bool__
的方法,并在bool方法中执行一些比较。NumPy
如果数组为空,则引发
DeprecationWarning
并返回False
。如果数组有一个元素,则返回一个
boolean
值。如果有多个元素,则引发值错误(
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
)
通过一个简单的程序可以进一步理解这一点:
import warnings
class Plan:
def __init__(self):
self.values = []
def append(self, val):
self.values.append(val)
def empty(self):
self.values.clear()
def __bool__(self):
size = len(self.values)
if size == 0:
warnings.warn("The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error.", DeprecationWarning)
return False
if size == 1:
return bool(self.values[0])
raise ValueError("ValueError: The truth value of an array with more than one element is ambiguous.")
让我们实例化Plan class
并使用它的对象:
plan = Plan()
bool(plan)
DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error.
warnings.warn("The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error.", DeprecationWarning)
False
plan = Plan()
plan.append(4)
bool(plan)
True
plan = Plan()
plan.append(False)
bool(plan)
False
plan = Plan()
plan.append(False)
plan.append(False)
bool(plan)
ValueError: ValueError: The truth value of an array with more than one element is ambiguous.
这就是当我们调用时当有多个元素时if numpy_arr
会抛出的原因,因为会被评估为。ValueError
`numpy_arrif numpy_arr
if bool(numpy_arr)`
解决方案 10:
对我来说,这个错误发生在测试中,代码错误如下:
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)
解决方案 11:
最简单的答案是使用“&”而不是“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])
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件