【问题标题】:ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()ValueError:具有多个元素的数组的真值不明确。使用 a.any() 或 a.all()
【发布时间】:2020-05-12 01:48:35
【问题描述】:

我刚刚在我的代码中发现了一个导致各种问题的逻辑错误。我无意中做了按位与而不是逻辑与

我将代码更改为:

r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]

到:

r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) and (r["dt"] <= enddate))
selected = r[mask]

令我惊讶的是,我收到了相当神秘的错误消息:

ValueError:具有多个元素的数组的真值是 模糊的。使用 a.any() 或 a.all()

为什么当我使用按位运算时没有发出类似的错误 - 我该如何解决这个问题?

【问题讨论】:

标签: python numpy


【解决方案1】:

r 是一个 numpy (rec) 数组。所以r["dt"] &gt;= startdate 也是一个(布尔值) 大批。对于 numpy 数组,&amp; 操作返回两个元素的和 布尔数组。

NumPy 开发人员认为没有一种普遍理解的评估方法 布尔上下文中的数组:它可能意味着 True 如果 any 元素是 True,或者如果所有元素都是True,则可能意味着True,或者如果数组长度不为零,则可能意味着True,仅列举三种可能性。

由于不同的用户可能有不同的需求和不同的假设,因此 NumPy 开发人员拒绝猜测,而是决定引发 ValueError 每当尝试在布尔上下文中评估数组时。申请and 两个 numpy 数组导致在布尔上下文中评估两个数组(通过 在 Python3 中调用 __bool__ 或在 Python2 中调用 __nonzero__

你的原始代码

mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]

看起来正确。但是,如果您确实想要and,那么请使用(a-b).any()(a-b).all() 而不是a and b

【讨论】:

  • 你是对的。原始代码是正确的。该错误似乎位于代码中的其他位置。
  • 很好的解释。然而,这意味着 NumPy 效率很低:它完全评估两个布尔数组,而有效的实现将在一个循环内评估 cond1(i)&&cond2(i),并跳过 cond2,除非 cond1 为真。
  • @JoachimWuttke:虽然np.allnp.any 能够短路,但传递给它的参数在np.allnp.any 有机会短路之前进行评估。为了做得更好,目前,您必须编写专门的 C/Cython 代码similar to this
  • 这不是他们能做的最好的举动......and&amp; 根本不是一回事,他们甚至没有相同的优先级。
【解决方案2】:

我遇到了同样的问题(即多条件索引,这里是在某个日期范围内查找数据)。 (a-b).any()(a-b).all() 似乎不起作用,至少对我来说是这样。

另外,我找到了另一种非常适合我所需功能的解决方案 (The truth value of an array with more than one element is ambigous when trying to index an array)。

不使用上面建议的代码,只需使用numpy.logical_and(a,b) 即可。在这里你可能想将代码重写为

selected  = r[numpy.logical_and(r["dt"] >= startdate, r["dt"] <= enddate)]

【讨论】:

    【解决方案3】:

    异常的原因是and隐式调用bool。首先在左操作数和(如果左操作数是True)然后在右操作数上。所以x and y 等价于bool(x) and bool(y)

    但是numpy.ndarray 上的bool(如果它包含多个元素)会抛出您看到的异常:

    >>> 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 中,但也隐含在 ifwhileor 中,因此以下任何示例也将失败:

    >>> 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 &lt; x &lt; 10只是2 &lt; x and x &lt; 10的另一种写法。而and 将调用bool: bool(2 &lt; x) and bool(x &lt; 10)

    andelement-wise 等效函数是 np.logical_and 函数,同样您可以使用 np.logical_or 等效于 or

    对于布尔数组 - 以及比较像 &lt;&lt;===!=&gt;=&gt; NumPy 数组返回布尔 NumPy 数组 - 你也可以使用 元素逐位函数(和运算符):np.bitwise_and&amp; 运算符)

    >>> 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】:

      如果您使用 pandas 为我解决的问题是当我有 NA 值时我试图进行计算,解决方案是运行:

      df = df.dropna()

      然后计算失败。

      【讨论】:

        【解决方案5】:

        接受@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 &gt; 0' to check that an array is not empty.

        这样做:

        • if np.array([]).size: print(1) 解决了这个错误。

        【讨论】:

          【解决方案6】:

          if-statement 比较存在数组时也会显示此类型的错误消息,例如 bool 或 int。例如:

          ... code snippet ...
          
          if dataset == bool:
              ....
          
          ... code snippet ...
          

          此子句将数据集作为数组,并且 bool 是 euhm 的“开门”...TrueFalse

          如果函数包含在 try-statement 中,您将收到带有 except Exception as error: 的不带错误类型的消息:

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

          【讨论】:

            【解决方案7】:

            try this=> numpy.array(r) 或 numpy.array(yourvariable) 后跟命令来比较你想要的。

            【讨论】:

              猜你喜欢
              • 2016-01-26
              • 2019-07-30
              • 2014-04-06
              • 2020-01-28
              相关资源
              最近更新 更多