2015-02-11 57 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]) 

現在工作得很好。