使用Pandas得到阿布分布功能進行運算是,經常需要創建臨時對象,這樣會占用很大的內存和使用較長的計算時間。pandas為了解決性能問題,引入了eval()和query()函數,他們都依賴Numexpr包,運算過程中不需要費力地配置中間數組。
一、使用Pandas.eval()實現高性能運算
1、pandas中的函數eval()能夠將字符串對象轉化為有效的表達式,進行求值運算並返回結果;
一般地,運算簡單或DataFrame數據量較少之時不適用eval()函數,在DataFrame大於10000行時使用eval(),性能會得到明顯提升。
>>>import numpy as np >>>import pandas as pd >>>nrows=20000 >>>nclos=200 >>>df1,df2,df3,df4 = [pd.DataFrame(np.random.randn(nrows,nclos)) for i in range(4)] >>>%timeit df1+df2+df3+df4 50.8 ms ± 3.11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) >>>%timeit pd.eval('df1+df2+df3+df4') 23.6 ms ± 888 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
其中:魔術命令%timeit可自動多次執行語句,產生一個較為精准的平均執行時間。
使用np.allclose()比較兩個數組是否完全相同,結果為True表示eval函數計算結果與普通Pandas計算結果一致。
>>>np.allclose(df1+df2+df3+df4,pd.eval('df1+df2+df3+df4')) True
2、eval()支持的運算方式
eval()函數支持多種運算方式,如:算數運算、比較運算和布爾運算,同時也支持對象屬性與索引的表達方式;
eval()函數目前還不支持函數條用,if條件語句,循環語句及更為復雜的運算。
3、DataFrame.eval()實現列間運算
>>>df.eval("sex=='female'and score_math>80") 0 False 1 True 2 True 3 False 4 True 5 False 6 False 7 False 8 False dtype: bool #新增列 >>> df.eval('sum_score = score_math + score_music',inplace=True) >>> df class sex score_math score_music sum_score 0 A male 95 79 174 1 A female 96 90 186 2 B female 85 85 170 3 C male 93 92 185 4 B female 84 90 174 5 B male 88 70 158 6 C male 59 89 148 7 A male 88 86 174 8 B male 89 74 163 #修改列 >>> df.eval('score_math = score_math +5') class sex score_math score_music sum_score 0 A male 100 79 174 1 A female 101 90 186 2 B female 90 85 170 3 C male 98 92 185 4 B female 89 90 174 5 B male 93 70 158 6 C male 64 89 148 7 A male 93 86 174 8 B male 94 74 163
4、DataFrame.eval()使用局部變量
通過@符號使用Python的局部變量,@符號表示其后緊隨的是一個變量名稱而不是列名稱,如下:
>>> add = pd.Series([1,2,3,4,5,6,7,8]) >>> df.eval('score_math+@add') 0 96.0 1 98.0 2 88.0 3 97.0 4 89.0 5 94.0 6 66.0 7 96.0 8 NaN dtype: float64
二、DataFrame.query()方法
query()可以實現查詢過濾的功能,其用於與DataFrame.eval()類似。
>>> df.query("score_math>85 & score_music>85") class sex score_math score_music sum_score 1 A female 96 90 186 3 C male 93 92 185 7 A male 88 86 174
注意:DtaFrame.eval()盡心相同運算時返回的是布爾值