2012-06-17 14 views
33

Ho alcuni dati da file di log e vorrei voci di gruppo per un minuto:Come raggruppare DataFrame per un periodo di tempo?

def gen(date, count=10): 
    while count > 0: 
     yield date, "event{}".format(randint(1,9)), "source{}".format(randint(1,3)) 
     count -= 1 
     date += DateOffset(seconds=randint(40)) 

df = DataFrame.from_records(list(gen(datetime(2012,1,1,12, 30))), index='Time', columns=['Time', 'Event', 'Source']) 

df:

Event Source 
2012-01-01 12:30:00  event3 source1 
2012-01-01 12:30:12  event2 source2 
2012-01-01 12:30:12  event2 source2 
2012-01-01 12:30:29  event6 source1 
2012-01-01 12:30:38  event1 source1 
2012-01-01 12:31:05  event4 source2 
2012-01-01 12:31:38  event4 source1 
2012-01-01 12:31:44  event5 source1 
2012-01-01 12:31:48  event5 source2 
2012-01-01 12:32:23  event6 source1 

ho provato queste opzioni:

  1. df.resample('Min') è troppo alto livello e vuole aggregare.
  2. df.groupby(date_range(datetime(2012,1,1,12, 30), freq='Min', periods=4)) non riesce con eccezione.
  3. df.groupby(TimeGrouper(freq='Min')) funziona bene e restituisce un oggetto DataFrameGroupBy per un'ulteriore elaborazione, ad es .:

    grouped = df.groupby(TimeGrouper(freq='Min')) 
    grouped.Source.value_counts() 
    2012-01-01 12:30:00 source1 1 
    2012-01-01 12:31:00 source2 2 
            source1 2 
    2012-01-01 12:32:00 source2 2 
            source1 2 
    2012-01-01 12:33:00 source1 1 
    

Tuttavia, classe TimeGrouper non è documentato.

Qual è il modo corretto di raggruppare per un periodo di tempo? Come posso raggruppare i dati di un minuto E per la colonna Sorgente, ad es. groupby([TimeGrouper(freq='Min'), df.Source])?

risposta

39

È possibile raggruppare qualsiasi array/serie della stessa lunghezza del DataFrame --- anche un fattore calcolato che non è in realtà una colonna di DataFrame. Quindi, per gruppo per minuto si può fare:

df.groupby(df.index.map(lambda t: t.minute)) 

Se si desidera raggruppare per minuto e qualcos'altro, giusto mix di cui sopra con la colonna che si desidera utilizzare:

df.groupby([df.index.map(lambda t: t.minute), 'Source']) 

Personalmente trovo utile per aggiungere semplicemente colonne al DataFrame per memorizzare alcune di queste cose calcolate (ad es. una colonna "Minute") se voglio raggrupparle spesso, poiché rende il codice di raggruppamento meno dettagliato.

Oppure si potrebbe provare qualcosa di simile:

df.groupby([df['Source'],pd.TimeGrouper(freq='Min')]) 
+3

Grazie. Ho ottenuto il risultato che stavo cercando con questa affermazione: df.groupby ([df.index.map (lambda t: datetime (t.year, t.month, t.day, t.hour, t.minute)), df.Source, df.Event]). size(). unstack (level = 2) – serguei

+2

come posso estenderlo a 30 minuti? – igaurav

+7

Questo pd.TimeGrouper può essere utilizzato per raggruppare per multipli di unità di tempo 'df.groupby (pd.TimeGrouper (freq = '30Min'))' – salomonvh

Problemi correlati