aho*_*osh 20 python exec filter dataframe 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
Run Code Online (Sandbox Code Playgroud)
但是,我想在一个函数中执行此操作,其中列的名称及其阈值在字典中提供给我.这是我的第一次尝试,运作正常.基本上我将过滤器放在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
Run Code Online (Sandbox Code Playgroud)
现在,最后我将所有内容都放在一个函数中并且它停止工作(也许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
Run Code Online (Sandbox Code Playgroud)
我知道exec函数在函数内使用时行为不同,但不知道如何解决问题.另外,我想知道,必须有定义一个函数来完成给定的两个输入滤波更优雅的方式:1)df和2) limits_dic = {"A" : 0, "B" : 2, "C" : -1}.我很感激任何想法.
cs9*_*s95 38
如果您正在尝试构建动态查询,则有更简单的方法.这是一个使用列表理解和str.join:
query = ' & '.join(['{}>{}'.format(k, v) for k, v in limits_dic.items()])
Run Code Online (Sandbox Code Playgroud)
或者,使用f带有python-3.6 +的-strings,
query = ' & '.join([f'{k}>{v}' for k, v in limits_dic.items()])
Run Code Online (Sandbox Code Playgroud)
print(query)
'A>0 & C>-1 & B>2'
Run Code Online (Sandbox Code Playgroud)
将查询字符串传递给df.query它,它的目的就是为了这个目的:
out = df.query(query)
print(out)
A B C
1 2 5 2
2 10 3 1
4 3 6 2
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
如果您需要查询使用字符串数据的列,则上面的代码需要稍作修改.
考虑(来自这个答案的数据):
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
Run Code Online (Sandbox Code Playgroud)
以及列,运算符和值的列表:
column = ['height', 'age', 'gender']
equal = ['>', '>', '==']
condition = [1.68, 20, 'F']
Run Code Online (Sandbox Code Playgroud)
这里适当的修改是:
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
Run Code Online (Sandbox Code Playgroud)
有关pd.eval()函数系列,其功能和用例的信息,请使用pd.eval()访问pandas中的Dynamic Expression Evaluation.
@coldspeed 版本的替代方案:
conditions = None
for key, val in limit_dic.items():
cond = df[key] > val
if conditions is None:
conditions = cond
else:
conditions = conditions & cond
print(df[conditions])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5867 次 |
| 最近记录: |