在 groupby 之后采用滚动前求和的更快方法?
Faster way to take rolling forward sum after groupby?
我正在尝试获取每天前 n 分钟 return 的股票,给定一个数据框,其中的行在某些时间间隔对应于 returns。
我试过使用 dask 和多线程对每个组进行滚动计算,但这似乎是我能想到的最快的方法。然而,对于大型数据框(数百万行)(252 天和 1000 只股票),执行此步骤最多需要 40 分钟。
ret_df.sort_values(['date','time','stock'], ascending=False, inplace=True)
gb = ret_df.groupby(['date','stock'])
forward_sum_df = gb.rolling(4, on='time', min_periods = 0)['interval_return'].sum().reset_index()
这将 return 数据框中每一行的接下来 4 次(按日期和股票)的总和,正如预期的那样,但速度很慢。感谢您的帮助!
编辑:添加示例以阐明
date stock time interval_ret
0 2017-01-03 10000001 09:30:00.000000 0.001418
1 2017-01-03 10000001 09:40:00.000000 0.000000
2 2017-01-03 10000001 09:50:00.000000 0.000000
3 2017-01-03 10000001 10:00:00.000000 -0.000474
4 2017-01-03 10000001 10:10:00.000000 -0.001417
5 2017-01-03 10000001 10:20:00.000000 -0.000944
6 2017-01-03 10000001 10:30:00.000000 0.000000
7 2017-01-03 10000001 10:40:00.000000 0.000000
8 2017-01-03 10000001 10:50:00.000000 0.000000
9 2017-01-03 10000001 11:00:00.000000 -0.000472
以此类推库存 10000002...和日期 2017-01-04....
例如,如果我的持有时间是 30 分钟而不是 10 分钟,我想总结 3 行 'interval_ret',按日期和股票分组。例如:
date stock time interval_ret_30
0 2017-01-03 10000001 09:30:00.000000 0.001418
1 2017-01-03 10000001 09:40:00.000000 0.000000 - 0.000474
2 2017-01-03 10000001 09:50:00.000000 0.000000 - 0.000474 - 0.001417
3 2017-01-03 10000001 10:00:00.000000 -0.000474 - 0.001417 - 0.000944
4 2017-01-03 10000001 10:10:00.000000 -0.001417 - 0.000944
5 2017-01-03 10000001 10:20:00.000000 -0.000944
6 2017-01-03 10000001 10:30:00.000000 0.000000
7 2017-01-03 10000001 10:40:00.000000 -0.000472
8 2017-01-03 10000001 10:50:00.000000 -0.000472
9 2017-01-03 10000001 11:00:00.000000 -0.000472
我不知道你是否可以将其适应 pandas,但你可以使用 numpy 在不到一秒的时间内获得 2000 万个值的滚动累积和:
N = 20000000
stocks = (np.random.random(N)*100)
window = 4
cumStocks = np.cumsum(np.append(stocks,np.zeros(window)))
rollSum = cumStocks[window:] - cumStocks[:-window]
诀窍是计算整个数组的累积和,然后用与 window 的大小相对应的偏移量从自身中减去结果数组。
cumsum 源数组用零填充以保持原始大小。比 window 大小更接近数组末尾的最后几个元素将仅获得剩余值的滚动总和。如果你不需要这些 "incomplete" 和,你可以简单地使用 cumStocks = np.cumsum(stocks)
并且计算将能够在一秒钟内完成 1 亿个值。
有人似乎在这里使用 pandas 找到了解决此问题的方法:
df.groupby(level=0).cumsum() - df.groupby(level=0).cumsum().shift(5)
我正在尝试获取每天前 n 分钟 return 的股票,给定一个数据框,其中的行在某些时间间隔对应于 returns。
我试过使用 dask 和多线程对每个组进行滚动计算,但这似乎是我能想到的最快的方法。然而,对于大型数据框(数百万行)(252 天和 1000 只股票),执行此步骤最多需要 40 分钟。
ret_df.sort_values(['date','time','stock'], ascending=False, inplace=True)
gb = ret_df.groupby(['date','stock'])
forward_sum_df = gb.rolling(4, on='time', min_periods = 0)['interval_return'].sum().reset_index()
这将 return 数据框中每一行的接下来 4 次(按日期和股票)的总和,正如预期的那样,但速度很慢。感谢您的帮助!
编辑:添加示例以阐明
date stock time interval_ret
0 2017-01-03 10000001 09:30:00.000000 0.001418
1 2017-01-03 10000001 09:40:00.000000 0.000000
2 2017-01-03 10000001 09:50:00.000000 0.000000
3 2017-01-03 10000001 10:00:00.000000 -0.000474
4 2017-01-03 10000001 10:10:00.000000 -0.001417
5 2017-01-03 10000001 10:20:00.000000 -0.000944
6 2017-01-03 10000001 10:30:00.000000 0.000000
7 2017-01-03 10000001 10:40:00.000000 0.000000
8 2017-01-03 10000001 10:50:00.000000 0.000000
9 2017-01-03 10000001 11:00:00.000000 -0.000472
以此类推库存 10000002...和日期 2017-01-04....
例如,如果我的持有时间是 30 分钟而不是 10 分钟,我想总结 3 行 'interval_ret',按日期和股票分组。例如:
date stock time interval_ret_30
0 2017-01-03 10000001 09:30:00.000000 0.001418
1 2017-01-03 10000001 09:40:00.000000 0.000000 - 0.000474
2 2017-01-03 10000001 09:50:00.000000 0.000000 - 0.000474 - 0.001417
3 2017-01-03 10000001 10:00:00.000000 -0.000474 - 0.001417 - 0.000944
4 2017-01-03 10000001 10:10:00.000000 -0.001417 - 0.000944
5 2017-01-03 10000001 10:20:00.000000 -0.000944
6 2017-01-03 10000001 10:30:00.000000 0.000000
7 2017-01-03 10000001 10:40:00.000000 -0.000472
8 2017-01-03 10000001 10:50:00.000000 -0.000472
9 2017-01-03 10000001 11:00:00.000000 -0.000472
我不知道你是否可以将其适应 pandas,但你可以使用 numpy 在不到一秒的时间内获得 2000 万个值的滚动累积和:
N = 20000000
stocks = (np.random.random(N)*100)
window = 4
cumStocks = np.cumsum(np.append(stocks,np.zeros(window)))
rollSum = cumStocks[window:] - cumStocks[:-window]
诀窍是计算整个数组的累积和,然后用与 window 的大小相对应的偏移量从自身中减去结果数组。
cumsum 源数组用零填充以保持原始大小。比 window 大小更接近数组末尾的最后几个元素将仅获得剩余值的滚动总和。如果你不需要这些 "incomplete" 和,你可以简单地使用 cumStocks = np.cumsum(stocks)
并且计算将能够在一秒钟内完成 1 亿个值。
有人似乎在这里使用 pandas 找到了解决此问题的方法:
df.groupby(level=0).cumsum() - df.groupby(level=0).cumsum().shift(5)