1、NumExpr
NumExpr 是一個對NumPy計算式進行的性能優(yōu)化。NumExpr的使用及其簡單,只需要將原來的numpy語句使用雙引號框起來,并使用numexpr中的evaluate方法調用即可。
經(jīng)驗上看,數(shù)據(jù)有上萬條+ 使用NumExpr才比較優(yōu)效果,對于簡單運算使用NumExpr可能會更慢。如下較復雜計算,速度差不多快了5倍。
importnumexprasne
importnumpyasnp
a=np.linspace(0,1000,1000)
print('#numpy十次冪計算')
%timeita**10
print('#numexpr十次冪計算')
%timeitne.evaluate('a**10')

2、Numba
Numba 使用行業(yè)標準的LLVM編譯器庫在運行時將 Python 函數(shù)轉換為優(yōu)化的機器代碼。Python 中 Numba 編譯的數(shù)值算法可以接近 C 或 FORTRAN 的速度。如果在你的數(shù)據(jù)處理過程涉及到了大量的數(shù)值計算,那么使用numba可以大大加快代碼的運行效率(一般來說,Numba 引擎在處理大量數(shù)據(jù)點 如 1 百萬+ 時表現(xiàn)出色)。numba使用起來也很簡單,因為numba內置的函數(shù)本身是個裝飾器,所以只要在自己定義好的函數(shù)前面加個@nb.方法就行,簡單快捷!
#pipinstallnumba
importnumbaasnb
#用numba加速的求和函數(shù)
@nb.jit()
defnb_sum(a):
Sum=0
foriinrange(len(a)):
Sum+=a[i]
returnSum
#沒用numba加速的求和函數(shù)
defpy_sum(a):
Sum=0
foriinrange(len(a)):
Sum+=a[i]
returnSum
importnumpyasnp
a=np.linspace(0,1000,1000)#創(chuàng)建一個長度為1000的數(shù)組
print('#python求和函數(shù)')
%timeitsum(a)
print('#沒加速的for循環(huán)求和函數(shù)')
%timeitpy_sum(a)
print('#numba加速的for循環(huán)求和函數(shù)')
%timeitnb_sum(a)
print('#numpy求和函數(shù)')
%timeitnp.sum(a)
fromnumbaimportcuda
cuda.select_device(1)
@cuda.jit
defCudaSquare(x):
i,j=cuda.grid(2)
x[i][j]*=x[i][j]
#numba的矢量化加速
frommathimportsin
@nb.vectorize()
defnb_vec_sin(a):
returnsin(a)
3、CuPy
CuPy 是一個借助 CUDA GPU 庫在英偉達 GPU 上實現(xiàn) Numpy 數(shù)組的庫?;?Numpy 數(shù)組的實現(xiàn),GPU 自身具有的多個 CUDA 核心可以促成更好的并行加速。
#pipinstallcupy
importnumpyasnp
importcupyascp
importtime
###numpy
s=time.time()
x_cpu=np.ones((1000,1000,1000))
e=time.time()
print(e-s)
###CuPy
s=time.time()
x_gpu=cp.ones((1000,1000,1000))
e=time.time()
print(e-s)
上述代碼,Numpy 創(chuàng)建(1000, 1000, 1000)的數(shù)組用了 1.68 秒,而 CuPy 僅用了 0.16 秒,實現(xiàn)了 10.5 倍的加速。隨著數(shù)據(jù)量的猛增,CuPy的性能提升會更為明顯。4、pandas使用技巧
更多pandas性能提升技巧請戳官方文檔:https://pandas.pydata.org/pandas-docs/stable/user_guide/enhancingperf.html
4.1 按行迭代優(yōu)化
我們按行對dataframe進行迭代,一般我們會用iterrows這個函數(shù)。在新版的pandas中,提供了一個更快的itertuples函數(shù),如下可以看到速度快了幾十倍。
importpandasaspd
importnumpyasnp
importtime
df=pd.DataFrame({'a':np.random.randn(100000),
'b':np.random.randn(100000),
'N':np.random.randint(100,1000,(100000)),
'x':np.random.randint(1,10,(100000))})
%%timeit
a2=[]
forrowindf.itertuples():
temp=getattr(row,'a')
a2.append(temp*temp)
df['a2']=a2
%%timeit
a2=[]
forindex,rowindf.iterrows():
temp=row['a']
a2.append(temp*temp)
df['a2']=a2

4.2 apply、applymap優(yōu)化
當對于每行執(zhí)行類似的操作時,用循環(huán)逐行處理效率很低。這時可以用apply或applymap搭配函數(shù)操作,其中apply是可用于逐行計算,而applymap可以做更細粒度的逐個元素的計算。
#列a、列b逐行進行某一函數(shù)計算
df['a3']=df.apply(lambdarow:row['a']*row['b'],axis=1)
#逐個元素保留兩位小數(shù)
df.applymap(lambdax:"%.2f"%x)

4.3 聚合函數(shù)agg優(yōu)化
對于某列將進行聚合后,使用內置的函數(shù)比自定義函數(shù)效率更高,如下示例速度加速3倍
%timeitdf.groupby("x")['a'].agg(lambdax:x.sum())
%timeitdf.groupby("x")['a'].agg(sum)
%timeitdf.groupby("x")['a'].agg(np.sum)

4.4 文件操作
pandas讀取文件,pkl格式的數(shù)據(jù)的讀取速度最快,其次是hdf格式的數(shù)據(jù),再者是讀取csv格式數(shù)據(jù),而xlsx的讀取是比較慢的。但是存取csv有個好處是,這個數(shù)據(jù)格式通用性更好,占用內存硬盤資源也比較少。此外,對于大文件,csv還可以對文件分塊、選定某幾列、指定數(shù)據(jù)類型做讀取。
4.5 pandas.eval
pandas.eval 是基于第一節(jié)提到的numexpr,pandas也是基于numpy開發(fā)的,numexpr同樣可以被用來對pandas加速)。使用eval表達式的一個經(jīng)驗是數(shù)據(jù)超過 10,000 行的情況下使用會有明顯優(yōu)化效果。
importpandasaspd
nrows,ncols=20000,100
df1,df2,df3,df4=[pd.DataFrame(np.random.randn(nrows,ncols))for_inrange(4)]
print('pd')
%timeitdf1+df2+df3+df4
print('pd.eval')
%timeitpd.eval("df1+df2+df3+df4")

5、Cython優(yōu)化
Cython是一個基于C語言的Python 編譯器,在一些計算量大的程序中,可以Cython來實現(xiàn)相當大的加速??紤]大部分人可能都不太了解復雜的cython語句,下面介紹下Cython的簡易版使用技巧。
通過在Ipython加入 Cython 魔術函數(shù)%load_ext Cython
,如下示例就可以加速了一倍。進一步再借助更高級的cython語句,還是可以比Python快個幾十上百倍。
%%cython
deff_plain(x):
returnx*(x-1)
defintegrate_f_plain(a,b,N):
s=0
dx=(b-a)/N
foriinrange(N):
s+=f_plain(a+i*dx)
returns*dx

6、swifter
swifter是pandas的插件,可以直接在pandas的數(shù)據(jù)上操作。Swifter的優(yōu)化方法檢驗計算是否可以矢量化或者并行化處理,以提高性能。如常見的apply就可以通過swifter并行處理。
importpandasaspd
importswifter
df.swifter.apply(lambdax:x.sum()-x.min())
7、Modin
Modin后端使用dask或者ray(dask是類似pandas庫的功能,可以實現(xiàn)并行讀取運行),是個支持分布式運行的類pandas庫,簡單通過更改一行代碼import modin.pandas as pd
就可以優(yōu)化 pandas,常用的內置的read_csv、concat、apply都有不錯的加速。注:并行處理的開銷會使小數(shù)據(jù)集的處理速度變慢。
!pipinstallmodin
importpandas
importmodin.pandasaspd
importtime
##pandas
pandas_df=pandas.DataFrame({'a':np.random.randn(10000000),
'b':np.random.randn(10000000),
'N':np.random.randint(100,10000,(10000000)),
'x':np.random.randint(1,1000,(10000000))})
start=time.time()
big_pandas_df=pandas.concat([pandas_dffor_inrange(25)])
end=time.time()
pandas_duration=end-start
print("Timetoconcatwithpandas:{}seconds".format(round(pandas_duration,3)))
####modin.pandas
modin_df=pd.DataFrame({'a':np.random.randn(10000000),
'b':np.random.randn(10000000),
'N':np.random.randint(100,10000,(10000000)),
'x':np.random.randint(1,1000,(10000000))})
start=time.time()
big_modin_df=pd.concat([modin_dffor_inrange(25)])
end=time.time()
modin_duration=end-start
print("TimetoconcatwithModin:{}seconds".format(round(modin_duration,3)))
print("Modinis{}xfasterthanpandasat`concat`!".format(round(pandas_duration/modin_duration,2)))
原文標題:Pandas、Numpy 性能優(yōu)化秘籍
文章出處:【微信公眾號:數(shù)據(jù)分析與開發(fā)】歡迎添加關注!文章轉載請注明出處。
-
數(shù)據(jù)處理
+關注
關注
0文章
627瀏覽量
29167 -
python
+關注
關注
56文章
4827瀏覽量
86690 -
性能優(yōu)化
+關注
關注
0文章
18瀏覽量
7529
原文標題:Pandas、Numpy 性能優(yōu)化秘籍
文章出處:【微信號:DBDevs,微信公眾號:數(shù)據(jù)分析與開發(fā)】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
python入門圣經(jīng)-高清電子書(建議下載)
Python在嵌入式系統(tǒng)中的應用場景
深度學習入門:簡單神經(jīng)網(wǎng)絡的構建與實現(xiàn)
使用Python實現(xiàn)xgboost教程
適用于MySQL和MariaDB的Python連接器:可靠的MySQL數(shù)據(jù)連接器和數(shù)據(jù)庫

評論