2012-06-17 15 views
33

Tengo algunos datos de los archivos de registro y me gustaría entradas de grupo por un minuto:¿Cómo se agrupa DataFrame por un período de tiempo?

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 

he probado todas estas opciones:

  1. df.resample('Min') es demasiado alto nivel y quiere agregar
  2. df.groupby(date_range(datetime(2012,1,1,12, 30), freq='Min', periods=4)) falla con excepción.
  3. df.groupby(TimeGrouper(freq='Min')) funciona bien y devuelve un objeto DataFrameGroupBy para su posterior procesamiento, por ejemplo .:

    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 
    

Sin embargo, la clase TimeGrouper no está documentada.

¿Cuál es la manera correcta de agrupar por un período de tiempo? ¿Cómo puedo agrupar los datos por un minuto Y por la columna Fuente, p. groupby([TimeGrouper(freq='Min'), df.Source])?

Respuesta

39

Puede agrupar en cualquier conjunto/serie de la misma longitud que su DataFrame --- incluso un factor calculado que no es realmente una columna del DataFrame. Así agrupar por minuto que puede hacer:

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

Si desea agrupar por minuto y algo más, sólo hay que mezclar lo anterior con la columna que desea utilizar:

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

Personalmente lo encuentro Es útil simplemente agregar columnas al DataFrame para almacenar algunas de estas cosas calculadas (por ejemplo, una columna "Minuto") si quiero agruparlas a menudo, ya que hace que el código de agrupación sea menos detallado.

O usted podría intentar algo como esto:

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

Gracias. Obtuve el resultado que estaba buscando con esta afirmación: 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

¿cómo puedo extenderlo a 30 minutos? – igaurav

+7

Este pd.TimeGrouper se puede usar para agrupar por múltiplos de unidades de tiempo 'df.groupby (pd.TimeGrouper (freq = '30Min'))' – salomonvh

Cuestiones relacionadas