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

2024-11-19 08:38:00
admin
原创
15
摘要:问题描述:设为xNumPy 数组。以下内容:(x > 1) and (x < 3) 给出错误信息:ValueError:具有多个元素的数组的真值不明确。请使用 a.any() 或 a.all()我该如何修复这个问题?解决方案 1:如果a和b是布尔 NumPy 数组,则该&操作返回它们的元素...

问题描述:

设为xNumPy 数组。以下内容:

(x > 1) and (x < 3)

给出错误信息:

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

我该如何修复这个问题?


解决方案 1:

如果ab是布尔 NumPy 数组,则该&操作返回它们的元素与:

a & b

这将返回一个布尔数组。要将其缩减为单个布尔,请使用

(a & b).any()

或者

(a & b).all()

注意:如果ab是非布尔数组,则考虑使用(a - b).any()(a - b).all()代替。


基本原理

NumPy 开发人员认为,没有一种普遍理解的方法来在布尔上下文中评估数组:它可能意味着任何元素是否为True,或者它可能意味着所有元素是否为,或者数组是否具有非零长度,仅列举三种可能性。True`TrueTrueTrue`

由于不同的用户可能有不同的需求和不同的假设,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)

但是boolnumpy.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,但在ifwhile、中也是如此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将调用boolbool(2 < x) and bool(x < 10)

的元素等价物andnp.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 anot a

  • 隐式使用内置anyall函数。(这些函数可以接受单个数组,无论它有多少维;但不能接受数组的列表、元组、集合等。)

  • 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 并不意味着“给出TrueFalse回答: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)。

  • 对于需要以相同方式组合的数组列表(或其他序列)(即内置函数allany函数的作用),请构建相应的(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“打开门”......TrueFalse

如果函数被包装在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:

因为ab不是一位数,而您实际上的意思是如果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_array2numpy_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_arrif 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])
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用