2010-10-20 17 views
9

I haben zwei verschiedene Zeitreihe mit teilweise überlappenden Zeitstempel:Wie Aggregate Zeitreihen in Python?

import scikits.timeseries as ts 
from datetime import datetime 
a = ts.time_series([1,2,3], dates=[datetime(2010,10,20), datetime(2010,10,21), datetime(2010,10,23)], freq='D') 
b = ts.time_series([4,5,6], dates=[datetime(2010,10,20), datetime(2010,10,22), datetime(2010,10,23)], freq='D') 

die Daten Folgende stellt:

Day: 20. 21. 22. 23. 
    a: 1 2 - 3 
    b: 4 - 5 6 

Ich möchte einen gewichteten Durchschnitt an jedem Tag mit Koeffizienten a (0,3) und b berechnen, (0,7), während ignorieren fehlende Werte:

Day 20.: (0.3 * 1 + 0.7 * 4)/(0.3 + 0.7) = 3.1/1. = 3.1 
Day 21.: (0.3 * 2   )/(0.3  ) = 0.6/0.3 = 2 
Day 22.: (   0.7 * 5)/(  0.7) = 3.5/0.7 = 5 
Day 23.: (0.3 * 3 + 0.7 * 6)/(0.3 + 0.7) = 3.1/1. = 5.1 

wenn ich versuche, zuerst diese Zeitreihen auszurichten:

a1, b1 = ts.aligned(a, b) 

Ich werde richtig maskiert Zeitreihe:

timeseries([1 2 -- 3], 
    dates = [20-Oct-2010 ... 23-Oct-2010], 
    freq = D) 

timeseries([4 -- 5 6], 
    dates = [20-Oct-2010 ... 23-Oct-2010], 
    freq = D) 

aber wenn ich a1 * 0.3 + b1 * 0.7 tun, es ignoriert Werte, die nur in einer Zeitreihe vorhanden sind:

timeseries([3.1 -- -- 5.1], 
    dates = [20-Oct-2010 ... 23-Oct-2010], 
    freq = D) 

Was soll ich tun, um erhalten die erwarteten?

timeseries([3.1 2. 5. 5.1], 
    dates = [20-Oct-2010 ... 23-Oct-2010], 
    freq = D) 

EDIT: Die Antwort sollte auch auf mehr als zwei Anfangszeitreihen mit unterschiedlichen Gewichten und unterschiedlich fehlenden Werte gelten.

Wenn wir also vier Zeitreihen mit Gewichten T1 haben (0,1), T2 (0.2), T3 (0,3) und T4 (0,4), deren Gewichte bei einer gegebenen Zeitstempel sind:

  | T1 | T2 | T3 | T4 | 
weight  | 0.1 | 0.2 | 0.3 | 0.4 | 
------------------------------------- 
all present | 10% | 20% | 30% | 40% | 
T1 missing |  | 22% | 33% | 45% | 
T1,T2 miss. |  |  | 43% | 57% | 
T4 missing | 17% | 33% | 50% |  | 
etc. 
+0

"mehr als zwei Anfangszeitreihen"? Du meinst T1, T2, T3? Ist das nicht einfach ((T1 * agg * T2) * agg * T3)? In diesem Fall kann eine beliebige Anzahl von Zeitreihen aggregiert werden, indem einfach die Lösung als Reduktion angewendet wird. Wenn nicht, warum nicht? –

+0

@ S.Lott - nicht wirklich. Wie würden Sie Gewichte mit T1 (0.2), T2 (0.2) und T3 (0.6) handhaben? Wenn zu einem gegebenen Zeitstempel T1 fehlt, dann repräsentiert der 0.6 von T3 tatsächlich 75% (T2 hat dann 25%) und nicht 60% der gesamten Gruppe. In Ihrer ((T1 agg T2) agg T3) Logik würde dies nicht funktionieren. – eumiro

+0

@eumiro: Bitte ** aktualisieren Sie Ihre Frage mit dieser Anforderung. –

Antwort

3

Ich habe versucht und gefunden:

aWgt = 0.3 
bWgt = 0.7 

print (np.where(a1.mask, 0., a1.data * aWgt) + 
     np.where(b1.mask, 0., b1.data * bWgt))/(np.where(a1.mask, 0., aWgt) + 
               np.where(b1.mask, 0., bWgt)) 

# array([ 3.1, 2. , 5. , 5.1]) 

Dies gilt für die bearbeitete Frage mit mehr als einer anfänglichen Zeitreihe. Aber hoffentlich wird jemand besser finden.

EDIT: Und das ist meine Funktion:

def weightedAvg(weightedTimeseries): 
    sumA = np.sum((np.where(ts.mask, 0., ts.data * weight) for ts, weight in weightedTimeseries), axis=0) 
    sumB = np.sum((np.where(ts.mask, 0., weight) for ts, weight in weightedTimeseries), axis=0) 
    return np.divide(sumA, sumB) 

weightedAvg(((a1, 0.3), (bb, 0.7))) 
# array([ 3.1, 2. , 5. , 5.1]) 

Arbeiten für eine beliebige Anzahl von Zeitreihen ;-)

+0

Ich denke, Ihre 'WeightedAvg' ist besser als die, die ich vorgeschlagen habe, weil es einfacher ist und weniger Speicherplatz benötigt. Sehr schön! – unutbu