Python pandas rolling_apply将两列输入到函数中

h.l*_*l.m 14 python pandas

继续这个问题Python自定义函数使用rolling_apply进行pandas,关于使用rolling_apply.虽然我已经使用了我的函数,但我正在努力处理需要两列或更多列作为输入的函数:

创建与以前相同的设置

import pandas as pd
import numpy as np
import random

tmp  = pd.DataFrame(np.random.randn(2000,2)/10000, 
                    index=pd.date_range('2001-01-01',periods=2000),
                    columns=['A','B'])
Run Code Online (Sandbox Code Playgroud)

但稍微改变功能需要两列.

def gm(df,p):
    df = pd.DataFrame(df)
    v =((((df['A']+df['B'])+1).cumprod())-1)*p
    return v.iloc[-1]
Run Code Online (Sandbox Code Playgroud)

它会产生以下错误:

pd.rolling_apply(tmp,50,lambda x: gm(x,5))

  KeyError: u'no item named A'
Run Code Online (Sandbox Code Playgroud)

我认为这是因为lambda函数的输入是长度为50且仅在第一列的ndarray,并且不会将两列作为输入.有没有办法将两列作为输入并在rolling_apply函数中使用它.

再次感谢任何帮助......

cal*_*ini 9

不确定这里是否仍然相关,对于 Pandasrolling上的新类,每当我们传递raw=False到 时apply,我们实际上是将系列传递给包装器,这意味着我们可以访问每个观察的索引,并且可以使用它来进一步处理多列.

从文档:

raw : bool, 默认无

False :将每一行或每一列作为系列传递给函数。

True 或 None :传递的函数将接收 ndarray 对象。如果您只是应用 NumPy 缩减功能,这将获得更好的性能。

在这种情况下,我们可以执行以下操作:

### create a func for multiple columns
def cust_func(s):

    val_for_col2 = df.loc[s.index, col2] #.values
    val_for_col3 = df.loc[s.index, col3] #.values
    val_for_col4 = df.loc[s.index, col4] #.values
    
    ## apply over multiple column values
    return np.max(s) *np.min(val_for_col2)*np.max(val_for_col3)*np.mean(val_for_col4)
    

### Apply to the dataframe
df.rolling('10s')['col1'].apply(cust_func, raw=False)
Run Code Online (Sandbox Code Playgroud)

请注意,这里我们仍然可以使用pandas rolling类中的所有功能,这在处理与时间相关的窗口时特别有用。

我们传递一列并使用整个数据框的事实感觉像是一种黑客攻击,但它在实践中是有效的。


low*_*ech 8

看起来像rolling_apply会尝试将用户func的输入转换为ndarray(http://pandas.pydata.org/pandas-docs/stable/generated/pandas.stats.moments.rolling_apply.html?highlight=rolling_apply#pandas.stats. moments.rolling_apply).

基于使用aux column ii的解决方法,用于选择操作函数gm中的窗口:

import pandas as pd
import numpy as np
import random

tmp = pd.DataFrame(np.random.randn(2000,2)/10000, columns=['A','B'])
tmp['date'] = pd.date_range('2001-01-01',periods=2000)
tmp['ii'] = range(len(tmp))            

def gm(ii, df, p):
    x_df = df.iloc[map(int, ii)]
    #print x_df
    v =((((x_df['A']+x_df['B'])+1).cumprod())-1)*p
    #print v
    return v.iloc[-1]

#print tmp.head()
res = pd.rolling_apply(tmp.ii, 50, lambda x: gm(x, tmp, 5))
print res
Run Code Online (Sandbox Code Playgroud)


alk*_*lko 0

所有rolling_* 函数都适用于一维数组。我确信人们可以发明一些传递二维数组的解决方法,但在您的情况下,您可以简单地预先计算行方向值以进行滚动评估:

>>> def gm(x,p):
...     return ((np.cumprod(x) - 1)*p)[-1]
...
>>> pd.rolling_apply(tmp['A']+tmp['B']+1, 50, lambda x: gm(x,5))
2001-01-01   NaN
2001-01-02   NaN
2001-01-03   NaN
2001-01-04   NaN
2001-01-05   NaN
2001-01-06   NaN
2001-01-07   NaN
2001-01-08   NaN
2001-01-09   NaN
2001-01-10   NaN
2001-01-11   NaN
2001-01-12   NaN
2001-01-13   NaN
2001-01-14   NaN
2001-01-15   NaN
...
2006-06-09   -0.000062
2006-06-10   -0.000128
2006-06-11    0.000185
2006-06-12   -0.000113
2006-06-13   -0.000962
2006-06-14   -0.001248
2006-06-15   -0.001962
2006-06-16   -0.003820
2006-06-17   -0.003412
2006-06-18   -0.002971
2006-06-19   -0.003882
2006-06-20   -0.003546
2006-06-21   -0.002226
2006-06-22   -0.002058
2006-06-23   -0.000553
Freq: D, Length: 2000
Run Code Online (Sandbox Code Playgroud)