2015-02-11 30 views
0

我试图计算系数从一个n -degree多项式适用于一个时间序列的日期窗口t。但是,我收到一个例外TypeError: only length-1 arrays can be converted to Python scalars滚动窗口多项式拟合熊猫

我的版本是:

  • 的Python 3.6
  • 大熊猫版本0.22.0
  • numpy的版本1.13.3

代码:

import pandas as pd 
import numpy as np 
my_ts = pd.Series(data = np.random.normal(size = 365 * 2), index = pd.date_range(start = '2013-01-01', periods = 365 * 2)) 
coefs = pd.rolling_apply(my_ts, 21, lambda x: np.polyfit(range(len(x)), x, 3)) 

然而,当我包装np.polyfit时如此它只返回一个系数,rolling_apply没有问题。

def pf_wrapper(x): 
    coef_lst = np.polyfit(range(len(x)), x, 3) 
    return coef_lst[0] 
coefs = pd.rolling_apply(my_ts, 21, pf_wrapper) 

UPDATE:

由于pd.rolling_apply()无法返回一个非标,我目前的解决方案是:

def get_beta(ts, deg): 
    coefs = polyfit(range(len(ts)), ts, deg = 3)[::-1] 
    return coefs[deg] 

b0 = pd.rolling_apply(my_ts, 21, lambda x: get_beta(x, 0)) 
... 
b3 = pd.rolling_apply(my_ts, 21, lambda x: get_beta(x, 3)) 

回答

1

我不认为这是可能的rolling_applydocumentation表示应用函数“必须从ndarray输入生成单个值”。它看起来实际上意味着“必须产生一个价值,或者可以转换成单个浮动”。如果您在充分例外回溯追踪它会导致你的代码中algos.pyx

output = np.empty(n, dtype=float) 
counts = roll_sum(np.isfinite(input).astype(float), win, minp) 

bufarr = np.empty(win, dtype=float) 
oldbuf = <float64_t*> bufarr.data 

n = len(input) 
for i from 0 <= i < int_min(win, n): 
    if counts[i] >= minp: 
     output[i] = func(input[int_max(i - win + 1, 0) : i + 1], *args, 
         **kwargs) 
    else: 
     output[i] = NaN 

的误差与output[i] = func(...)行提出。你可以看到输出数组被硬编码为dtype浮点数。您收到的错误是一样的,如果你试图将一个numpy的数组转换(长度大于1)的浮动你会得到什么:

>>> float(np.array([1, 2, 3])) 
Traceback (most recent call last): 
    File "<pyshell#14>", line 1, in <module> 
    float(np.array([1, 2, 3])) 
TypeError: only length-1 arrays can be converted to Python scalars 

所以发生的是,它试图分配的输出polyfit复制到float ndarray的单个元素,并失败,因为polyfit的输出是不能转换为float的数组。

这可以通过使output具有dtype对象来“固定”,但这会减慢速度。

我认为你必须考虑rolling_apply仅适用于返回单个浮点数的函数。要支持非标量输出,您必须滚动(har har)您自己的rolling_apply版本。

0

我想创建一个IIR滤波器类型的时间序列的扩展。例如:[1,2,3,4,5]窗口= 2应该给出:[[1,2],[2,3],[3,4],[4,5]]

这是我的解决方案,基于一些不好的编码习惯,但完成了工作。 从rolling_apply()返回全局字典/数组的索引并丢弃返回值。当rolling_apply返回时,解决方案已经在dict中准备好了。

import pandas as pd 
import numpy as np 

dataDict = dict() 
INDEX = 0 

def windowFunc(w): 
    global INDEX 
    global dataDict 
    dataDict[INDEX] = np.copy(w) 
    INDEX = INDEX + 1 
    return INDEX 

dd = pd.DataFrame([1,2,3,4,5,6,7,8,9,0]) 
dd2 = pd.rolling_apply(dd, window=2, func = windowFunc) 
print(list(dataDict.values())) 
0

我遇到了同样的问题来了,你可以[0]添加到lambda函数:

coefs = pd.rolling_apply(my_ts, 21, lambda x: np.polyfit(range(len(x)), x, 3)[0]) 

现在工作得很好。