Grupo de pandas por hora con hora de inicio especificada.

– Editar me di cuenta de que había ingresado los tiempos no como lo había previsto. Convirtí los tiempos posteriores a las 12 p. M. A la convención de 24 horas. Sin embargo, la respuesta de Unutbu aún debe ser clara.

– 2ª Edición. Cambié los datos para hacer un mejor ejemplo.

A continuación se muestra una serie de tiempo indexada por fecha. Quiero hacer una agregación a partir de un start_datetime y continuar su agregación según el timedelta a continuación (9.5 horas = 34200 segundos).

def main(): # start_datetime = datetime.datetime(2013, 1, 1, 8) # end_datetime = datetime.datetime(2013, 1, 1, 5, 30) s = pd.Series( np.arange(2, 10), pd.to_datetime([ '20130101 7:34:04', '20130101 8:34:08', '20130101 10:34:08', '20130101 12:34:15', '20130101 13:34:28', '20130101 12:34:54', '20130101 14:34:55', '20130101 17:29:12'])) print(s) bar_size = datetime.timedelta(seconds=60*60*9.5) time_group = pd.Grouper( freq=pd.Timedelta(bar_size), closed='left', label='right') foobar = s.groupby(time_group).agg(np.sum) print(foobar) if __name__ == "__main__": main() 

Ejecutar el código anterior dará como resultado lo siguiente:

 2013-01-01 09:30:00 5 2013-01-01 19:00:00 39 Freq: 570T, dtype: int64 

Los internos de los pandas deciden comenzar a agruparse desde la medianoche en lugar de las 8:00 am. No puedo encontrar una manera de forzar que el dataframe comience a agruparse a las 8:00 am. ¿Alguien tiene una solución usando las funciones de pandas?

Use base=480 para cambiar el punto de inicio en 480 minutos (8 horas). Las unidades están en minutos porque la frecuencia del mero es 570T (T, aquí, denota minutos):

 import datetime import pandas as pd def main(): start_datetime = datetime.datetime(2013, 1, 1, 8) s = pd.Series( range(8), pd.to_datetime([ '20130101 8:34:04', '20130101 10:34:08', '20130101 10:34:08', '20130101 12:34:15', '20130101 1:34:28', '20130101 3:34:54', '20130101 4:34:55', '20130101 5:29:12'])) bar_size = datetime.timedelta(seconds=60*60*9.5) time_group = pd.Grouper(freq=bar_size, closed='left', label='right', base=480) foobar = s.groupby(time_group).agg(sum) print(foobar) if __name__ == "__main__": main() 

rendimientos

 2013-01-01 08:00:00 22 2013-01-01 17:30:00 6 Freq: 570T, dtype: int64 

Internamente, cuando se asigna una frecuencia a TimeGrouper se devuelve un TimeGrouper :

 In [81]: time_group Out[81]:  

Así que los argumentos pasados ​​a pd.Grouper realidad se pasan a pd.TimeGrouper .

 In [82]: pd.TimeGrouper? Init signature: pd.TimeGrouper(self, freq='Min', closed=None, label=None, how='mean', nperiods=None, axis=0, fill_method=None, limit=None, loffset=None, kind=None, convention=None, base=0, **kwargs) 

Los documentos de TimeGrouper no explican el parámetro base , pero tiene el mismo significado que en df.resample :

 In [83]: df.resample? Parameters ---------- base : int, default 0 For frequencies that evenly subdivide 1 day, the "origin" of the aggregated intervals. For example, for '5min' frequency, base could range from 0 through 4. Defaults to 0 

Lo siguiente le permitirá deslizar el inicio a las fechas de ocho horas:

 (s.index + pd.Timedelta('9 hours 30 minutes')).strftime('%Y-%m-%d') # array([u'2013-01-01', u'2013-01-01', u'2013-01-01', u'2013-01-01', # u'2013-01-01', u'2013-01-01', u'2013-01-01', u'2013-01-01'], # dtype=' 

A continuación, puede llamar a:

 s.groupby((s.index + pd.Timedelta('9 hours 30 minutes')).strftime('%Y-%m-%d')).agg(sum) # 2013-01-01 28 

También puede confiar únicamente en los módulos de fecha y hora de pandas para su función, en lugar de importar la datetime separado:

 import pandas as pd def main(): start_datetime = pd.datetime(2013, 1, 1, 8) s = pd.Series( range(8), pd.to_datetime([ '20130101 8:34:04', '20130101 10:34:08', '20130101 10:34:08', '20130101 12:34:15', '20130101 1:34:28', '20130101 3:34:54', '20130101 4:34:55', '20130101 5:29:12'])) time_group = (s.index + pd.Timedelta('9 hours 30 minutes')).strftime('%Y-%m-%d') foobar = s.groupby(time_group).agg(sum) print(foobar)