2015-02-11 1 views
0

я пытаюсь вычислить коэффициенты из п градусного полинома применяется к т -дня окна временного ряда. Однако я получаю исключение 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_apply. В documentation говорится, что прикладная функция «должна выводить одно значение из входа ndarray». На самом деле это означает, что «необходимо произвести значение , которое может быть преобразовано в один поплавок». Если вы будете следовать на полном TRACEBACK исключение это приводит вас к этому коду в 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 float. Ошибка вы получаете то же самое, что вы получите, если вы пытаетесь преобразовать 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]]

Вот мое решение, основанное на некорректных методах кодирования, но выполняет свою работу. Возвратите индекс в глобальный dict/array из roll_apply() и выбросите возвращаемые значения. Решение готово в dict, когда roll_apply возвращается.

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] в лямбда-функции:

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

Он теперь работает отлично.

Смежные вопросы