如何矢量化基于最后x行数据的Pandas计算

时间:2016-06-26 04:49:00

标签: python pandas

我有一个相当复杂的预测代码,每列使用wls超过20列和数百万数据。现在我使用iterrow循环日期,然后根据这些日期中的日期和值,提取不同大小的数据进行计算。在我的制作中运行需要几个小时,我将代码简化为以下内容:

import pandas as pd
import numpy as np
from datetime import timedelta

df=pd.DataFrame(np.random.randn(1000,2), columns=list('AB'))
df['dte'] = pd.date_range('9/1/2014', periods=1000, freq='D')

def calculateC(A, dte):
    if A>0: #based on values has different cutoff length for trend prediction
        depth=10
    else:
        depth=20
    lastyear=(dte-timedelta(days=365)) 
    df2=df[df.dte<lastyear].head(depth) #use last year same date data for basis of prediction
    return df2.B.mean() #uses WLS in my model but for simplification replace with mean

for index, row in df.iterrows():
    if index>365:
        df.loc[index,'C']=calculateC(row.A, row.dte)

我读到iterrow是主要原因,因为它不是使用Pandas的有效方法,我应该使用vector方法。但是,我似乎无法根据条件(日期,不同长度和值范围)找到一种矢量方法。有办法吗?

2 个答案:

答案 0 :(得分:2)

我有好消息和坏消息。好消息是我有一些矢量化的速度大约快300倍,但坏消息是我不能完全复制你的结果。但我认为您应该能够使用此处的原则来大大加快代码速度,即使此代码实际上并未实际复制您的结果。

df['result'] = np.where( df['A'] > 0,
                         df.shift(365).rolling(10).B.mean(),
                         df.shift(365).rolling(20).B.mean() )

代码的难度(慢)部分是这样的:

df2=df[df.dte<lastyear].head(depth)

但是,只要您的日期相隔365天,您就可以使用这样的代码,它是矢量化的,速度更快:

df.shift(365).rolling(10).B.mean()

shift(365)取代df.dte < lastyearrolling().mean()取代head().mean()。它会更快,使用更少的内存。

实际上,即使您的日期不是完全正常的,您也可以重新采样并使这种方式起作用。或者,在某种程度上,如果您将日期作为索引,则可以根据频率而不是行来进行转换(例如,转换365天,即使不是365行)。制作&#39; dte&#39;可能是一个好主意。你的索引无论如何。

答案 1 :(得分:0)

我会尝试pandas.DataFrame.apply(func,axis = 1)

def calculateC2(row):
    if row.name >365: # row.name is the index of the row
        if row.A >0: #based on values has different cutoff length for trend prediction
            depth=10
        else:
            depth=20
        lastyear=(row.dte-timedelta(days=365)) 
        df2=df[df.dte<lastyear].B.head(depth) #use last year same date data for basis of prediction
        print row.name,np.mean(df2) #uses WLS in my model but for simplification replace with mean

df.apply(calculateC2,axis=1)