使用任意数量的条件过滤Pandas Dataframe

时间:2017-11-06 23:13:02

标签: python pandas

我对使用Pandas进行基本过滤和查询感到满意。例如,如果我有一个名为df的数据框,我可以df[df['field1'] < 2]df[df['field2'] < 3]。我还可以将多个标准链接在一起,例如:

df[(df['field1'] < 3) & (df['field2'] < 2)]

如果我事先不知道需要使用多少条件,该怎么办?有没有办法去&#34;链&#34;任意数量的这些操作在一起?我想传递一个过滤器列表,例如[('field1', 3), ('field2', 2), ('field3', 4)],这会导致将这三个条件链接在一起。

谢谢!

6 个答案:

答案 0 :(得分:3)

pandas Series对象具有少于,大于等操作作为可以调用的方法。因此df['field1'] < 3变为df['field1'].lt(3)。这不是非常重要,但它使代码更具可读性。

要实现您的要求,您可以使用functools中的reduce函数和运算符包中的and_(相当于&)。

from functools import reduce
from operator import and_

reduce(and_, (df.field1.lt(3), df.field2.lt(2), df.field3.lt(4)))

答案 1 :(得分:3)

方法1
使用pd.DataFrame.query

c = [('field1', 3), ('field2', 2), ('field3', 4)]
f = '{0[0]} < {0[1]}'.format

df.query(' & '.join(f(t) for t in c))

方法2

c = [('field1', 3), ('field2', 2), ('field3', 4)]

df[df[[t[0] for t in c]].lt([t[1] for t in c]).all(1)]

方法3
pd.Series中创建c,然后进行比较

c = [('field1', 3), ('field2', 2), ('field3', 4)]

s = pd.Series(dict(c))

df[df[s.index].lt(s).all(1)]

答案 2 :(得分:1)

add之类的东西,然后使用all,你得到布尔值你需要

df1[['f1','f2','f3']].add([-2,-3,-4]).lt(0).all(1)

答案 3 :(得分:0)

我相信reduce( (lambda x, y: x & (df[y[0]]<y[1])), list_of_filters )会这样做。

答案 4 :(得分:0)

你可以遍历条件并通过&(逻辑和)布尔掩码一起迭代地构建掩码

def chain_lt(df, conditions):
    for i, (field, val) in enumerate(conditions):
        res = df[field] < val
        if i == 0:
            msk = res
        else:
            msk &= res
    return df[msk]

答案 5 :(得分:0)

这是另一种方式:

import pandas as pd
import numpy as np

df = pd.DataFrame([np.arange(4),np.arange(3,7),np.arange(5,9)],
                  columns = ["field1","field2","field3","field4"])

f = [('field1', 3), ('field2', 4), ('field3', 5)]

mask = np.array([(df[i[0]] == i[1]) for i in f])

# 1 True is enough:
df[mask.any(axis=0)]  # [False  True False] in this sample

# All must be true
df[mask.all(axis=0)]  # [False  True False] in this sample

Df看起来像这样:

   field1  field2  field3  field4
0       0       1       2       3
1       3       4       5       6
2       5       6       7       8