2014-10-08 8 views
11

Ich habe eine Zeitreihe A mit mehreren Werten. Ich brauche eine Reihe B zu erhalten, die algebraisch wie folgt definiert ist:Rekursive Definitionen in Pandas

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

wo wir B[0] = 0 annehmen kann, und a und b sind reelle Zahlen.

Gibt es eine Möglichkeit, diese Art der rekursiven Berechnung in Pandas zu machen? Oder habe ich keine andere Wahl, als Python wie in this answer vorgeschlagen zu wiederholen?

Als Beispiel für Eingabe:

> 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

hier die offene Frage schreiben um es zu cythonisieren: https://github.com/pydata/pandas/issues/4567, aber einige Links sind auch ihre – Jeff

+2

Sie können 'scipy.signal.lfilter' verwenden. Ein Beispiel finden Sie unter http://stackoverflow.com/questions/21336794/python-recursive-vectorization-with-timeseries. –

Antwort

14

Wie ich in einem Kommentar erwähnt, können Sie scipy.signal.lfilter verwenden. In diesem Fall (A Annahme, daß ein eindimensionales numpy Array), alles, was Sie brauchen, ist:

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

Hier ist ein komplettes Skript:

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)) 

Die Ausgabe des Skripts ist:

[ -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 

Ein anderes Beispiel in IPython, das einen pandas DataFrame anstelle eines numpy Arrays verwendet:

Wenn Sie

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 

und Sie eine neue Spalte zu erstellen, B, so dass B[k] = A[k] + 2*B[k-1] (mit B[k] == 0 für k < 0), können Sie

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

Fantastische Antwort. Danke Warren. Ich nahm Unterricht in Signalen und Systemen (Oppenheims Buch), und das fühlt sich so richtig an. Ich werde diese Antwort sorgfältig prüfen, da es aussieht, als wäre es der richtige Weg, das Problem zu lösen. Ich gehe davon aus, dass dieser Ansatz nur lineare Rekursionen verarbeiten kann, richtig? – Josh

+1

Ja, nur linear. (Das 'l' in' lfilter' steht für 'linear'.) –