高效计算 Pandas 数据框的滚动平均值

4

我有一个庞大的数据框,经常需要添加单行数据。我希望在添加单行数据后更新滚动均值(在最近的时间窗口内)和标准差。是否有人知道 Pandas 是否会使用新包含/删除行的增量在恒定时间内自动执行此操作,还是实际上需要重新计算所有总和和平方和?

编辑:已要求提供示例以解释我的意思,即恒定时间滚动均值更新:

data_set = (1,2,3)
old_mean = 2

new_value: 4
expired_value = 1
new_mean = (old_mean * num_of_values - expired_value + new_value) / num_values
         = (2 * 3 - 1 + 4) / 3
         = 3

^常数时间。对于大型数据框架来说很重要。


1
这是一个相当简单的操作,请提供一个 [mcve]。 - user3483203
滚动平均部分很容易理解,但是您仍然没有提供DataFrame。听起来您只是想要df.rolling(3).mean() - user3483203
所以我的问题是,mean()部分是否是一个属性,在添加新行时以恒定时间更新,还是一个费力地遍历DF滚动部分中的所有行的方法,每次添加时都要执行? - jsstuball
1个回答

3
从性能数据和代码来看,似乎pandas没有进行你所请求的任何优化(我对代码没有深入了解,所以可能会错过一些东西)。只需要看一下Window操作是如何实现的,就不会找到任何考虑任何预计算值的过滤器。 如果你想一想,你可能会得出这样的结论,即Pandas需要记住所有“脏”的行,其中值已经更改。这是一个相当消耗内存的操作。 从性能数字来看,这个结论也是正确的。
import pandas
import numpy
df = pandas.DataFrame({'A':numpy.random.random(20000000)})
r = df.rolling(3)

.

%%time
r.mean()

CPU时间:用户使用312毫秒,系统使用515毫秒,总共用时828毫秒。墙上的时间是836毫秒。

# Add one row
df.loc[len(df)] = {'A': numpy.random.random(1)[0]}

.

%%time
r.mean()

CPU时间:用户用时334毫秒,系统用时534毫秒,总用时868毫秒。 墙上时间:950毫秒。 无论您执行单元格的次数如何,这些时间几乎不会改变。 那么,如何提高运行效率? 让我们使用此基础结果来与其他结果进行比较:

%timeit df.rolling(3).mean()

每循环一次,平均执行时间为 854 毫秒 ± 38.5 毫秒(7 次运行的平均值及标准差,每次循环 1 次)

这将计算窗口大小为 3 的所有行的平均值。 如果要基于最后相关行计算您的新行的平均值,则可以仅使用 pandas 来执行此操作:

%timeit df.iloc[-3:, df.columns.get_loc('A')].mean()

每次循环平均需要192微秒,标准差为21.9微秒(7次运行,每次1000次循环)。

这已经比原来快了4000倍以上。但是直接使用numpy还可以提高性能:

%timeit df.values[-3:].mean()

每次循环的平均值为15.2微秒,标准偏差为699纳秒(7次运行,每次100000次循环)。

这远远超过了8000倍。除非付出更多的努力,否则它就已经达到了极限。但要注意,当自己在较低层次上实现操作时,您会失去pandas提供的一些方便(例如类型检查和转换等)。如果您想使用Cython,则更加如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接