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

Posted

技术标签:

【中文标题】在熊猫`DataFrame`中将`TimeStamp`列截断为小时精度【英文标题】:Truncate `TimeStamp` column to hour precision in pandas `DataFrame` 【发布时间】:2015-04-30 15:40:52 【问题描述】:

我有一个名为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 的魔法可以做到这一点?

【问题讨论】:

所以你想要相同的值但没有正确的秒数 @EdChum 没有分钟或秒...我只对小时精度感兴趣 【参考方案1】:

在 pandas 0.18.0 及更高版本中,有 datetime floorceilround 方法将时间戳舍入到给定的固定精度/频率。要向下舍入到小时精度,您可以使用:

>>> 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',等等:

跟上一年:'&lt;M8[Y]' 保持最新月份:'&lt;M8[M]' 保持最新状态:'&lt;M8[D]' 保持最新状态:'&lt;M8[m]' 保持第二:'&lt;M8[s]'

【讨论】:

很好的答案。 Waaay 比 datetime.replace 快,这是 SO 上提到的最常见的解决方案。 我的 dt 系列有一个我想去掉的毫秒项 (+00:00)。您答案的第一部分似乎是四舍五入(将术语归零)但没有截断。您对 astype 的回答的第二部分起到了作用。谢谢! 对于分钟频率所有三个:'m'、'M' 和 ' 超级有帮助!午夜时间 (00:00:00) 没有出现在 df.head() 中,所以我认为在应用 df['hour'].dt.floor('h') 后出现了问题。但并没有错,检查df['hour'].loc[0] 显示正确的小时截断。【参考方案2】:

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

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

【讨论】:

【参考方案3】:

或者:

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

【讨论】:

以上是关于在熊猫`DataFrame`中将`TimeStamp`列截断为小时精度的主要内容,如果未能解决你的问题,请参考以下文章

在熊猫中将毫秒设置为小时,最长 24 小时

在熊猫中将多列合并为一列

你如何在熊猫中将多行连接成一行?

在循环中将字典附加到熊猫数据框

如何在熊猫数据框中将单元格设置为 NaN

在熊猫中将数据类型从对象更改为字符串