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