改进了this question,它为在DataFrame中的多个列应用函数提供了一个聪明的解决方案,我想知道这个解决方案是否可以进一步优化速度。
环境: Python 2.7.8,Pandas 14.1,Numpy 1.8。
下面是示例设置:
import pandas as pd
import numpy as np
import random
def meanmax(ii,df):
xdf = df.iloc[map(int,ii)]
n = max(xdf['A']) + max(xdf['B'])
return n / 2.0
df = pd.DataFrame(np.random.randn(2500,2)/10000,
index=pd.date_range('2001-01-01',periods=2500),
columns=['A','B'])
df['ii'] = range(len(df))
res = pd.rolling_apply(df.ii, 26, lambda x: meanmax(x, df))请注意,meanmax函数不是成对的,因此像rolling_mean(df['A'] + df['B'],26)这样的函数将无法工作。
但是,我可以这样做:
res2 = (pd.rolling_max(df['A'],26) + pd.rolling_max(df['B'],26)) / 2它的完成速度大约快3000倍:
%timeit res = pd.rolling_apply(df.ii, 26, lambda x: meanmax(x, df))
1 loops, best of 3: 1 s per loop
%timeit res2 = (pd.rolling_max(df['A'],26) + pd.rolling_max(df['B'],26)) / 2
1000 loops, best of 3: 325 µs per loop在给定示例函数并使用rolling_apply的情况下,有没有比上面的第二种选择更好/更等效的方法?虽然第二种方法速度更快,但它不使用rolling_apply,它可以应用于更广泛的问题集
编辑:性能计时校正
发布于 2014-08-31 01:39:52
在具有m大小的窗口的n大小的数组上计算通用滚动函数大约需要O(n*m)时间。内置的rollin_xxx方法使用了一些非常智能的算法来将运行时间保持在较低的水平,并且通常可以保证O(n)时间,如果你认为这是一个非常令人印象深刻的事情。
rolling_min和rolling_max特别借鉴了bottleneck的实现,它引用了Richard Harter作为算法的来源,尽管我在this paper中找到了我认为是对相同算法的早期描述。
所以在历史课之后:你很可能吃不下你的蛋糕。rolling_apply非常方便,但它几乎总是要牺牲特定算法的性能。根据我的经验,使用Python科学堆栈的一个更有趣的部分是提出高效的计算方法,使用以创造性方式提供的快速原语。您自己的解决方案调用rolling_max两次就是一个很好的例子。所以,放轻松,享受这段旅程,知道如果你或SO的好朋友不能提供更聪明的解决方案,你将永远有rolling_apply可以依靠。
发布于 2014-08-31 07:41:47
您将无法获得rolling_max速度,但是您通常可以通过.values将速度降低一个数量级左右,即使用numpy
def meanmax_np(ii, df):
ii = ii.astype(int)
n = df["A"].values[ii].max() + df["B"].values[ii].max()
return n/2.0给了我
>>> %timeit res = pd.rolling_apply(df.ii, 26, lambda x: meanmax(x, df))
1 loops, best of 3: 701 ms per loop
>>> %timeit res_np = pd.rolling_apply(df.ii, 26, lambda x: meanmax_np(x, df))
10 loops, best of 3: 31.2 ms per loop
>>> %timeit res2 = (pd.rolling_max(df['A'],26) + pd.rolling_max(df['B'],26)) / 2
1000 loops, best of 3: 247 µs per loop它虽然仍然比优化后的情况慢100倍,但比原始情况快得多。有时,当我只需要一个东西快十倍的时候,它不是主要的时间链接就足够了。
https://stackoverflow.com/questions/25583494
复制相似问题