python—序列的真值是不明确的使用a.empty、a.bool()、a.item()、a.any()或a.all()

9rbhqvlz  于 2021-08-20  发布在  Java
关注(0)|答案(10)|浏览(371)

使用 or 条件我想要我的结果 df 提取所有列 var 高于0.25且低于-0.25的值。
下面的逻辑为我提供了一个模糊的真值,但当我将此过滤拆分为两个单独的操作时,它仍然有效。这里发生了什么?不确定在哪里使用建议的 a.empty(), a.bool(), a.item(),a.any() or a.all() .

result = result[(result['var'] > 0.25) or (result['var'] < -0.25)]
bnlyeluc

bnlyeluc1#

这个 orand python语句需要 truth -价值观。对于 pandas 这些被认为是不明确的,所以您应该使用“按位” | (或)或 & (和)业务:

result = result[(result['var']>0.25) | (result['var']<-0.25)]

对于这些类型的数据结构,它们被重载以生成元素级的数据 or (或 and ).
只是想对这句话再做一些解释:
当您想要获取 bool 属于 pandas.Series :

>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

您找到的是运算符将操作数隐式转换为 bool (你曾经 or 但这种情况也发生在 and , ifwhile ):

>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

除了这4条语句之外,还有几个python函数隐藏了一些 bool 电话(如 any , all , filter ,…)这些通常不存在问题 pandas.Series 但为了完整性,我想提到这些。
在您的案例中,异常并没有真正的帮助,因为它没有提到正确的替代方案。对于 andor 您可以使用(如果希望进行元素级比较): numpy.logical_or :

>>> import numpy as np
>>> np.logical_or(x, y)

或者仅仅是 | 接线员:

>>> x | y
``` `numpy.logical_and` :

np.logical_and(x, y)

或者仅仅是 `&` 接线员:

x & y

如果使用的是运算符,请确保正确设置括号,因为运算符的优先级。
有几个逻辑numpy函数可以使用 `pandas.Series` .
如果您在执行操作时遇到异常,则异常中提到的备选方案更合适 `if` 或 `while` . 我将很快解释其中的每一个:
如果要检查序列是否为空:

x = pd.Series([])
x.empty
True
x = pd.Series([1])
x.empty
False

python通常解释 `len` 集装箱总长度(如 `list` ,  `tuple` ,…)作为真值,如果它没有明确的布尔解释。因此,如果需要类似python的检查,可以执行以下操作: `if x.size` 或 `if not x.empty` 而不是 `if x` .
如果你的 `Series` 包含且仅包含一个布尔值:

x = pd.Series([100])
(x > 50).bool()
True
(x < 50).bool()
False

如果您想检查系列的第一项也是唯一一项(如 `.bool()` 但即使对于非布尔内容也有效):

x = pd.Series([100])
x.item()
100

如果要检查所有或任何项是否为零、是否为空或是否为假:

x = pd.Series([0, 1, 2])
x.all() # because one element is zero
False
x.any() # because one (or more) elements are non-zero
True

ryoqjall

ryoqjall2#

对于布尔逻辑,使用 &| .

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))

>>> df
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
2  0.950088 -0.151357 -0.103219
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

>>> df.loc[(df.C > 0.25) | (df.C < -0.25)]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

要查看发生了什么,您可以为每个比较获取一列布尔值,例如。

df.C > 0.25
0     True
1    False
2    False
3     True
4     True
Name: C, dtype: bool

当您有多个条件时,将返回多个列。这就是连接逻辑不明确的原因。使用 andor 分别处理每个列,因此首先需要将该列减少为单个布尔值。例如,查看每列中的任何值或所有值是否为真。


# Any value in either column is True?

(df.C > 0.25).any() or (df.C < -0.25).any()
True

# All values in either column is True?

(df.C > 0.25).all() or (df.C < -0.25).all()
False

实现相同功能的一种复杂方法是将所有这些列压缩在一起,并执行适当的逻辑。

>>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

有关更多详细信息,请参阅文档中的布尔索引。

xuo3flqw

xuo3flqw3#

Pandas是按位使用的
& | 每个条件都应该用一个 () 比如下面的作品

data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]

但没有适当括号的同一个查询不适用

data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]
eit6fx6z

eit6fx6z4#

或者,您也可以使用操作员模块。更详细的信息在这里

import operator
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
df.loc[operator.or_(df.C > 0.25, df.C < -0.25)]

          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.4438
2hh7jdfx

2hh7jdfx5#

这个极好的答案很好地解释了正在发生的事情,并提供了一个解决方案。我想添加另一个可能适用于类似情况的解决方案:使用 query 方法:

result = result.query("(var > 0.25) or (var < -0.25)")

另见http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-询问。
(我目前正在使用的 Dataframe 的一些测试表明,这种方法比在一系列布尔值上使用逐位运算符要慢一点:2毫秒比870µs)
一条警告:至少有一种情况是,列名恰好是python表达式,这种情况并不简单。我有一些列被命名为 WT_38hph_IP_2 , WT_38hph_input_2log2(WT_38hph_IP_2/WT_38hph_input_2) 并希望执行以下查询: "(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)" 我获得了以下异常级联: KeyError: 'log2' UndefinedVariableError: name 'log2' is not defined ValueError: "log2" is not a supported function 我猜这是因为查询解析器试图从前两列生成一些内容,而不是用第三列的名称标识表达式。
这里提出了一种可能的解决方法。

lmyy7pcs

lmyy7pcs6#

我遇到了相同的错误,并被pyspark Dataframe 暂停了几天,我能够通过使用0填充na值成功地解决它,因为我比较了两个字段中的整数值。

e5nszbig

e5nszbig7#

您需要使用位运算符 | 而不是 or& 而不是 and 在pandas中,不能简单地使用python中的bool语句。
对于更复杂的过滤,请创建一个 mask 并在 Dataframe 上应用掩码。
将所有查询放入掩码并应用它。
假设,

mask = (df["col1"]>=df["col2"]) & (stock["col1"]<=df["col2"])
df_new = df[mask]
14ifxucb

14ifxucb8#

我将尝试给出三种最常见的方法的基准(如上所述):

from timeit import repeat

setup = """
import numpy as np;
import random;
x = np.linspace(0,100);
lb, ub = np.sort([random.random() * 100, random.random() * 100]).tolist()
"""
stmts = 'x[(x > lb) * (x <= ub)]', 'x[(x > lb) & (x <= ub)]', 'x[np.logical_and(x > lb, x <= ub)]'

for _ in range(3):
    for stmt in stmts:
        t = min(repeat(stmt, setup, number=100_000))
        print('%.4f' % t, stmt)
    print()

结果:

0.4808 x[(x > lb) * (x <= ub)]
0.4726 x[(x > lb) & (x <= ub)]
0.4904 x[np.logical_and(x > lb, x <= ub)]

0.4725 x[(x > lb) * (x <= ub)]
0.4806 x[(x > lb) & (x <= ub)]
0.5002 x[np.logical_and(x > lb, x <= ub)]

0.4781 x[(x > lb) * (x <= ub)]
0.4336 x[(x > lb) & (x <= ub)]
0.4974 x[np.logical_and(x > lb, x <= ub)]

但是 * panda系列中不支持,并且numpy阵列比pandas Dataframe 快(大约慢1000倍,请参见编号):

from timeit import repeat

setup = """
import numpy as np;
import random;
import pandas as pd;
x = pd.DataFrame(np.linspace(0,100));
lb, ub = np.sort([random.random() * 100, random.random() * 100]).tolist()
"""
stmts = 'x[(x > lb) & (x <= ub)]', 'x[np.logical_and(x > lb, x <= ub)]'

for _ in range(3):
    for stmt in stmts:
        t = min(repeat(stmt, setup, number=100))
        print('%.4f' % t, stmt)
    print()

结果:

0.1964 x[(x > lb) & (x <= ub)]
0.1992 x[np.logical_and(x > lb, x <= ub)]

0.2018 x[(x > lb) & (x <= ub)]
0.1838 x[np.logical_and(x > lb, x <= ub)]

0.1871 x[(x > lb) & (x <= ub)]
0.1883 x[np.logical_and(x > lb, x <= ub)]

注意:添加一行代码 x = x.to_numpy() 将需要大约20µs。
对于那些喜欢 %timeit :

import numpy as np
import random
lb, ub = np.sort([random.random() * 100, random.random() * 100]).tolist()
lb, ub
x = pd.DataFrame(np.linspace(0,100))

def asterik(x):
    x = x.to_numpy()
    return x[(x > lb) * (x <= ub)]

def and_symbol(x):
    x = x.to_numpy()
    return x[(x > lb) & (x <= ub)]

def numpy_logical(x):
    x = x.to_numpy()
    return x[np.logical_and(x > lb, x <= ub)]

for i in range(3):
    %timeit asterik(x)
    %timeit and_symbol(x)
    %timeit numpy_logical(x)
    print('\n')

结果:

23 µs ± 3.62 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
35.6 µs ± 9.53 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
31.3 µs ± 8.9 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

21.4 µs ± 3.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
21.9 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
21.7 µs ± 500 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

25.1 µs ± 3.71 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
36.8 µs ± 18.3 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
28.2 µs ± 5.97 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
stszievb

stszievb9#

一件小事,浪费了我的时间。
输入条件(如果使用“=”、“!=”)进行比较)在括号中,不这样做也会引发此异常。这会奏效的

df[(some condition) conditional operator (some conditions)]

这不会

df[some condition conditional-operator some condition]
8zzbczxx

8zzbczxx10#

此命令中出现错误:
如果df!='':通过
但当我把它改成这样时,它起了作用:
如果df不是“”:通过

相关问题