【问题标题】:Speeding up the calculation of a rolling mean/std within a grouped pandas dataframe加快分组熊猫数据帧中滚动平均值/标准差的计算
【发布时间】:2018-02-08 05:27:40
【问题描述】:

我有一个 DataFrame,其中包含代表组、时间和值的三列。我想计算每组内的滚动平均值、标准偏差等。现在我定义一个函数并使用apply。然而,这在非常大的数据集上非常慢。下面是函数。

def GetRollingMetrics(x, cols, windows, suffix):
    for col in cols:
        for win in windows:
            x[col + '_' + str(win) + 'D' + '_mean' + '_' + suffix] = x.shift(1).rolling(win)[col].mean()
            x[col + '_' + str(win) + 'D' + '_std' + '_' + suffix] = x.shift(1).rolling(win)[col].std()
            x[col + '_' + str(win) + 'D' + '_min' + '_' + suffix] = x.shift(1).rolling(win)[col].min()
            x[col + '_' + str(win) + 'D' + '_max' + '_' + suffix] = x.shift(1).rolling(win)[col].max()

    return x

然后应用它,例如,我使用:

df = pd.DataFrame(np.random.randint(0,100,size=(1000000, 3)), columns=['Group','Time','Value'])
df.sort_values(by='Time', inplace=True)
df = df.groupby('Group').apply(lambda x: GetRollingMetrics(x, ['Value'], [7,14,28], 'my_suffix'))

有没有更“Pandaic”或更有效的方法来做到这一点?

【问题讨论】:

  • "Pandaic" ... :-) 另外,您想为每个列和每个窗口计算这些滚动统计信息吗?
  • 好吧,在这个例子中我只有一列“值”,但我可能想为多列和多个窗口大小计算它,因此 cols 是一个列表。
  • 和“Pandaic”听起来更好 - 编辑:)
  • 查看jonisalonen.com/2014/…。您可以利用将方差分解为平方和和平方和:在每一步从尾部截取一个点并将新数据添加到头部。
  • 您现有的方法需要多长时间?

标签: python performance function pandas dataframe


【解决方案1】:

我重构了你的函数以使用agg(),这样我们就可以一次性准备好每个窗口的所有数据:

def GetRollingMetrics(x, cols, windows, suffix):
    for win in windows:
        aggs = {col: ['mean', 'std', 'min', 'max'] for col in cols}
        df = x.shift(1).rolling(win).agg(aggs)
        # the real work is done, just copy the columns into x
        for col in cols:
            prefix = col + '_' + str(win) + 'D'
            for stat in ('mean', 'std', 'min', 'max'):
                x['_'.join((prefix, stat, suffix))] = df[col][stat]
    return x

如果您有多个列,则速度会更快。如果你只有一列,它似乎并没有快多少。 for stat 循环肯定有改进的空间——复制大约需要一半的时间。也许您可以改用重命名,然后将结果连接起来?

如果您迫切希望进一步加快这一速度,您应该考虑使用 Numba,它可以让您实现一次性最小/最大/总和,然后您可以将其用于所有滚动计算。我以前做过,你可以在不比现在多多少时间的时间内完成所有四个计算(因为昂贵的部分是将数据加载到缓存中)。

【讨论】:

    猜你喜欢
    • 2019-11-19
    • 2021-06-03
    • 2020-03-06
    • 2014-09-28
    • 1970-01-01
    • 2019-11-24
    • 2020-03-19
    • 2017-08-03
    • 2021-09-23
    相关资源
    最近更新 更多