系列的真值是模棱两可的。使用a.empty,a.bool(),a.item(),a.any()或a.all()

时间:2016-04-28 17:46:31

标签: python pandas dataframe boolean filtering

有问题过滤我的结果数据框or条件。我希望我的结果df提取高于0.25且低于-0.25的所有列var值。

下面的这个逻辑给了我一个模糊的真值,但是当我在两个单独的操作中拆分这个过滤时它可以工作。这里发生了什么?不确定在何处使用建议的a.empty(), a.bool(), a.item(),a.any() or a.all()

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

11 个答案:

答案 0 :(得分:331)

orand python语句需要truth - 值。对于pandas,这些被认为是不明确的,因此您应该使用&#34;按位&#34; |(或)或&(和)操作:

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

为这些数据结构重载这些数据结构以产生元素or(或and)。

只是为此声明添加更多解释:

如果您希望获得bool的{​​{1}},则会引发异常:

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(). 的位置(您使用boolor and也发生了if 1}}和while):

>>> 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个语句外,还有几个隐藏一些bool调用的python函数(如anyallfilter,...)这些函数通常没有问题与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
    

如果您正在使用运算符,请确保因the operator precedence而正确设置括号。

pandas.Series {/ 3>}。{/}

如果在执行ifwhile时遇到异常,则异常中提到的替代方案更适合。我将简要解释其中的每一个:

  • 如果您想检查系列是否为空

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

    如果没有明确的布尔解释,Python通常会将len个容器(如listtuple,...)解释为真值。因此,如果您需要类似python的检查,您可以执行:if x.sizeif 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
    

答案 1 :(得分:30)

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

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

有关详细信息,请参阅文档中的Boolean Indexing

答案 2 :(得分:8)

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

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

答案 3 :(得分:6)

大熊猫使用按位'&''|'并将每个条件都包装在'()'

例如以下作品

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

但是没有适当括号的相同查询不会

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

答案 4 :(得分:1)

This excellent answer非常清楚地解释了发生了什么并提供了解决方案。我想添加另一个可能适用于类似情况的解决方案:使用query方法:

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

另见http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-query

(我正在使用的数据帧的一些测试表明,这种方法比在一系列布尔值上使用按位运算符慢一点:2 ms与870μs相比)

一条警告:至少有一种情况,这不是直截了当的,当列名恰好是python表达式时。我的列名为WT_38hph_IP_2WT_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

我想这是因为查询解析器试图从前两列创建一些内容,而不是使用第三列的名称来标识表达式。

提出了一种可行的解决方法here

答案 5 :(得分:1)

我遇到了相同的错误,并在pyspark数据帧中停滞了几天, 我能够通过将na值填充为0来成功解决它 来自2个字段的整数值。

答案 6 :(得分:1)

在熊猫中,您需要使用按位运算符|来代替or&来代替and,不能简单地使用python中的bool语句。 br />
对于复杂得多的过滤,请创建mask并将掩码应用于数据框。
将所有查询放入遮罩并应用。
假设

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

答案 7 :(得分:0)

在我的情况下,发生错误是因为我试图将整个系列传递给布尔条件检查,而不是单个值。尽管该系列仅包含一个元素。

(max_last >= (max_prev + 0.4*volatility)) and ((min_last + 0.2*volatility) >= min_prev)

上面的代码导致错误“ Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()”,将and更改为&并没有帮助。

ipdb> type(max_last >= (max_prev + 0.4*volatility))
<class 'pandas.core.series.Series'>
ipdb> type((min_last + 0.2*volatility) >= min_prev)
<class 'pandas.core.series.Series'>
ipdb> (max_last >= (max_prev + 0.4*volatility)).shape
(1,)

在检查条件之前从一系列中提取值有助于消除错误。

bull_condition = (max_last >= (max_prev + 0.4*volatility))[0] and ((min_last + 0.2*volatility) >= min_prev)[0]

此代码可以正常工作。

ipdb> type((max_last >= (max_prev + 0.4*volatility))[0])
<class 'numpy.bool_'>

答案 8 :(得分:0)

一件小事,浪费了我的时间。

在括号中放入条件(如果使用“ =”,“!=”进行比较),否则将引发此异常。 这将起作用

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

这不会

df[some condition conditional-operator some condition]

答案 9 :(得分:0)

我将尝试给出三种最常见方法的基准(也在上面提到):

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)]

但是,熊猫系列不支持*,并且NumPy Array的速度比熊猫数据帧快(慢约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)

答案 10 :(得分:0)

我在此命令中遇到错误:

如果 df != '': 通过

但是当我把它改成这个时它就起作用了:

如果 df 不是 '': 通过