[英]Selecting data from Pandas dataframe based on criteria stored in a dict
我有一個包含大量變量的 Pandas 數據框。 這可以簡化為:
tempDF = pd.DataFrame({ 'var1': [12,12,12,12,45,45,45,51,51,51],
'var2': ['a','a','b','b','b','b','b','c','c','d'],
'var3': ['e','f','f','f','f','g','g','g','g','g'],
'var4': [1,2,3,3,4,5,6,6,6,7]})
如果我想選擇數據框的一個子集(例如 var2='b' 和 var4=3),我會使用:
tempDF.loc[(tempDF['var2']=='b') & (tempDF['var4']==3),:]
但是,如果匹配條件存儲在 dict 中,是否可以選擇數據幀的子集,例如:
tempDict = {'var2': 'b','var4': 3}
重要的是變量名稱不是預定義的,並且字典中包含的變量數量是可變的。
我一直對此感到困惑,所以任何建議都將不勝感激。
您可以評估一系列條件。 他們不必只是一個平等。
df = tempDF
d = tempDict
# `repr` returns the string representation of an object.
>>> df[eval(" & ".join(["(df['{0}'] == {1})".format(col, repr(cond))
for col, cond in d.iteritems()]))]
var1 var2 var3 var4
2 12 b f 3
3 12 b f 3
看看eval
在這里做了什么:
conditions = " & ".join(["(df['{0}'] == {1})".format(col, repr(cond))
for col, cond in d.iteritems()])
>>> conditions
"(df['var4'] == 3) & (df['var2'] == 'b')"
>>> eval(conditions)
0 False
1 False
2 True
3 True
4 False
5 False
6 False
7 False
8 False
9 False
dtype: bool
這是另一個使用等式約束的示例:
>>> eval(" & ".join(["(df['{0}'] == {1})".format(col, repr(cond))
for col, cond in d.iteritems()]))
d = {'var2': ('==', "'b'"),
'var4': ('>', 3)}
>>> df[eval(" & ".join(["(df['{0}'] {1} {2})".format(col, cond[0], cond[1])
for col, cond in d.iteritems()]))]
var1 var2 var3 var4
4 45 b f 4
5 45 b g 5
6 45 b g 6
另一種選擇是使用query
:
qry = " & ".join('{0} {1} {2}'.format(k, cond[0], cond[1]) for k, cond in d.iteritems())
>>> qry
"var4 > 3 & var2 == 'b'"
>>> df.query(qry)
var1 var2 var3 var4
4 45 b f 4
5 45 b g 5
6 45 b g 6
您可以使用列表理解為每個條件創建掩碼,然后通過轉換為數據框並使用all
來加入它們:
In [23]: pd.DataFrame([tempDF[key] == val for key, val in tempDict.items()]).T.all(axis=1)
Out[23]:
0 False
1 False
2 True
3 True
4 False
5 False
6 False
7 False
8 False
9 False
dtype: bool
然后你可以用那個掩碼切片你的數據框:
mask = pd.DataFrame([tempDF[key] == val for key, val in tempDict.items()]).T.all(axis=1)
In [25]: tempDF[mask]
Out[25]:
var1 var2 var3 var4
2 12 b f 3
3 12 b f 3
這是從tempDict
建立條件的一種方法
In [25]: tempDF.loc[pd.np.all([tempDF[k] == tempDict[k] for k in tempDict], axis=0), :]
Out[25]:
var1 var2 var3 var4
2 12 b f 3
3 12 b f 3
或者使用query
來獲得更易讀的類似查詢的字符串。
In [33]: tempDF.query(' & '.join(['{0}=={1}'.format(k, repr(v)) for k, v in tempDict.iteritems()]))
Out[33]:
var1 var2 var3 var4
2 12 b f 3
3 12 b f 3
In [34]: ' & '.join(['{0}=={1}'.format(k, repr(v)) for k, v in tempDict.iteritems()])
Out[34]: "var4==3 & var2=='b'"
這是我個人實用程序中的一個函數,它接受單個值或列表作為子集:
def subsetdict(df, sdict):
subsetter_list = [df[i].isin([j]) if not isinstance(j, list) else df[i].isin(j) for i, j in sdict.items()]
subsetter = pd.concat(subsetter_list, axis=1).all(1)
return df.loc[subsetter, :]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.