我想用一个或条件来过滤我的数据帧,以保持特定列的值超出范围[-0.25,0.25]的行。我尝试了:
df = df[(df['col'] < -0.25) or (df['col'] > 0.25)]
但我得到了错误:
级数的真值不明确。使用a.empty、a.bool()、a.item()、.any()或.all()
我想用一个或条件来过滤我的数据帧,以保持特定列的值超出范围[-0.25,0.25]的行。我尝试了:
df = df[(df['col'] < -0.25) or (df['col'] > 0.25)]
但我得到了错误:
级数的真值不明确。使用a.empty、a.bool()、a.item()、.any()或.all()
当前回答
这个出色的答案很好地解释了正在发生的事情,并提供了解决方案。我想添加另一种可能适用于类似情况的解决方案:使用查询方法:
df = df.query("(col > 0.25) or (col < -0.25)")
请参见索引和选择数据。
(我目前正在使用的数据帧的一些测试表明,这种方法比在一系列布尔运算中使用逐位运算符要慢一点:2毫秒对870µs)
一条警告:至少有一种情况是列名恰好是Python表达式,这一点并不简单。我的列名为WT_38hph_IP_2、WT_38ph_input_2和log2(WT_38kph_IP_2/WT_38lph_input_2),希望执行以下查询:“(log2(WT_38hph_IP_2/WT_38hph_input_3)>1)和(WT_38h ph_IP_2>20)”
我获得了以下异常级联:
键错误:“log2”UndefinedVariableError:未定义名称“log2”ValueError:“log2”不是受支持的函数
我想发生这种情况是因为查询解析器试图从前两列中提取一些内容,而不是用第三列的名称来标识表达式。
这里提出了一种可能的解决方法。
其他回答
or和Python语句需要真值。对于panda,这些被认为是不明确的,因此应该使用“按位”|(或)或&(和)操作:
df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]
对于这些类型的数据结构,它们被重载,以生成元素或和。
只是为了给这句话补充一些解释:
当你想得到熊猫的嘘声时,会抛出异常。系列:
>>> 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().
您到达了一个位置,在该位置运算符隐式地将操作数转换为布尔值(您使用了或,但它也适用于和、if和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().
除了这四个语句之外,还有几个Python函数隐藏了一些bool调用(比如any、all、filter…)。pandas.Series通常不会有问题,但为了完整起见,我想提一下这些。
在您的案例中,例外并没有真正的帮助,因为它没有提到正确的替代方案。对于和和或,如果要按元素进行比较,可以使用:
numpy.logical_或:>>>将numpy导入为np>>>np.逻辑或(x,y)或简单地使用|运算符:>>>x |年numpy.logical_and:>>>np.逻辑和(x,y)或简单地使用&运算符:>>>x和y
如果您使用的是运算符,请确保正确设置括号,因为运算符优先。
有几个逻辑NumPy函数可以在pandas.Series上工作。
如果在执行if或while时遇到异常,则异常中提到的备选方案更适合。我将很快解释其中的每一个:
如果要检查系列是否为空:>>>x=pd.系列([])>>>x.空真的>>>x=pd.系列([1])>>>x.空错误如果没有明确的布尔解释,Python通常会将容器的长度(如列表、元组等)解释为真值。因此,如果您想进行类似Python的检查,可以这样做:如果x.size或如果不是x.empty,而不是如果x。如果“系列”包含且仅包含一个布尔值:>>>x=pd.系列([100])>>>(x>50).bool()真的>>>(x<50).bool()错误如果您想检查Series的第一项也是唯一一项(例如.bool(),但它甚至适用于非布尔内容):>>>x=pd.系列([100])>>>x.项()100如果要检查所有或任何项目是否不为零、不为空或不为False:>>>x=pd.系列([0,1,2])>>>x.all()#因为一个元素为零错误>>>x.any()#,因为一个(或多个)元素非零真的
我在这个命令中遇到了一个错误:
if df != '':
pass
但当我把它改成这样时,它起了作用:
if df is not '':
pass
您需要在panda中使用按位运算符|而不是或和&,而不是和。您不能简单地使用python中的bool语句。
对于非常复杂的过滤,请创建一个掩码并在数据帧上应用该掩码。将所有查询放入掩码并应用它,
mask = (df["col1"]>=df["col2"]) & (stock["col1"]<=df["col2"])
df_new = df[mask]
我遇到了同样的错误,并在PySpark数据帧中停滞了几天。由于我比较了两个字段中的整数值,所以通过用0填充na值,我成功地解决了这个问题。
对于布尔逻辑,请使用&和|。
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
当您有多个条件时,将返回多个列。这就是联接逻辑不明确的原因。使用和或或单独处理每一列,因此首先需要将该列减少为一个布尔值。例如,查看每个列中的任何值或所有值是否为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)]]
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
有关详细信息,请参阅文档中的布尔索引。