在 pandas `DataFrame` 中将 `TimeStamp` 列截断为小时精度
Truncate `TimeStamp` column to hour precision in pandas `DataFrame`
我有一个名为 df
的 pandas.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
我有一个名为 df
的 pandas.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