加速数据帧分组聚合的优化方法

2024-09-29 21:57:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个大数据帧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聚合需要几分钟的时间。在我的例子中,什么是加速这个过程的最佳方式,多处理可以工作吗


Tags: 数据returndefstocknppriceseriespd
1条回答
网友
1楼 · 发布于 2024-09-29 21:57:30

当有直接可用的内置和可能优化的函数时,您真的不需要.agg^默认情况下,{}被忽略。只需单独计算所需的列,并在以后使用它们

基准测试:在我运行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...

然后,您可以根据需要使用这些数据集。e、 g.使用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

注意tot部分的溢出仅仅是因为重复增量。这不会发生在真实数据中

相关问题 更多 >

    热门问题