自定义datetime子类插入pandas DataFrame后丢失附加功能如何解决?
问题根因
pandas内部对datetime子类的实例有默认的自动转换逻辑,会统一转成Timestamp类型存储在datetime64[ns]类型的列中,这个是pandas为了优化时间序列处理性能做的默认处理,所以你自定义的CPyTime类的附加属性和方法会在转换后丢失。
可行解决方案
方案1:强制列类型为object(快速实现,适合小范围使用)
直接在赋值时强制将列的类型指定为object,就能阻止pandas的自动类型转换,保留原生的CPyTime实例:
import pandas as pd pdf = pd.DataFrame(data=[[2021, 1], [2021, 2], [2021, 3], [2021, 4]], columns=["Year", "Month"]) # 赋值后调用astype强制转为object类型 pdf["OwnDate"] = pdf.apply(lambda row: CPyTime(row["Year"], row["Month"]), axis=1).astype(object)
测试验证:
print(type(pdf["OwnDate"][0])) # 输出 <class '__main__.CPyTime'> print(pdf["OwnDate"][0].year_plus_month) # 正常输出 2022
该方案的缺点是无法使用pandas内置的时间序列相关方法(比如dt访问器、重采样等),如果需要用到这些能力,可以先手动将CPyTime实例转成Timestamp使用。
方案2:实现pandas扩展类型(生产级方案,性能更优)
如果需要兼顾自定义功能和pandas的原生时间序列能力,可以按照pandas官方规范实现自定义扩展类型:继承pandas.api.extensions.ExtensionDtype和pandas.api.extensions.ExtensionArray,将CPyTime的逻辑封装到扩展类型中,这种方式下pandas可以原生支持你的自定义时间类型,不会做强制转换,同时也能兼容大部分pandas内置的时间操作接口。
方案3:用组合替代继承(规避隐式转换问题)
放弃继承datetime.datetime,改为在自定义类中封装一个datetime实例作为内部属性,对外暴露需要的方法和属性,这种方式可以从根源上避免pandas识别为datetime类型而做自动转换,实现起来比扩展类型简单,也更灵活。
内容的提问来源于stack exchange,提问作者fastest
相关产品推荐
相关产品推荐

