微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

python – 动态过滤pandas数据帧

我正在尝试使用三列的阈值来过滤pandas数据帧

import pandas as pd
df = pd.DataFrame({"A" : [6, 2, 10, -5, 3],
                   "B" : [2, 5, 3, 2, 6],
                   "C" : [-5, 2, 1, 8, 2]})
df = df.loc[(df.A > 0) & (df.B > 2) & (df.C > -1)].reset_index(drop = True)

df
    A  B  C
0   2  5  2
1  10  3  1
2   3  6  2

但是,我想在一个函数中执行此操作,其中列的名称及其阈值在字典中提供给我.这是我的第一次尝试,运作正常.基本上我将过滤器放在cond变量中并运行它:

df = pd.DataFrame({"A" : [6, 2, 10, -5, 3],
                   "B" : [2, 5, 3, 2, 6],
                   "C" : [-5, 2, 1, 8, 2]})
limits_dic = {"A" : 0, "B" : 2, "C" : -1}
cond = "df = df.loc["
for key in limits_dic.keys():
    cond += "(df." + key + " > " + str(limits_dic[key])+ ") & "
cond = cond[:-2] + "].reset_index(drop = True)"
exec(cond)
df
    A  B  C
0   2  5  2
1  10  3  1
2   3  6  2

现在,最后我将所有内容都放在一个函数中并且它停止工作(也许exec函数不喜欢在函数内部使用!):

df = pd.DataFrame({"A" : [6, 2, 10, -5, 3],
                   "B" : [2, 5, 3, 2, 6],
                   "C" : [-5, 2, 1, 8, 2]})
limits_dic = {"A" : 0, "B" : 2, "C" : -1}
def filtering(df, limits_dic):
    cond = "df = df.loc["
    for key in limits_dic.keys():
        cond += "(df." + key + " > " + str(limits_dic[key])+ ") & "
    cond = cond[:-2] + "].reset_index(drop = True)"
    exec(cond)
    return(df)

df = filtering(df, limits_dic)
df
    A  B  C
0   6  2 -5
1   2  5  2
2  10  3  1
3  -5  2  8
4   3  6  2

我知道exec函数函数内部使用时行为不同,但不确定如何解决问题.另外,我想知道必须有一种更优雅的方法来定义一个函数来进行两次输入的过滤:1)df和2)limits_dic = {“A”:0,“B”:2,“C”: – 1}.我很感激任何想法.

解决方法:

如果您正在尝试构建动态查询,则有更简单的方法.这是一个使用列表理解和str.join:

query = ' & '.join(['{}>{}'.format(k, v) for k, v in limits_dic.items()])

或者,使用python-3.6的f-string,

query = ' & '.join([f'{k}>{v}' for k, v in limits_dic.items()])
print(query)

'A>0 & C>-1 & B>2'

查询字符串传递给df.query,它就是为了这个目的:

out = df.query(query)
print(out)

    A  B  C
1   2  5  2
2  10  3  1
4   3  6  2

如果要为查询获取布尔掩码,也可以使用df.eval,然后索引变得简单:

mask = df.eval(query)
print(mask)

0    False
1     True
2     True
3    False
4     True
dtype: bool

out = df[mask]
print(out)

    A  B  C
1   2  5  2
2  10  3  1
4   3  6  2

字符串数据

如果您需要查询使用字符串数据的列,则上面的代码需要稍作修改.

考虑(来自this answer的数据):

df = pd.DataFrame({'gender':list('MMMFFF'),
                   'height':[4,5,4,5,5,4],
                   'age':[70,80,90,40,2,3]})

print (df)
  gender  height  age
0      M       4   70
1      M       5   80
2      M       4   90
3      F       5   40
4      F       5    2
5      F       4    3

以及列,运算符和值的列表:

column = ['height', 'age', 'gender']
equal = ['>', '>', '==']
condition = [1.68, 20, 'F']

这里适当的修改是:

query = ' & '.join(f'{i} {j} {repr(k)}' for i, j, k in zip(column, equal, condition))
df.query(query)

   age gender  height
3   40      F       5

有关pd.eval()函数系列,其功能和用例的信息,请访问Dynamic Expression Evaluation in pandas using pd.eval().

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐