簡體   English   中英

如何檢查一個pandas列中列表中的所有元素是否存在於另一個pandas列中

[英]How to check if all the elements in list in one pandas column are present in another pandas column

我在數據幀df1一列中有一個列表,我想檢查每一行是否該列表的所有元素都在第二個數據幀df2中的另一列中。

這兩個數據框是這樣的:

df1                                          df2

id | members      |                          num  |  available           |
1  |['a',b']      |                          one  | ['a','b','c','d','e']|
2  |['b']         |                          two  | ['a','b']            |
3  |['a','b','c'] |                          three| ['b','d','e']        |

我正在嘗試提出一種方法,該方法可以為我提供df2哪些行具有df1每一行的所有members元素。 也許會產生這樣的結果:


id | members      | which_cols            |                
1  |['a',b']      | ['one','two']         |                       
2  |['b']         | ['one','two','three'] |                         
3  |['a','b','c'] | ['one']               |                      

{k: list(v) for k,v in df1.groupby("id")["members"]}它轉換成字典,比如{k: list(v) for k,v in df1.groupby("id")["members"]}{i: list(j) for i,j in df2.groupby("num")["available"]}可能會更靈活地實現所需的輸出,但仍然沒有找到一種方法來獲得我正在尋找的內容。

df2將有大約300行, available長度與25,000一樣大。 df1可以大到1M行, members列表長度最多為 15。所以我認為效率也很重要。

問題的核心在於您的數據設置。 如果您進行一些預處理,則可以避免多次重復遍歷每個列表。

設置

df1 = pd.Series([['a', 'b'], ['b'], ['a', 'b', 'c']], name = 'members').to_frame()
df2 = pd.Series([['a', 'b', 'c', 'd', 'e'], 
                  ['a', 'b'],
                  ['b', 'd', 'e']], name = 'available').to_frame()
df2.index = ['one', 'two', 'three']

>>> df1

    members
0   ['a', 'b']
1   ['b']
2   ['a', 'b', 'c']

>>> df2

        available
one.    ['a', 'b', 'c', 'd', 'e']
two     ['a', 'b']
three   ['b', 'd', 'e']

重塑數據

如果您在使用數據之前對其進行一次性編碼,那么您將在進行子集檢查方面處於極大優勢:

# You can do this many ways, but sklearn makes this very easy with:
from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()
df1 = df1.join(pd.DataFrame(mlb.fit_transform(df1.pop('members')),
                          columns=mlb.classes_, index=df1.index))

mlb = MultiLabelBinarizer()
df2 = df2.join(pd.DataFrame(mlb.fit_transform(df2.pop('available')),
                          columns=mlb.classes_, index=df2.index))

>>> df1
    a   b   c
0   1   1   0
1   0   1   0
2   1   1   1


>>> df2
        a   b   c   d   e
one     1   1   1   1   1
two     1   1   0   0   0
three   0   1   0   1   1

計算

這種數據格式的巧妙之處在於,現在您可以從df2減去df1並且如果您的所有結果值都不是 -1(表示df2缺少元素,那么您將其添加到列表中。將其視為疊加兩個數據幀(對齊每個資源)然后相減。當然,這可以矢量化:

>>> df1.apply(lambda row: df2.index[((df2[df1.columns] - row) >= 0).all(axis = 1)], axis = 1)

0   Index(['one', 'two'], dtype='object')
1   Index(['one', 'two', 'three'], dtype='object')
2   Index(['one'], dtype='object')

暫無
暫無

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

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