Усечение столбца `TimeStamp` до точности часов в pandas` DataFrame`

У меня есть pandas.DataFrame, называемый df, который имеет автоматически сгенерированный индекс со столбцом dt:

df['dt'].dtype, df['dt'][0]
# (dtype('<M8[ns]'), Timestamp('2014-10-01 10:02:45'))

То, что я хотел бы сделать, - создать новый столбец с укороченной точностью часов. В настоящее время я использую:

df['dt2'] = df['dt'].apply(lambda L: datetime(L.year, L.month, L.day, L.hour))

Это работает, так что отлично. Тем не менее, я немного понимаю, используя pandas.tseries.offsets или создавая DatetimeIndex или аналогичный.

Итак, если возможно, есть ли какое-то волшебство pandas для этого?

Ответы

Ответ 1

В pandas 0.18.0 и более поздних версиях есть datetime floor, ceil и round для округления временных меток с заданной фиксированной точностью/частотой. Чтобы округлить до часовой точки, вы можете использовать:

>>> df['dt2'] = df['dt'].dt.floor('h')
>>> df
                      dt                     dt2
0    2014-10-01 10:02:45     2014-10-01 10:00:00
1    2014-10-01 13:08:17     2014-10-01 13:00:00
2    2014-10-01 17:39:24     2014-10-01 17:00:00

Здесь другая альтернатива усечению временных меток. В отличие от floor, он поддерживает усечение до такой точности, как год или месяц.

Вы можете временно отрегулировать блок точности базового типа NumPy datetime64, изменив его с [ns] на [h]:

df['dt'].values.astype('<M8[h]')

Это сокращает все до точности часов. Например:

>>> df
                       dt
0     2014-10-01 10:02:45
1     2014-10-01 13:08:17
2     2014-10-01 17:39:24

>>> df['dt2'] = df['dt'].values.astype('<M8[h]')
>>> df
                      dt                     dt2
0    2014-10-01 10:02:45     2014-10-01 10:00:00
1    2014-10-01 13:08:17     2014-10-01 13:00:00
2    2014-10-01 17:39:24     2014-10-01 17:00:00

>>> df.dtypes
dt     datetime64[ns]
dt2    datetime64[ns]

Тот же метод должен работать для любого другого устройства: месяцев 'M', минут 'M' и т.д.:

  • Держать до года: '<M8[Y]'
  • Следите за месяцем: '<M8[M]'
  • Следите за обновлениями: '<M8[D]'
  • Сохраняйте до минуты: '<M8[M]'
  • Следите за порядком: '<M8[s]'

Ответ 2

Метод, который я использовал в прошлом для достижения этой цели, был следующим (очень похожим на то, что вы уже делаете, но думал, что я его вообще выброшу):

df['dt2'] = df['dt'].apply(lambda x: x.replace(minute=0, second=0))