Pandas DataFrame如何进行更快的rolling_apply?

2024-10-01 07:39:59 发布

您现在位置:Python中文网/ 问答频道 /正文

this question为在数据帧中的多个列上应用函数提供了一个聪明的解决方案,我想知道该解决方案是否可以进一步优化以提高速度。在

环境:python2.7.8,Pandas 14.1,numpy1.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)的函数将不起作用。在

不过,我可以做一些类似的事情:

^{pr2}$

完成速度大约快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,它可以应用于更广泛的问题集

编辑:性能计时修正


Tags: 函数import示例dfasnp解决方案速度
2条回答

你不能降到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

给了我

^{pr2}$

虽然仍然比优化后的情况慢100倍,但比原来快得多。有时候,我只需要速度快十倍的东西,就不会成为占主导地位的时间链,这就足够了。在

在一个大小为n且窗口大小为m的数组上计算通用滚动函数大约需要O(n*m)时间。内置的rollin_xxx方法使用一些非常聪明的算法来保持运行时间远低于该时间,并且通常可以保证O(n)时间,如果你认为这是一件令人印象深刻的事情。在

rolling_min和{}尤其是借用了bottleneck的实现,后者引用了Richard Harter作为算法的源代码,尽管我在{a3}中发现了我认为的相同算法的早期描述。在

所以在历史课之后:很有可能你不能吃你的蛋糕。rolling_apply非常方便,但它几乎总是牺牲特定算法的性能。根据我的经验,使用Python科学堆栈的一个更有趣的部分是,使用以创造性方式提供的快速原语来实现高效的计算方法。您自己的解决方案调用rolling_max两次就是一个很好的例子。因此,放松并享受这段旅程吧,要知道,如果你或其他好人无法找到更明智的解决方案,你将永远有机会依靠。在

相关问题 更多 >