【问题标题】:Using rolling_apply on a DataFrame object在 DataFrame 对象上使用 rolling_apply
【发布时间】:2013-10-07 22:44:23
【问题描述】:

我正在尝试滚动计算成交量加权平均价格。

为此,我有一个函数 vwap 可以为我执行此操作,如下所示:

def vwap(bars):
    return ((bars.Close*bars.Volume).sum()/bars.Volume.sum()).round(2)

当我尝试将此函数与 rolling_apply 一起使用时,如图所示,出现错误:

import pandas.io.data as web
bars = web.DataReader('AAPL','yahoo')
print pandas.rolling_apply(bars,30,vwap)

AttributeError: 'numpy.ndarray' object has no attribute 'Close'

这个错误对我来说很有意义,因为 rolling_apply 不需要 DataSeries 或 ndarray 作为输入,而不是 dataFrame.. 我这样做的方式。

有没有办法使用 rolling_apply 到 DataFrame 来解决我的问题?

【问题讨论】:

标签: python pandas


【解决方案1】:

这个不是直接启用的,但是你可以这样做

In [29]: bars
Out[29]: 
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 942 entries, 2010-01-04 00:00:00 to 2013-09-30 00:00:00
Data columns (total 6 columns):
Open         942  non-null values
High         942  non-null values
Low          942  non-null values
Close        942  non-null values
Volume       942  non-null values
Adj Close    942  non-null values
dtypes: float64(5), int64(1)

window=30

In [30]: concat([ (Series(vwap(bars.iloc[i:i+window]),
                      index=[bars.index[i+window]])) for i in xrange(len(df)-window) ])
Out[30]: 
2010-02-17    203.21
2010-02-18    202.95
2010-02-19    202.64
2010-02-22    202.41
2010-02-23    202.19
2010-02-24    201.85
2010-02-25    201.65
2010-02-26    201.50
2010-03-01    201.31
2010-03-02    201.35
2010-03-03    201.42
2010-03-04    201.09
2010-03-05    200.95
2010-03-08    201.50
2010-03-09    202.02
...
2013-09-10    485.94
2013-09-11    487.38
2013-09-12    486.77
2013-09-13    487.23
2013-09-16    487.20
2013-09-17    486.09
2013-09-18    485.52
2013-09-19    485.30
2013-09-20    485.37
2013-09-23    484.87
2013-09-24    485.81
2013-09-25    486.41
2013-09-26    486.07
2013-09-27    485.30
2013-09-30    484.74
Length: 912

【讨论】:

  • 不错的解决方案,对我很有帮助!但是问题:在您的列表理解中,您不会使用 bar.iloc[i:i+window+1] 因为 .iloc 不包括上限吗?使用您的代码,在以 bar.iloc[i+window-1] 结尾的计算中仅使用 29 个值,而 bar.index[i+window] 用作标签。在这种计算中,我想你会希望 bar.iloc[i+window] 包含在计算中。
【解决方案2】:

清理后的版本供参考,希望索引正确:

def myrolling_apply(df, N, f, nn=1):
    ii = [int(x) for x in arange(0, df.shape[0] - N + 1, nn)]
    out = [f(df.iloc[i:(i + N)]) for i in ii]
    out = pandas.Series(out)
    out.index = df.index[N-1::nn]
    return(out)

【讨论】:

    【解决方案3】:

    修改了@mathtick 的答案以包含na_fill。另请注意,您的函数f 需要返回单个值,这不能返回具有多列的数据框。

    def rolling_apply_df(dfg, N, f, nn=1, na_fill=True):
        ii = [int(x) for x in np.arange(0, dfg.shape[0] - N + 1, nn)]
        out = [f(dfg.iloc[i:(i + N)]) for i in ii]
        if(na_fill):
            out = pd.Series(np.concatenate([np.repeat(np.nan, N-1),np.array(out)]))
            out.index = dfg.index[::nn]
        else:
            out = pd.Series(out)
            out.index = dfg.index[N-1::nn]
        return(out)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      • 2016-04-24
      • 2021-07-15
      • 1970-01-01
      相关资源
      最近更新 更多