使用numpy.digitize处理datetime类型时间序列分箱报错如何解决
报错原因
np.digitize 不支持存储Python原生datetime对象的Object类型数组,其内部做单调性校验、数值比较时需要将数组转换为数值类型,因此触发了Object转float64的类型错误。
可行解决方案
有两种常用的处理方式,均可实现你的分箱需求:
方案1:转换为numpy原生datetime64类型(推荐)
该方案无需手动计算时间戳,直接利用numpy对日期类型的原生支持,代码修改量最小:
from datetime import datetime, timedelta import numpy as np sdate = datetime.strptime('2017-01-01 18:00:00', "%Y-%m-%d %H:%M:%S") edate = datetime.strptime('2017-01-01 18:00:30', "%Y-%m-%d %H:%M:%S") # 创建数组时指定dtype为datetime64,[s]代表精度为秒,可根据实际需求调整为[ms]等其他精度 t_data = np.array([sdate + timedelta(seconds=x) for x in range((edate - sdate).seconds)], dtype='datetime64[s]') t_edges = np.array([ datetime.strptime('2017-01-01 18:00:00', "%Y-%m-%d %H:%M:%S"), datetime.strptime('2017-01-01 18:00:10',"%Y-%m-%d %H:%M:%S"), datetime.strptime('2017-01-01 18:00:20', "%Y-%m-%d %H:%M:%S") ], dtype='datetime64[s]') t_bin = np.digitize(t_data, t_edges)
运行后得到的t_bin就符合你预期的输出:前10个值为1,中间10个值为2,最后10个值为3。
方案2:转换为Unix时间戳
如果你需要保留原生datetime对象的其他属性,也可以先将所有时间转换为数值型的时间戳再分箱:
# 沿用你原有代码生成的t_data、t_edges(Object类型数组) t_data_ts = np.array([dt.timestamp() for dt in t_data]) t_edges_ts = np.array([dt.timestamp() for dt in t_edges]) t_bin = np.digitize(t_data_ts, t_edges_ts)
注意事项
- 两种方案都需要保证箱边数组单调递增,这是
np.digitize本身的通用要求,和时间类型无关 - 使用
datetime64时需要匹配时间精度,避免精度截断导致分箱错误
内容的提问来源于stack exchange,提问作者FluidFox
相关产品推荐
相关产品推荐

