簡體   English   中英

使用字典中的值過濾 pandas dataframe

[英]Filter a pandas dataframe using values from a dict

我需要使用 dict 過濾數據框,其中鍵是列名,值是我要過濾的值:

filter_v = {'A':1, 'B':0, 'C':'This is right'}
# this would be the normal approach
df[(df['A'] == 1) & (df['B'] ==0)& (df['C'] == 'This is right')]

但我想做點事情就行了

for column, value in filter_v.items():
    df[df[column] == value]

但這將多次過濾數據框,一次一個值,而不是同時應用所有過濾器。 有沒有辦法以編程方式做到這一點?

編輯:一個例子:

df1 = pd.DataFrame({'A':[1,0,1,1, np.nan], 'B':[1,1,1,0,1], 'C':['right','right','wrong','right', 'right'],'D':[1,2,2,3,4]})
filter_v = {'A':1, 'B':0, 'C':'right'}
df1.loc[df1[filter_v.keys()].isin(filter_v.values()).all(axis=1), :]

    A   B   C   D
0   1   1   right   1
1   0   1   right   2
3   1   0   right   3

但預期的結果是

    A   B   C   D
3   1   0   right   3

只應選擇最后一個。

IIUC,你應該能夠做這樣的事情:

>>> df1.loc[(df1[list(filter_v)] == pd.Series(filter_v)).all(axis=1)]
   A  B      C  D
3  1  0  right  3

這通過制作一個系列來比較:

>>> pd.Series(filter_v)
A        1
B        0
C    right
dtype: object

選擇df1的對應部分:

>>> df1[list(filter_v)]
    A      C  B
0   1  right  1
1   0  right  1
2   1  wrong  1
3   1  right  0
4 NaN  right  1

找到他們匹配的地方:

>>> df1[list(filter_v)] == pd.Series(filter_v)
       A      B      C
0   True  False   True
1  False  False   True
2   True  False  False
3   True   True   True
4  False  False   True

找到它們匹配的地方:

>>> (df1[list(filter_v)] == pd.Series(filter_v)).all(axis=1)
0    False
1    False
2    False
3     True
4    False
dtype: bool

最后使用它來索引 df1:

>>> df1.loc[(df1[list(filter_v)] == pd.Series(filter_v)).all(axis=1)]
   A  B      C  D
3  1  0  right  3

這是一種方法:

df.loc[df[filter_v.keys()].isin(filter_v.values()).all(axis=1), :]

更新:

隨着列之間的值相同,您可以執行以下操作:

# Create your filtering function:

def filter_dict(df, dic):
    return df[df[dic.keys()].apply(
            lambda x: x.equals(pd.Series(dic.values(), index=x.index, name=x.name)), asix=1)]

# Use it on your DataFrame:

filter_dict(df1, filter_v)

其中產生:

   A  B      C  D
3  1  0  right  3            

如果這是您經常做的事情,您可以盡可能修補 DataFrame 以便輕松訪問此過濾器:

pd.DataFrame.filter_dict_ = filter_dict

然后像這樣使用這個過濾器:

df1.filter_dict_(filter_v)

這將產生相同的結果。

但是,這顯然不是正確的方法。 我會使用 DSM 的方法。

對於python2,@primer 的回答沒問題。 但是,由於dict_keys ,您應該在 Python3 中小心 例如,

>> df.loc[df[filter_v.keys()].isin(filter_v.values()).all(axis=1), :]
>> TypeError: unhashable type: 'dict_keys'

Python3的正確方法:

df.loc[df[list(filter_v.keys())].isin(list(filter_v.values())).all(axis=1), :]

對於傳遞過濾器值數組而不是單個值的情況的上述抽象(類似於 pandas.core.series.Series.isin())。 使用相同的示例:

df1 = pd.DataFrame({'A':[1,0,1,1, np.nan], 'B':[1,1,1,0,1], 'C':['right','right','wrong','right', 'right'],'D':[1,2,2,3,4]})
filter_v = {'A':[1], 'B':[1,0], 'C':['right']}
##Start with array of all True
ind = [True] * len(df1)

##Loop through filters, updating index
for col, vals in filter_v.items():
    ind = ind & (df1[col].isin(vals))

##Return filtered dataframe
df1[ind]

##Returns

    A   B    C      D
0   1.0 1   right   1
3   1.0 0   right   3

這是另一種方式:

filterSeries = pd.Series(np.ones(df.shape[0],dtype=bool))
for column, value in filter_v.items():
    filterSeries = ((df[column] == value) & filterSeries)

這給出:

>>> df[filterSeries]
   A  B      C  D
3  1  0  right  3 

要跟進 DSM 的回答,您還可以使用any()將您的查詢轉換為 OR 操作(而不是 AND):

df1.loc[(df1[list(filter_v)] == pd.Series(filter_v)).any(axis=1)]

您還可以創建查詢

query_string = ' and '.join(
    [f'({key} == "{val}")' if type(val) == str else f'({key} == {val})' for key, val in filter_v.items()]
)

df1.query(query_string)

結合以前的答案,這是一個 function 您可以提供給df1.loc 允許 AND/OR(使用how='all' / 'any' ),如果需要,它還允許使用op關鍵字進行==以外的比較。

import operator

def quick_mask(df, filters, how='all', op=operator.eq) -> pd.Series:
    if how == 'all':
        comb = pd.Series.all
    elif how == 'any':
        comb = pd.Series.any
    return comb(op(df[[*filters]], pd.Series(filters)), axis=1)

# Usage
df1.loc[quick_mask(df1, filter_v)]

由於我的字典對同一個鍵有多個值,我遇到了問題。

我能夠將 DSM 的查詢更改為:

df1.loc[df1[list(filter_v)].isin(filter_v).all(axis=1), :]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM