Pandas中Apply函數(shù)加速百倍的技巧

來(lái)源 | kaggle競(jìng)賽寶典
編輯 | 極市平臺(tái)
極市導(dǎo)讀
現(xiàn)在的dask,cudf包的出現(xiàn),我們的數(shù)據(jù)處理得到了大大的加速,但不是很貴的人比較好gpu,非常多的朋友仍然可以使用pandas工具包,但等真的很無(wú)奈,熊貓的許多問(wèn)題我們都需要使用apply函數(shù)來(lái)進(jìn)行處理,而apply函數(shù)是非常緩慢的,本文我們就介紹如何加速apply函數(shù)600倍的技巧。 >>加入極市CV技術(shù)交流群,走在計(jì)算機(jī)視覺(jué)的最前沿
現(xiàn)在的dask,cudf包的出現(xiàn),我們的數(shù)據(jù)處理得到了大大的加速,但不是很貴的人比較好gpu,非常多的朋友仍然可以使用pandas工具包,但等真的很無(wú)奈,熊貓的許多問(wèn)題我們都需要使用apply函數(shù)來(lái)進(jìn)行處理,而apply函數(shù)是非常緩慢的,本文我們就介紹如何加速apply函數(shù)600倍的技巧。
實(shí)驗(yàn)對(duì)比
01 應(yīng)用(基線)
我們以應(yīng)用為案,原來(lái)的應(yīng)用程序處理下面這個(gè)問(wèn)題,需要18.4 秒的時(shí)間。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(0, 11, size=(1000000, 5)), columns=('a','b','c','d','e'))
def func(a,b,c,d,e):
if e == 10:
return c*d
elif (e < 10) and (e>=5):
return c+d
elif e < 5:
return a+b
%%time
df['new'] = df.apply(lambda x: func(x['a'], x['b'], x['c'], x['d'], x['e']), axis=1)
CPU times: user 17.9 s, sys: 301 ms, total: 18.2 s
Wall time: 18.4 s
02 迅捷
因?yàn)樘幚硎遣⑿械?,所以我們可以使用Swift進(jìn)行加速,在使用Swift之后,相同的操作在我的機(jī)器上可以提升到7.67s 。
%%time
# !pip install swifter
import swifter
df['new'] = df.swifter.apply(lambda x : func(x['a'],x['b'],x['c'],x['d'],x['e']),axis=1)
HBox(children=(HTML(value='Dask Apply'), FloatProgress(value=0.0, max=16.0), HTML(value='')))
CPU times: user 329 ms, sys: 240 ms, total: 569 ms
Wall time: 7.67 s
03 矢量化
使用Pandas和Numpy的避免應(yīng)用方法是將函數(shù)直接化。如果我們的操作是可以直接直接化的話,那么我們就很簡(jiǎn)單的使用
用于循環(huán); 列表處理; 應(yīng)用等操作
在將上面的問(wèn)題轉(zhuǎn)化為下面的處理之后,我們的時(shí)間為:421 ms
%%time
df['new'] = df['c'] * df['d'] #default case e = =10
mask = df['e'] < 10
df.loc[mask,'new'] = df['c'] + df['d']
mask = df['e'] < 5
df.loc[mask,'new'] = df['a'] + df['b']
CPU times: user 134 ms, sys: 149 ms, total: 283 ms
Wall time: 421 ms
04 類別轉(zhuǎn)化+類別化
我們先將上面的類別轉(zhuǎn)化為int16型,再進(jìn)行相同的操作,發(fā)現(xiàn)時(shí)間為:116 ms
for col in ('a','b','c','d'):
df[col] = df[col].astype(np.int16)
%%time
df['new'] = df['c'] * df['d'] #default case e = =10
mask = df['e'] < 10
df.loc[mask,'new'] = df['c'] + df['d']
mask = df['e'] < 5
df.loc[mask,'new'] = df['a'] + df['b']
CPU times: user 71.3 ms, sys: 42.5 ms, total: 114 ms
Wall time: 116 ms
05 轉(zhuǎn)化為值處理
在能轉(zhuǎn)化為.values的地方典型轉(zhuǎn)化為.values,再進(jìn)行操作。
這里先轉(zhuǎn)化為.values等價(jià)于轉(zhuǎn)化為numpy,這樣我們的操作會(huì)更快捷。
于是,上面的操作時(shí)間又被延遲為:74.9ms
%%time
df['new'] = df['c'].values * df['d'].values #default case e = =10
mask = df['e'].values < 10
df.loc[mask,'new'] = df['c'] + df['d']
mask = df['e'].values < 5
df.loc[mask,'new'] = df['a'] + df['b']
CPU times: user 64.5 ms, sys: 12.5 ms, total: 77 ms
Wall time: 74.9 ms
實(shí)驗(yàn)總結(jié)
通過(guò)上面的一些小技巧,我們將簡(jiǎn)單的長(zhǎng)大了,具體地:
應(yīng)用:18.4 秒 應(yīng)用 + Swifter:7.67 秒 熊貓矢量化:421 毫秒 Pandas 矢量化 + 數(shù)據(jù)類型:116 毫秒 Pandas 向量化 + 值 + 數(shù)據(jù)類型:74.9ms
參考文獻(xiàn)
https://towardsdatascience.com/do-you-use-apply-in-pandas-there-is-a-600x-faster-way-d2497facfa66
如果覺(jué)得有用,就請(qǐng)分享到朋友圈吧!
公眾號(hào)后臺(tái)回復(fù)“CVPR21檢測(cè)”獲取CVPR2021目標(biāo)檢測(cè)論文下載~

# CV技術(shù)社群邀請(qǐng)函 #

備注:姓名-學(xué)校/公司-研究方向-城市(如:小極-北大-目標(biāo)檢測(cè)-深圳)
即可申請(qǐng)加入極市目標(biāo)檢測(cè)/圖像分割/工業(yè)檢測(cè)/人臉/醫(yī)學(xué)影像/3D/SLAM/自動(dòng)駕駛/超分辨率/姿態(tài)估計(jì)/ReID/GAN/圖像增強(qiáng)/OCR/視頻理解等技術(shù)交流群
每月大咖直播分享、真實(shí)項(xiàng)目需求對(duì)接、求職內(nèi)推、算法競(jìng)賽、干貨資訊匯總、與 10000+來(lái)自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺(jué)開(kāi)發(fā)者互動(dòng)交流~

