我想用一个或条件来过滤我的数据帧,以保持特定列的值超出范围[-0.25,0.25]的行。我尝试了:

df = df[(df['col'] < -0.25) or (df['col'] > 0.25)]

但我得到了错误:

级数的真值不明确。使用a.empty、a.bool()、a.item()、.any()或.all()


当前回答

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

将条件(如果使用“=”,“!=”进行比较)放在括号中。未能做到这一点也会引发这种例外。

这将起作用:

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

这不会:

df[some condition conditional-operator some condition]

其他回答

Pandas使用位&|。此外,每个条件都应该包装在()内。

这是有效的:

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

但没有括号的相同查询不会:

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

我遇到了同样的错误,并在PySpark数据帧中停滞了几天。由于我比较了两个字段中的整数值,所以通过用0填充na值,我成功地解决了这个问题。

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

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”不是受支持的函数

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

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

或者,也可以使用操作员模块。更多详细信息请参见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

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

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)