2010-10-20 22 views
9

Ho due timeseries differenti con timestamp parzialmente sovrapposte:Come aggregare le serie temporali 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') 

che rappresenta seguenti dati:

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

desidero calcolare una media ponderata ogni giorno con coefficienti a (0,3) e b (0.7), ignorando i valori mancanti:

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 

quando sono cercare di allineare queste timeseries:

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

timeseries vengo correttamente mascherato:

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) 

ma quando lo faccio a1 * 0.3 + b1 * 0.7, ignora i valori, che sono presenti in una sola timeseries:

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

Cosa devo fare per ricevere l'atteso?

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

EDIT: La risposta dovrebbe essere applicabile anche a più di due timeseries iniziali con diversi pesi e valori diversamente mancanti.

Quindi se abbiamo quattro timeseries con pesi T1 (0,1), T2 (0,2), T3 (0,3) e T4 (0,4), i pesi in un dato timestamp saranno:

  | 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

"più di due timeseries iniziali"? Intendi T1, T2, T3? Non è solo ((T1 * agg * T2) * agg * T3)? In tal caso, qualsiasi numero di serie temporali può essere aggregato semplicemente applicando la soluzione come una riduzione. Se no, perché no? –

+0

@ S.Lott - non proprio. Come gestireste i pesi con T1 (0,2), T2 (0,2) e T3 (0,6)? Se a un dato timestamp T1 manca, allora lo 0,6 di T3 rappresenta effettivamente il 75% (T2 ha quindi il 25%) e non il 60% di tutto il gruppo. Nella tua logica ((T1 agg T2) agg T3) ciò non funzionerebbe. – eumiro

+0

@eumiro: per favore ** aggiorna ** la tua domanda con questo requisito. –

risposta

3

Ho provato e ho trovato questo:

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

questo è applicabile alla domanda modificato con più di un timeseries iniziali. Ma speriamo che qualcuno trovi di meglio.

EDIT: E questa è la mia funzione:

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

funziona per qualsiasi numero di TimeSeries ;-)

+0

Penso che il tuo 'weightedAvg' sia migliore di quello che ho suggerito perché è più semplice e richiede meno memoria. Molto bella! – unutbu

Problemi correlati