如何在滚动数据的子集上应用滚动聚合函数?

时间:2019-04-27 13:24:58

标签: python python-3.x pandas performance

假设我有一个大数据集,并且我想长时间应用滚动操作,但是只想对少量数据点应用聚合。我可以用pandas吗?

当我尝试对聚合函数的结果应用切片器时,看来我来不及了,整个计算已经发生了:

small = 10
big = 1000
bigger = 10000000
s = pd.Series(np.arange(bigger))

%time x = s.rolling(big).mean()
%time x = s.rolling(big).mean()[:-small]

此输出为:

CPU times: user 306 ms, sys: 162 ms, total: 467 ms
Wall time: 468 ms
CPU times: user 291 ms, sys: 127 ms, total: 418 ms
Wall time: 418 ms

在上面的示例中,我希望第二个定时表达式可以更快地运行,因为我只需要在最后10个数据点上计算聚合,但是花费的时间与计算1000万个相同的时间

我在这里做什么错了?

在我的实际情况中,我同时使用rollingexpanding,所以我正在寻找一种适用于两者的解决方案。另外,在我的实际示例中,bigbigger几乎相同。

编辑:以下内容说明了计算滚动平均值与没有冗余计算的计算之间的性能差异。它计算朴素的大小写,通过3UqU57GnaX的解决方案以及“手动”计算。请注意,手动计算是我通常希望实现的(显然,我不想手动实现每个聚合函数):

import pandas as pd
import numpy as np

small = 10
big = 10000000
bigger = 100000000
s = pd.Series(np.arange(bigger))

def adjusted_mean(current_mean, removed_element, new_element, length):
    return current_mean + (new_element - removed_element) / length

def rolling_mean_optimisation(small, big):
    current_mean = s[-big-small:-small].mean()

    return [adjusted_mean(current_mean, s.values[-big-x], s.values[-x], big) for x in range(small, 0, -1)]

%time naive = s.rolling(big).mean()[-small:]
%time answer_by_3UqU57GnaX = s[-big-small:].rolling(big).mean()[-small:]
%time manual_mean_optimisation = rolling_mean_optimisation(small, big)

尽管3UqU57GnaX的回答比单纯的情况有了很大的改进,但是手动实现的速度仍然快了一个数量级(实际数量取决于big与{{1的大小}}:

bigger

1 个答案:

答案 0 :(得分:1)

自从您第一次在整个系列中应用rollingmean以来,这花费了相同的时间。

如果仅将其应用于最后10个数据点(s[-10:]),则会更快:

s[-10:].rolling(1000).mean()

但是,这将为您提供NaN值,因为您仅使用最后10个数据点,但滚动平均值需要1000个数据点。

编辑:这不会给您NaN,应该更快:

s[-big-small:].rolling(big).mean()[-small:]