讓 Pandas DataFrame 性能飛升 40 倍

val這一列進(jìn)行處理:如果是偶數(shù)則減1,奇數(shù)則加1。實際的數(shù)據(jù)分析工作要比這個例子復(fù)雜的多,但考慮到我們沒有那么多時間等待運(yùn)行結(jié)果,所以就偷個懶吧??梢钥吹?/span>transform函數(shù)的平均運(yùn)行時間是284ms:import?pandas?as?pd
import?numpy?as?np
def?gen_data(size):
????d?=?dict()
????d["genre"]?=?np.random.choice(["A",?"B",?"C",?"D"],?size=size)
????d["val"]?=?np.random.randint(low=0,?high=100,?size=size)
????return?pd.DataFrame(d)
data?=?gen_data(1000000)
data.head()
def?transform(data):
????data.loc[:,?"new_val"]?=?data.val.apply(lambda?x:?x?+?1?if?x?%?2?else?x?-?1)
%timeit?-n?1?transform(data)
284?ms?±?8.95?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
x + 1 if x % 2 else x - 1 這個函數(shù)。平均運(yùn)行時間降低到了202ms,果然速度變快了。性能大約提升了1.4倍,離40倍的flag還差的好遠(yuǎn)。%load_ext?cython
%%cython
cpdef?int?_transform(int?x):
????if?x?%?2:
????????return?x?+?1
????return?x?-?1
def?transform(data):
????data.loc[:,?"new_val"]?=?data.val.apply(_transform)
%timeit?-n?1?transform(data)
202?ms?±?13.1?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
val這一列作為Numpy數(shù)組傳遞給Cython函數(shù),注意區(qū)分cnp和np。平均運(yùn)行時間直接降到10.8毫秒,性能大約提升了26倍,仿佛看到了一絲希望。%%cython
import?numpy?as?np
cimport?numpy?as?cnp
ctypedef?cnp.int_t?DTYPE_t
cpdef?cnp.ndarray[DTYPE_t]?_transform(cnp.ndarray[DTYPE_t]?arr):
????cdef:
????????int?i?=?0
????????int?n?=?arr.shape[0]
????????int?x
????????cnp.ndarray[DTYPE_t]?new_arr?=?np.empty_like(arr)
????while?i?????????x?=?arr[i]
????????if?x?%?2:
????????????new_arr[i]?=?x?+?1
????????else:
????????????new_arr[i]?=?x?-?1
????????i?+=?1
????return?new_arr
def?transform(data):
????data.loc[:,?"new_val"]?=?_transform(data.val.values)
%timeit?-n?1?transform(data)
10.8?ms?±?512?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
@cython.boundscheck(False),@cython.wraparound(False)裝飾器關(guān)閉數(shù)組的邊界檢查和負(fù)下標(biāo)處理,平均運(yùn)行時間變?yōu)?.9毫秒。性能提升了42倍左右,順利完成任務(wù)。%%cython
import?cython
import?numpy?as?np
cimport?numpy?as?cnp
ctypedef?cnp.int_t?DTYPE_t
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef?cnp.ndarray[DTYPE_t]?_transform(cnp.ndarray[DTYPE_t]?arr):
????cdef:
????????int?i?=?0
????????int?n?=?arr.shape[0]
????????int?x
????????cnp.ndarray[DTYPE_t]?new_arr?=?np.empty_like(arr)
????while?i?????????x?=?arr[i]
????????if?x?%?2:
????????????new_arr[i]?=?x?+?1
????????else:
????????????new_arr[i]?=?x?-?1
????????i?+=?1
????return?new_arr
def?transform(data):
????data.loc[:,?"new_val"]?=?_transform(data.val.values)
%timeit?-n?1?transform(data)
6.76?ms?±?545?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
作者:李小文,先后從事過數(shù)據(jù)分析、數(shù)據(jù)挖掘工作,主要開發(fā)語言是Python,現(xiàn)任一家小型互聯(lián)網(wǎng)公司的算法工程師。
Github:?https://github.com/tushushu
推薦閱讀


點擊下方閱讀原文加入社區(qū)會員
點贊鼓勵一下

評論
圖片
表情
