从性能数据和代码来看,似乎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毫秒。
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,则更加如此。
df.rolling(3).mean()
。 - user3483203