Pandas datetime按最近小时取整不一致:原因及统一取整方法
Pandas datetime按小时取整的不一致行为与统一取整方案
问题现象
用Pandas的dt.round('H')对datetime类型数据按最近小时取整时,半小时节点的取整逻辑存在差异:奇数小时的半小时(如5:30)会向上取整到下一小时,偶数小时的半小时(如6:30)则向下取整到当前小时,示例代码及输出如下:
df['nearest_hour']=df['datetime'].dt.round('H') df
| datetime | nearest_hour | |
|---|---|---|
| 141470 | 2019-10-26 04:45:00+00:00 | 2019-10-26 05:00:00+00:00 |
| 294282 | 2019-10-26 05:00:00+00:00 | 2019-10-26 05:00:00+00:00 |
| 178460 | 2019-10-26 05:15:00+00:00 | 2019-10-26 05:00:00+00:00 |
| 92696 | 2019-10-26 05:30:00+00:00 | 2019-10-26 06:00:00+00:00 |
| 227946 | 2019-10-26 05:45:00+00:00 | 2019-10-26 06:00:00+00:00 |
| 216924 | 2019-10-26 06:00:00+00:00 | 2019-10-26 06:00:00+00:00 |
| 167823 | 2019-10-26 06:15:00+00:00 | 2019-10-26 06:00:00+00:00 |
| 240039 | 2019-10-26 06:30:00+00:00 | 2019-10-26 06:00:00+00:00 |
原因分析
这种差异来自Pandasround方法采用的银行家舍入法(四舍六入五成双):当时间处于取整区间的中间点(即半小时)时,会自动取到小时数为偶数的整点。比如:
- 5:30的前后小时是5(奇数)和6(偶数),所以向上取整到6点;
- 6:30的前后小时是6(偶数)和7(奇数),所以向下取整到6点。
统一向上取整的实现方法
要让所有半小时及以后的时间都向上取整,可以用以下两种方案:
方法1:加30分钟后向下取整
给原时间加上30分钟,再用floor('H')向下取整,这样所有>=xx:30的时间都会被推到下一小时:
df['ceil_hour'] = (df['datetime'] + pd.Timedelta(minutes=30)).dt.floor('H')
方法2:结合条件判断使用ceil/floor
直接对分钟数>=30的时间用ceil('H')向上取整,其余时间用floor('H')向下取整:
df['ceil_hour'] = df['datetime'].apply( lambda x: x.ceil('H') if x.minute >= 30 else x.floor('H') )
两种方法都能实现统一规则:5:30取整为6点,6:30取整为7点,所有超过半小时的时间都向上对齐到下一小时。
内容的提问来源于stack exchange,提问作者Forrest Abouelnasr
相关产品推荐
相关产品推荐

