为什么链式(间隔)比较在numpy数组上不起作用? [英] Why doesn't chained (interval) comparison work on numpy arrays?

查看:74
本文介绍了为什么链式(间隔)比较在numpy数组上不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

a < b < c是Python中的链接表达式,它看起来它适用于定义了适当比较运算符的对象,但不适用于numpy数组.为什么?

a < b < c is an chained expression in Python, and it looks like it works on objects with appropriate comparison operators defined, but it doesn't work on numpy arrays. Why?

import numpy as np

class ContrarianContainer(object):
    def __init__(self, x):
        self.x = x
    def __le__(self, y):
        return not self.x <= y
    def __lt__(self, y):
        return not self.x < y
    def __ge__(self, y):
        return not self.x >= y
    def __gt__(self, y):
        return not self.x > y
    def __eq__(self, y):
        return not self.x == y
    def __ne__(self, y):
        return not self.x != y

numlist = np.array([1,2,3,4])
for n in numlist:
    print 0 < n < 3.5
for n in numlist:
    print 0 > ContrarianContainer(n) > 3.5
print 0 < numlist < 3.5

此打印:

True
True
True
False
True
True
True
False
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-187-277da7750148> in <module>()
      4 for n in numlist:
      5     print 0 < n < 3.5
----> 6 print 0 < numlist < 3.5

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

推荐答案

因此文档说:

形式上,如果a,b,c,...,y,z是表达式,而op1,op2,...,opN是比较运算符,则op1 b op2 c ... y opN z等效于op1 b和b op2 c和... y opN z,不同之处在于每个表达式最多只能计算一次.

Formally, if a, b, c, ..., y, z are expressions and op1, op2, ..., opN are comparison operators, then a op1 b op2 c ... y opN z is equivalent to a op1 b and b op2 c and ... y opN z, except that each expression is evaluated at most once.

(但是在两种情况下,当x< y为假时,z都不会被评估).

(but in both cases z is not evaluated at all when x < y is found to be false).

对于标量

In [20]: x=5
In [21]: 0<x<10
Out[21]: True
In [22]: 0<x and x<10
Out[22]: True

但是带有数组

In [24]: x=np.array([4,5,6])    
In [25]: 0<x and x<10
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

当在需要标量布尔值的上下文中使用numpy布尔值时,会出现此ValueError.

This ValueError arises when a numpy boolean is used in a context that expects a scalar boolean.

In [26]: (0<x)
Out[26]: array([ True,  True,  True], dtype=bool)

In [30]: np.array([True, False]) or True
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [33]: if np.array([True, False]): print('yes')
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

它评估0<x,但是甚至没有评估x<10,因为它不能在or/and上下文中使用结果布尔数组. numpy定义了|&,但没有定义orand.

It evaluates the 0<x, but doesn't even get to evaluating the x<10, because it can't use the resulting boolean array in a or/and context. numpy has defined | and &, but not or or and.

In [34]: (0<x) & x<10
Out[34]: array([ True,  True,  True], dtype=bool)

使用0 < x <10时,我们隐式地期望评估标量链接表达式的矢量化版本.

When we use 0 < x <10 we are implicitly expecting to evaluate a vectorized version of the scalar chained expression.

In [35]: f = np.vectorize(lambda x: 0<x<10, otypes=[bool])
In [36]: f(x)
Out[36]: array([ True,  True,  True], dtype=bool)
In [37]: f([-1,5,11])
Out[37]: array([False,  True, False], dtype=bool)

请注意,尝试将链接应用于列表甚至都不会超过第一个<:

Note that attempting to apply chaining to a list doesn't even get past the first <:

In [39]: 0 < [-1,5,11]
TypeError: unorderable types: int() < list()


这组表达式表示&运算符优先于<运算符:


This set of expressions indicates that the & operator has precedence over the < operator:

In [44]: 0 < x & x<10
ValueError ...

In [45]: (0 < x) & x<10
Out[45]: array([ True,  True,  True], dtype=bool)

In [46]: 0 < x & (x<10)
Out[46]: array([False,  True, False], dtype=bool)

In [47]: 0 < (x & x)<10
ValueError...

因此安全版本为(0 < x) & (x<10),请确保在&之前对所有<进行评估.

So the safe version is (0 < x) & (x<10), making sure that all < are evaluated before the &.

这篇关于为什么链式(间隔)比较在numpy数组上不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆