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

oba*_*abs 286 python filtering boolean dataframe pandas

问题是使用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)]
Run Code Online (Sandbox Code Playgroud)

MSe*_*ert 454

orand蟒蛇语句需要truth-值.因为pandas这些被认为是不明确的,所以你应该使用"按位" |(或)或&(和)操作:

result = result[(result['var']>0.25) | (result['var']<-0.25)]
Run Code Online (Sandbox Code Playgroud)

对于这些类型的数据结构,这些都是重载的,以产生元素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().
Run Code Online (Sandbox Code Playgroud)

你击中的是一个操作符隐式将操作数转换为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().
Run Code Online (Sandbox Code Playgroud)

除了这些4个报表有几个Python函数的隐藏一些bool调用(如any,all,filter,...),这些都是通常没有问题与pandas.Series而是完整性我想提一提这些.


在您的情况下,异常并不真正有用,因为它没有提到正确的替代方案.对于andor你可以使用(如果你想要元素比较):

如果您正在使用运算符,请确保由于运算符优先级而正确设置括号.

几个逻辑numpy的功能,应该工作的pandas.Series.


如果你在做if或时遇到它,那么Exception中提到的替代方案更适合while.我将简要解释其中的每一个:

  • 如果要检查系列是否为:

    >>> x = pd.Series([])
    >>> x.empty
    True
    >>> x = pd.Series([1])
    >>> x.empty
    False
    
    Run Code Online (Sandbox Code Playgroud)

    如果没有明确的布尔解释,Python通常会将len容器的gth(例如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
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果你想检查你的系列的第一个也是唯一一个项目(比如.bool()但是对于不是布尔内容也可以):

    >>> x = pd.Series([100])
    >>> x.item()
    100
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果你想检查所有任何项目是否为零,不是空或不是假:

    >>> 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
    
    Run Code Online (Sandbox Code Playgroud)


Ale*_*der 31

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

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
Run Code Online (Sandbox Code Playgroud)

要了解发生了什么,每个比较都会得到一列布尔值,例如

df.C > 0.25
0     True
1    False
2    False
3     True
4     True
Name: C, dtype: bool
Run Code Online (Sandbox Code Playgroud)

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

# 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
Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

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


Ynj*_*jmh 17

对于初学者在 Pandas 中设置多个条件时,这是一个很常见的问题。一般来说,有两种可能的情况导致此错误:

\n

条件 1:Python 运算符优先级

\n

有一段布尔索引 | 索引和选择数据 \xe2\x80\x94 pandas 文档解释了这一点:

\n
\n

另一个常见的操作是使用布尔向量来过滤数据。运算符是:|for or&forand~for not。这些必须使用括号进行分组。

\n

df[\'A\'] > 2 & df[\'B\'] < 3默认情况下,Python 将计算诸如之类的表达式df[\'A\'] > (2 & df[\'B\']) < 3,而所需的计算顺序是(df[\'A\'] > 2) & (df[\'B\'] < 3)

\n
\n
# Wrong\ndf[\'col\'] < -0.25 | df[\'col\'] > 0.25\n\n# Right\n(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)\n
Run Code Online (Sandbox Code Playgroud)\n

有一些可能的方法可以去掉括号,我将在稍后介绍。

\n
\n

情况2:不正确的操作符/语句

\n

正如前面的引用中所解释的,您需要使用|for or&forand~for not

\n
# Wrong\n(df[\'col\'] < -0.25) or (df[\'col\'] > 0.25)\n\n# Right\n(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)\n
Run Code Online (Sandbox Code Playgroud)\n
\n

另一种可能的情况是您在if语句中使用布尔系列。

\n
# Wrong\nif pd.Series([True, False]):\n    pass\n
Run Code Online (Sandbox Code Playgroud)\n

很明显,Pythonif语句接受类似布尔的表达式,而不是 Pandas Series。您应该使用pandas.Series.any错误消息中列出的 或 方法将 Series 转换为您需要的值。

\n

例如:

\n
# Right\nif df[\'col\'].eq(0).all():\n    # If you want all column values equal to zero\n    print(\'do something\')\n\n# Right\nif df[\'col\'].eq(0).any():\n    # If you want at least one column value equal to zero\n    print(\'do something\')\n
Run Code Online (Sandbox Code Playgroud)\n
\n

我们先来说说第一种情况下转义括号的方法。

\n
    \n
  1. 使用 Pandas 数学函数

    \n

    Pandas定义了很多数学函数,包括比较,如下:

    \n\n

    结果,您可以使用

    \n
    df = df[(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)]\n\n# is equal to\n\ndf = df[df[\'col\'].lt(-0.25) | df[\'col\'].gt(0.25)]\n
    Run Code Online (Sandbox Code Playgroud)\n
  2. \n
  3. 使用pandas.Series.between()

    \n

    如果要选择两个值之间的行,可以使用pandas.Series.between

    \n
      \n
    • df[\'col].between(left, right)等于
      \n (left <= df[\'col\']) & (df[\'col\'] <= right)
    • \n
    • df[\'col].between(left, right, inclusive=\'left)等于
      \n (left <= df[\'col\']) & (df[\'col\'] < right)
    • \n
    • df[\'col].between(left, right, inclusive=\'right\')等于
      \n (left < df[\'col\']) & (df[\'col\'] <= right)
    • \n
    • df[\'col].between(left, right, inclusive=\'neither\')等于
      \n (left < df[\'col\']) & (df[\'col\'] < right)
    • \n
    \n
    df = df[(df[\'col\'] > -0.25) & (df[\'col\'] < 0.25)]\n\n# is equal to\n\ndf = df[df[\'col\'].between(-0.25, 0.25, inclusive=\'neither\')]\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
  5. 使用pandas.DataFrame.query()

    \n

    之前引用的文档有一章query()方法”很好地解释了这一点。

    \n

    pandas.DataFrame.query()可以帮助您选择带有条件字符串的 DataFrame。在查询字符串中,您可以使用按位运算符 (&|) 及其布尔表兄弟 (andor)。此外,您可以省略括号,但出于可读性原因我不建议这样做。

    \n
    df = df[(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)]\n\n# is equal to\n\ndf = df.query(\'col < -0.25 or col > 0.25\')\n
    Run Code Online (Sandbox Code Playgroud)\n
  6. \n
  7. 使用pandas.DataFrame.eval()

    \n

    pandas.DataFrame.eval()评估描述 DataFrame 列操作的字符串。因此,我们可以使用这个方法来构建我们的多个条件。语法与 相同pandas.DataFrame.query()

    \n
    df = df[(df[\'col\'] < -0.25) | (df[\'col\'] > 0.25)]\n\n# is equal to\n\ndf = df[df.eval(\'col < -0.25 or col > 0.25\')]\n
    Run Code Online (Sandbox Code Playgroud)\n

    pandas.DataFrame.query()并且pandas.DataFrame.eval()可以做比我在这里描述的更多的事情。建议您阅读他们的文档并享受其中的乐趣。

    \n
  8. \n
\n


Cản*_*yễn 8

或者,您也可以使用操作员模块.更详细的信息在这里是Python文档

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
Run Code Online (Sandbox Code Playgroud)


bli*_*bli 6

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

\n
df = df.query("(col > 0.25) or (col < -0.25)")\n
Run Code Online (Sandbox Code Playgroud)\n

另请参见索引和选择数据

\n

(对我当前正在使用的数据帧进行的一些测试表明,此方法比在一系列布尔值上使用按位运算符要慢一些:2\xc2\xa0ms 与 870\xc2\xa0\xc2\xb5s)

\n

一条警告:至少有一种情况并不简单,那就是列名恰好是 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)"

\n

我获得了以下异常级联:

\n
    \n
  • KeyError: \'log2\'
  • \n
  • UndefinedVariableError: name \'log2\' is not defined
  • \n
  • ValueError: "log2" is not a supported function
  • \n
\n

我猜发生这种情况是因为查询解析器试图从前两列中获取某些内容,而不是使用第三列的名称来标识表达式。

\n

这里提出了一种可能的解决方法。

\n


小智 6

好吧熊猫使用按位'&''|' 并且每个条件都应该用'()'包装

例如以下作品

data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]
Run Code Online (Sandbox Code Playgroud)

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

data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]
Run Code Online (Sandbox Code Playgroud)