在 pandas `DataFrame` 中将 `TimeStamp` 列截断为小时精度

Truncate `TimeStamp` column to hour precision in pandas `DataFrame`

我有一个名为 dfpandas.DataFrame,它有一个自动生成的索引,其中有一列 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 魔法可以做到这一点?

在 pandas 0.18.0 及更高版本中,有 datetime floor, ceil and round 方法将时间戳舍入到给定的固定值 precision/frequency。要向下舍入到小时精度,您可以使用:

>>> 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]'

我过去用来实现这个目标的方法如下(与您已经在做的非常相似,但我想我还是会把它扔掉):

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

或者:

df.dt.index.to_period("h") # for the period
df.dt.index.to_period("h").to_timestamp() # for the timestamp truncated

将是实现这一目标的最不明确(更 pythonic?)的方式。 使用 floor/round/ceil 进行较粗略的循环(月、年...),您会收到一条错误消息

ValueError: <YearEnd: month=12> is a non-fixed frequency

在此处查看讨论:https://github.com/pandas-dev/pandas/issues/15303