Панды: Как сгруппировать по столбцу даты и времени, используя только время и отбрасывая дату - PullRequest
1 голос
/ 09 октября 2019

У меня есть датафрейм со столбцом даты и времени. Я хочу сгруппировать только по компоненту времени и агрегировать, например, взяв среднее.

Я знаю, что могу использовать pd.Grouper для группировки по дате и времени, но это не работает только по времени.

Скажем, у нас есть следующий фрейм данных:

import numpy as np
import pandas as pd

drange = pd.date_range('2019-08-01 00:00', '2019-08-12 12:00', freq='1T')
time = drange.time
c0 = np.random.rand(len(drange))
c1 = np.random.rand(len(drange))
df = pd.DataFrame(dict(drange=drange, time=time, c0=c0, c1=c1))
print(df.head())
               drange      time        c0        c1
0 2019-08-01 00:00:00  00:00:00  0.031946  0.159739
1 2019-08-01 00:01:00  00:01:00  0.809171  0.681942
2 2019-08-01 00:02:00  00:02:00  0.036720  0.133443
3 2019-08-01 00:03:00  00:03:00  0.650522  0.409797
4 2019-08-01 00:04:00  00:04:00  0.239262  0.814565

В этом случае следующее выдает ошибку типа:

grouper = pd.Grouper(key='time', freq='5T')
grouped = df.groupby(grouper).mean()

Я мог бы установить key=drangeдля группировки по дате и времени, а затем:

  • Сброс индекса
  • Преобразование нового столбца в число с плавающей точкой
  • Корзина с pd.cut
  • Вернёмся ко времени
  • Наконец, группируем и затем агрегируем

... Но мне интересно, есть ли более чистый способ достижения тех же результатов.

Ответы [ 2 ]

2 голосов
/ 09 октября 2019

Series.dt.time / DatetimeIndex.time возвращает время как datetime.time. Это не очень хорошо, потому что pandas лучше всего работает с timedelta64, и поэтому ваш столбец 'time' приводится к object, теряя все функции даты и времени.

Вы можете вычесть нормированную дату, чтобы получить время как timedelta, чтобы вы могли продолжать использовать datetime инструменты панд. Вы можете floor это сгруппировать.

s = (df.drange - df.drange.dt.normalize()).dt.floor('5T')

df.groupby(s).mean()

                c0        c1
drange                      
00:00:00  0.436971  0.530201
00:05:00  0.441387  0.518831
00:10:00  0.465008  0.478130
...            ...       ...
23:45:00  0.523233  0.515991
23:50:00  0.468695  0.434240
23:55:00  0.569989  0.510291

В качестве альтернативы, если вы не уверены в floor, вы получите идентичный вывод вплоть до имени индекса

df['time'] = (df.drange - df.drange.dt.normalize())  # timedelta64[ns]
df.groupby(pd.Grouper(key='time', freq='5T')).mean()
0 голосов
/ 09 октября 2019

Когда вы используете DataFrame.groupby, вы можете Series аргумент . Более того, если ваша серия - это дата и время, вы можете использовать series.dt для доступа к свойствам даты. В вашем случае df['drange'].dt.hour или df['drange'].dt.time должны это сделать.

# df['drange']=pd.to_datetime(df['drange'])
df.groupby(df['drange'].dt.hour).agg(...)
...