使用pd.round处理时间戳舍入出现异常结果,求技术解答
问题:Pandas时间戳按分钟舍入结果不符合预期
我的测试数据子集:
print(test) created_at 29100988 2020-06-01 00:03:49+00:00 29100989 2020-06-01 00:03:42+00:00 29100990 2020-06-01 00:03:41+00:00 29100991 2020-06-01 00:03:37+00:00 29100992 2020-06-01 00:03:36+00:00 29100993 2020-06-01 00:03:36+00:00 29100994 2020-06-01 00:03:31+00:00 29100995 2020-06-01 00:03:17+00:00 29100996 2020-06-01 00:03:17+00:00 29100997 2020-06-01 00:03:12+00:00
我用以下代码将created_at列按1分钟舍入:
test['created_at_Min'] = pd.to_datetime(test['created_at']).dt.round("1Min")
得到的结果:
created_at created_at_Min 29100988 2020-06-01 00:03:49+00:00 2020-06-01 00:04:00+00:00 29100989 2020-06-01 00:03:42+00:00 2020-06-01 00:04:00+00:00 29100990 2020-06-01 00:03:41+00:00 2020-06-01 00:04:00+00:00 29100991 2020-06-01 00:03:37+00:00 2020-06-01 00:04:00+00:00 29100992 2020-06-01 00:03:36+00:00 2020-06-01 00:04:00+00:00 29100993 2020-06-01 00:03:36+00:00 2020-06-01 00:04:00+00:00 29100994 2020-06-01 00:03:31+00:00 2020-06-01 00:04:00+00:00 29100995 2020-06-01 00:03:17+00:00 2020-06-01 00:03:00+00:00 29100996 2020-06-01 00:03:17+00:00 2020-06-01 00:03:00+00:00 29100997 2020-06-01 00:03:12+00:00 2020-06-01 00:03:00+00:00
可以看到00:03:17+00:00被舍入到00:03:00+00:00,但00:03:31+00:00却被舍入到00:04:00+00:00,小时维度也存在同样问题,求解决办法。
解答
这是因为Pandas的dt.round()默认使用银行家舍入法(四舍六入五成双),而非常规的四舍五入规则:
- 尾数小于半单位(比如1分钟的半单位是30秒)时舍去
- 尾数大于半单位时进1
- 尾数等于半单位时,若前一位是偶数则舍去,奇数则进1
你的例子中,00:03:31的秒数31超过半分钟(30秒),所以按规则进1到00:04:00;00:03:17秒数17小于30秒,舍去到00:03:00,这符合银行家舍入逻辑。小时维度的异常,也是因为同样的奇偶判断规则。
解决办法
实现常规四舍五入(秒数≥30进1,<30舍去):
通过给时间戳加上30秒后再向下取整,模拟常规四舍五入效果:test['created_at_Min'] = (pd.to_datetime(test['created_at']) + pd.Timedelta(30, unit='s')).dt.floor("1Min")直接截断到当前分钟(忽略所有秒数):
如果不需要舍入,只保留当前分钟的整数部分,直接使用dt.floor():test['created_at_Min'] = pd.to_datetime(test['created_at']).dt.floor("1Min")
内容的提问来源于stack exchange,提问作者Dalogh
相关产品推荐
相关产品推荐

