python - 使用numpy向量化檢查pandas列中的參考列表




(2)

我有一個參考清單

ref = ['September', 'August', 'July', 'June', 'May', 'April', 'March']

還有一個數據框

df = pd.DataFrame({'Month_List': [['July'], ['August'], ['July', 'June'], ['May', 'April', 'March']]})
df
    Month_List
0   [July]
1   [August]
2   [July, June]
3   [May, April, March]

我想檢查參考列表中的哪些元素存在於每一行中,並轉換為二進制列表

我可以使用 apply 來實現

def convert_month_to_binary(ref,lst):
    s = pd.Series(ref)
    return s.isin(lst).astype(int).tolist()  

df['Binary_Month_List'] = df['Month_List'].apply(lambda x: convert_month_to_binary(ref, x))
df

    Month_List          Binary_Month_List
0   [July]              [0, 0, 1, 0, 0, 0, 0]
1   [August]            [0, 1, 0, 0, 0, 0, 0]
2   [July, June]        [0, 0, 1, 1, 0, 0, 0]
3   [May, April, March] [0, 0, 0, 0, 1, 1, 1]

但是,在大型數據集上使用Apply非常慢,因此我希望使用numpy向量化。 如何改善我的表現?

擴展名

我想使用 numpy vectorization 因為我現在需要在此列表上應用另一個函數

我正在嘗試這樣,但是性能非常慢。 與 apply 類似的結果

def count_one(lst):
    index = [i for i, e in enumerate(lst) if e != 0] 
    return len(index)

vfunc = np.vectorize(count_one)
df['Value'] = vfunc(df['Binary_Month_List']) 

在熊貓中最好 不要這樣使用 list ,但是可以使用 MultiLabelBinarizer DataFrame.reindex 來添加缺少的類別,最後將值轉換為numpy數組,然後在性能很重要時 list s:

from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()
df1 = pd.DataFrame(mlb.fit_transform(df['Month_List']),columns=mlb.classes_)
df['Binary_Month_List'] = df1.reindex(columns=ref, fill_value=0).values.tolist()

或使用 Series.str.join Series.str.get_dummies reindex

df['Binary_Month_List'] = (df['Month_List'].str.join('|')
                                           .str.get_dummies()
                                           .reindex(columns=ref, fill_value=0)
                                           .values
                                           .tolist())
print (df)
            Month_List      Binary_Month_List
0               [July]  [0, 0, 1, 0, 0, 0, 0]
1             [August]  [0, 1, 0, 0, 0, 0, 0]
2         [July, June]  [0, 0, 1, 1, 0, 0, 0]
3  [May, April, March]  [0, 0, 0, 0, 1, 1, 1]

性能有所不同:

df = pd.concat([df] * 1000, ignore_index=True)

from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()

In [338]: %timeit (df['Month_List'].str.join('|').str.get_dummies().reindex(columns=ref, fill_value=0).values.tolist())
31.4 ms ± 1.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [339]: %timeit pd.DataFrame(mlb.fit_transform(df['Month_List']),columns=mlb.classes_).reindex(columns=ref, fill_value=0).values.tolist()
5.57 ms ± 94.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [340]: %timeit df['Binary_Month_List2'] =df.Month_List.explode().str.get_dummies().sum(level=0).reindex(columns=ref, fill_value=0).values.tolist()
58.6 ms ± 461 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

我們可以將 explodeget_dummies 一起 get_dummies ,請注意0.25之後可用 explode

df.Month_List.explode().str.get_dummies().sum(level=0).reindex(columns=ref, fill_value=0).values.tolist()
Out[79]: 
[[0, 0, 1, 0, 0, 0, 0],
 [0, 1, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1]]

#df['new']=df.Month_List.explode().str.get_dummies().sum(level=0).reindex(columns=ref, fill_value=0).values.tolist()




numpy