[英]Optimal method to speed up Pandas Dataframe groupby aggregation
我有一個像這樣的大數據框price_d
:
+---------------------------------------------------+
| date monthEndDate stock volume logRet |
+---------------------------------------------------+
| 1990-01-01 1990-01-31 A 1 NA |
| 1990-01-02 1990-01-31 A 2 0.2 |
| 1990-02-01 1990-02-28 A 3 0.3 |
| 1990-02-02 1990-02-28 A 4 0.4 |
| ... ... |
| 1990-01-01 1990-01-31 B 1 NA |
| 1990-01-02 1990-01-31 B 2 0.08 |
| ... ... |
| 1990-02-01 1990-02-28 B 0 0.3 |
| 1990-02-02 1990-02-28 B 3 0.4 |
| ... ... |
+---------------------------------------------------+
該數據幀的長度將是數以百萬計,在數百個不同的值monthEndDate
,數千獨特價值的stock
。
我使用三個自定義函數對 volume 和 logRet 進行了 groupby 聚合:
def varLogRet(_s):
return pd.Series({'varLogRet': np.var(_s.iloc[_s.to_numpy().nonzero()])})
def TotRet1M(_s):
return pd.Series({'TotRet1M': np.exp(np.sum(_s))-1})
def avgVolume(_s):
return pd.Series({'avgVolume': np.mean(_s.iloc[_s.to_numpy().nonzero()])})
return_m = price_d.groupby(['monthEndDate', 'tradingItemId']).agg({'logRet': [varLogRet, TotRet1M],
'volume': avgVolume})
groupby 聚合需要幾分鍾的時間。 就我而言,加速此過程的最佳方法是什么,多處理是否有效?
當有內置的.agg
和可能直接可用的優化功能時,你真的不需要.agg
。 默認情況下忽略NaN
。 只需單獨計算您需要的列,然后再使用它們。
基准測試:在運行 64 位 debian 10 的普通 Core i5-8250U (4C8T) 筆記本電腦上,800 萬行不到 3 秒即可完成。數據是您提供的簡單重復數據。
# make a dataset of 8 million rows
df = pd.read_clipboard(sep=r"\s{2,}")
df2 = df.loc[df.index.repeat(1000000)].reset_index(drop=True)
# set 0's to nan's as requested...
df2[df2["logRet"] == 0] = np.nan
t0 = datetime.now()
dfgp = df2.groupby(['monthEndDate', 'stock']) # groupby object
# what you want
tot = np.exp(dfgp["logRet"].sum() - 1)
var = dfgp["logRet"].var() # ddof=1 by default in pandas 1.1.3
vol = dfgp["volume"].mean()
print(f"{(datetime.now() - t0).total_seconds():.2f}s elapsed...")
# 2.89s elapsed...
然后您可以根據需要使用這些數據集。 例如使用pd.concat([tot, var, vol], axis=1)
將它們組合在一起。
tot
Out[6]:
monthEndDate stock
1990-01-31 A inf <- will not happen with real data
B inf
1990-02-28 A inf
B inf
Name: logRet, dtype: float64
var
Out[7]:
monthEndDate stock
1990-01-31 A 0.0000
B 0.0000
1990-02-28 A 0.0025
B 0.0025
Name: logRet, dtype: float64
vol
Out[8]:
monthEndDate stock
1990-01-31 A 1.5
B 1.5
1990-02-28 A 3.5
B 1.5
Name: volume, dtype: float64
NB 在tot
部分發生溢出僅僅是因為重復增量。 這不會發生在真實數據中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.