2014-10-08 40 views
11

Mam szereg czasowy A posiadający kilka wartości. Muszę uzyskać szereg B który jest zdefiniowany następująco: algebraicznieDefinicje rekursywne w pandach

B[t] = a * A[t] + b * B[t-1] 

gdzie możemy założyć B[0] = 0 i a i b są liczbami rzeczywistymi.

Czy istnieje sposób na wykonanie tego typu obliczeń rekursywnych w Pandach? Czy nie mam innego wyjścia, jak zapętlić w Pythonie, jak zasugerowano w this answer?

Jako przykład wejścia:

> A = pd.Series(np.random.randn(10,)) 

0 -0.310354 
1 -0.739515 
2 -0.065390 
3 0.214966 
4 -0.605490 
5 1.293448 
6 -3.068725 
7 -0.208818 
8 0.930881 
9 1.669210 
+1

tu kwestią otwartą w celu cytonizacji: https://github.com/pydata/pandas/issues/4567, ale niektóre linki są również takie same. – Jeff

+2

Możesz użyć 'scipy.signal.lfilter'. Zobacz przykład: http://stackoverflow.com/questions/21336794/python-recursive-vectorization-with-time. –

Odpowiedz

14

Jak zauważono w komentarzu, można użyć scipy.signal.lfilter. W tym przypadku (zakładając A jest jednowymiarowa numpy tablicy), wszystko czego potrzebujesz to:

B = lfilter([a], [1.0, -b], A) 

Oto kompletny scenariusz:

import numpy as np 
from scipy.signal import lfilter 


np.random.seed(123) 

A = np.random.randn(10) 
a = 2.0 
b = 3.0 

# Compute the recursion using lfilter. 
# [a] and [1, -b] are the coefficients of the numerator and 
# denominator, resp., of the filter's transfer function. 
B = lfilter([a], [1, -b], A) 

print B 

# Compare to a simple loop. 
B2 = np.empty(len(A)) 
for k in range(0, len(B2)): 
    if k == 0: 
     B2[k] = a*A[k] 
    else: 
     B2[k] = a*A[k] + b*B2[k-1] 

print B2 

print "max difference:", np.max(np.abs(B2 - B)) 

Wyjście skryptu jest:

[ -2.17126121e+00 -4.51909273e+00 -1.29913212e+01 -4.19865530e+01 
    -1.27116859e+02 -3.78047705e+02 -1.13899647e+03 -3.41784725e+03 
    -1.02510099e+04 -3.07547631e+04] 
[ -2.17126121e+00 -4.51909273e+00 -1.29913212e+01 -4.19865530e+01 
    -1.27116859e+02 -3.78047705e+02 -1.13899647e+03 -3.41784725e+03 
    -1.02510099e+04 -3.07547631e+04] 
max difference: 0.0 

Innym przykładem, w ipython stosując DataFrame pandas zamiast numpy tablicy:

Jeśli masz

In [12]: df = pd.DataFrame([1, 7, 9, 5], columns=['A']) 

In [13]: df 
Out[13]: 
    A 
0 1 
1 7 
2 9 
3 5 

i chcesz utworzyć nową kolumnę, B, tak że B[k] = A[k] + 2*B[k-1] (z B[k] == 0 k < 0), można napisać

In [14]: df['B'] = lfilter([1], [1, -2], df['A'].astype(float)) 

In [15]: df 
Out[15]: 
    A B 
0 1 1 
1 7 9 
2 9 27 
3 5 59 
+0

Fantastyczna odpowiedź. Dzięki Warren. Brałem udział w zajęciach z sygnałów i systemów (książka Oppenheima), a to wydaje się być słuszne. Przyjrzę się dokładnie tej odpowiedzi, ponieważ wygląda na to, że jest to właściwy sposób rozwiązania problemu. Zakładam, że to podejście może obsłużyć tylko liniowe rekursje, prawda? – Josh

+1

Tak, tylko liniowy. ("L" w "lfilter" oznacza "liniowy".) –