首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在熊猫DataFrame上运行更快的rolling_apply?

在熊猫DataFrame上运行更快的rolling_apply?
EN

Stack Overflow用户
提问于 2014-08-30 22:34:30
回答 2查看 4.7K关注 0票数 3

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

环境: Python 2.7.8,Pandas 14.1,Numpy 1.8。

下面是示例设置:

代码语言:javascript
复制
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)这样的函数将无法工作。

但是,我可以这样做:

代码语言:javascript
复制
res2 = (pd.rolling_max(df['A'],26) + pd.rolling_max(df['B'],26)) / 2

它的完成速度大约快3000倍:

代码语言:javascript
复制
%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,它可以应用于更广泛的问题集

编辑:性能计时校正

EN

回答 2

Stack Overflow用户

发布于 2014-08-31 01:39:52

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

rolling_minrolling_max特别借鉴了bottleneck的实现,它引用了Richard Harter作为算法的来源,尽管我在this paper中找到了我认为是对相同算法的早期描述。

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

票数 7
EN

Stack Overflow用户

发布于 2014-08-31 07:41:47

您将无法获得rolling_max速度,但是您通常可以通过.values将速度降低一个数量级左右,即使用numpy

代码语言:javascript
复制
def meanmax_np(ii, df):
    ii = ii.astype(int)
    n = df["A"].values[ii].max() + df["B"].values[ii].max()
    return n/2.0

给了我

代码语言:javascript
复制
>>> %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倍,但比原始情况快得多。有时,当我只需要一个东西快十倍的时候,它不是主要的时间链接就足够了。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25583494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档