2016-06-16 38 views
5

Ho un DataFrame contenente una serie temporale:Groupby con TimeGrouper 'a ritroso'

rng = pd.date_range('2016-06-01', periods=24*7, freq='H') 
ones = pd.Series([1]*24*7, rng) 
rdf = pd.DataFrame({'a': ones}) 

Ultimo ingresso è 2016-06-07 23:00:00. Ora voglio gruppo questo, dico due giorni, in fondo in questo modo:

rdf.groupby(pd.TimeGrouper('2D')).sum() 

Tuttavia, voglio gruppo a partire dal mio ultimo dati dei punti a ritroso, quindi invece di ottenere questo risultato:

  a 
2016-06-01 48 
2016-06-03 48 
2016-06-05 48 
2016-06-07 24 

preferirei mille volte aspetto che questo:

  a 
2016-06-01 24 
2016-06-03 48 
2016-06-05 48 
2016-06-07 48 

e quando il raggruppamento per '3D':

  a 
2016-06-01 24 
2016-06-04 72 
2016-06-07 72 

risultato previsto quando il raggruppamento per '4D' è:

  a 
2016-06-03 72 
2016-06-07 96 

Io non sono in grado di ottenere questo con ogni combinazione di closed, label ecc mi veniva in mente.

Come posso ottenere questo risultato?

risposta

0

Dal momento che voglio in primo luogo al gruppo di 7 giorni, in arte una settimana, sto usando questo metodo ora di venire a bidoni desiderati:

from pandas.tseries.offsets import Week 

# Let's not make full weeks 
hours = 24*6*4 
rng = pd.date_range('2016-06-01', periods=hours, freq='H') 

# Set week start to whatever the last weekday of the range is 
print("Last day is %s" % rng[-1]) 
freq = Week(weekday=rng[-1].weekday()) 

ones = pd.Series([1]*hours, rng) 
rdf = pd.DataFrame({'a': ones}) 
rdf.groupby(pd.TimeGrouper(freq=freq, closed='right', label='right')).sum() 

Questo mi dà l'output desiderato di

2016-06-25 96 
2016-07-02 168 
2016-07-09 168 
+0

Probabilmente questo può essere fatto anche più genericamente con '' 'DateOffset'''. – TomTom101

0

Dato che la questione ora si concentra sul raggruppamento per settimana, si può semplicemente:

rdf.resample('W-{}'.format(rdf.index[-1].strftime('%a')), closed='right', label='right').sum() 

È possibile utilizzare loffset per farlo funzionare - almeno per la maggior parte dei periodi (utilizzando .resample()):

for i in range(2, 7): 
    print(i) 
    print(rdf.resample('{}D'.format(i), closed='right', loffset='{}D'.format(i)).sum()) 

2 
      a 
2016-06-01 24 
2016-06-03 48 
2016-06-05 48 
2016-06-07 48 
3 
      a 
2016-06-01 24 
2016-06-04 72 
2016-06-07 72 
4 
      a 
2016-06-01 24 
2016-06-05 96 
2016-06-09 48 
5 
       a 
2016-06-01 24 
2016-06-06 120 
2016-06-11 24 
6 
       a 
2016-06-01 24 
2016-06-07 144 

Tuttavia, è anche possibile creare raggruppamenti personalizzati che calcolano i valori corretti senza TimeGrouper in questo modo:

days = rdf.index.to_series().dt.day.unique()[::-1] 
for n in range(2, 7): 
    chunks = [days[i:i + n] for i in range(0, len(days), n)][::-1] 
    grp = pd.Series({k: v for d in [zip(chunk, [idx] * len(chunk)) for idx, chunk in enumerate(chunks)] for k, v in d}) 
    rdf.groupby(rdf.index.to_series().dt.day.map(grp))['a'].sum() 

2 
groups 
0 24 
1 48 
2 48 
3 48 
Name: a, dtype: int64 

3 
groups 
0 24 
1 72 
2 72 
Name: a, dtype: int64 

4 
groups 
0 72 
1 96 
Name: a, dtype: int64 

5 
groups 
0  48 
1 120 
Name: a, dtype: int64 

6 
groups 
0  24 
1 144 
Name: a, dtype: int64 
+0

Grazie! Dato che l'ultimo bin è il mio più importante, avrei bisogno che fosse molto affidabile. Strano, sembra che non ci sia una soluzione facile per questo. – TomTom101

+0

Vedere aggiornato per una soluzione per calcolare i valori di gruppo in modo affidabile ma senza utilizzare TimeGrouper. – Stefan

+0

Merita di essere accettato;) Grazie! – TomTom101