一个系列的真实价值是不明确的。 使用a.empty,a.bool(),a.item(),a.any()或a.all()

有问题过滤我的结果数据框与条件。 我想我的结果df提取所有列高于0.25和低于-0.25的列var值。 下面的逻辑给了我一个模棱两可的真值,但是当我在两个单独的操作中分割这个过滤时,它是有效的。 这里发生了什么? 不知道在哪里使用build议的a.empty(),a.bool(),a.item(),a.any()或a.all()。

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

or和python语句需要truth 。 对于pandas这些被认为是不明确的,所以你应该使用“按位” | (或)或(和)操作:

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

对于这些types的数据结构来说,这些过载是为了产生元素or (或) and


只是为了更多的解释这个陈述:

当你想获得一个pandas.Seriesbool时抛出exception。 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也适用于, 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个语句之外,还有几个隐藏一些bool调用(比如anyallfilter ,…)的python函数,这些函数通常对于pandas.Series并不是问题,但是为了完整性,我想提一下这些。


在你的情况下,这个例外是没有用的,因为它没有提到正确的select 。 对于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工作。


exception中提到的替代方法更适合在ifwhile时遇到它。 我会很快解释其中的每一个:

  • 如果你想检查你的系列是否是空的

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

    如果没有明确的布尔解释,Python通常将容器的长度(如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 

对于布尔逻辑,使用&|

 np.random.seed(0) df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC')) >>> df ABC 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)] ABC 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 

当你有多个标准,你会得到多个列返回。 这就是连接逻辑不明确的原因。 分别使用and或对待每个列,因此您首先需要将该列减less为单个布尔值。 例如,查看每个列中的任何值或所有值是否为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 

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

 >>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]] ABC 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 

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

或者,也可以使用Operator模块。 更详细的信息在这里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)] ABC 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 

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

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

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

(一些我正在使用的数据框的testing表明,这种方法比在一系列布尔值上使用按位运算符要慢一些:2 ms vs. 870μs)

一个警告 :至less有一种情况,这不是直截了当的列名碰巧是pythonexpression式。 我有列名为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)"

我获得了以下exception级联:

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

我猜这是因为查询parsing器试图从前两列做出一些事情,而不是使用第三列的名称来标识expression式。

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