Pandas eval执行日期算术时报错:无法将Timedelta转为Timestamp
问题解答
1. eval()日期算术报错的原因
这是pandas 1.5.x版本eval()的固有限制,不是操作错误。
- 直接执行
df.date + pd.Timedelta('1D')时,pandas会调用Series与Timedelta的原生加法逻辑,自动适配Timestamp和Timedelta的运算规则,返回正确的Timestamp序列。 - 但
eval()依赖的numexpr解析器在1.5.2版本中对pandas时间类型的支持不完善,它无法正确识别Timedelta与Timestamp列的运算逻辑,错误地尝试把Timedelta转换成Timestamp,最终抛出类型转换异常。
2. local_dict传pd无效的问题
这也是pandas 1.5.x版本eval()的设计细节:
local_dict参数主要用于传递自定义变量,而非模块对象。表达式解析逻辑不会从local_dict中解析模块(比如pd),所以即便传入{'pd': pd},写pd.Timedelta还是会报错。@前缀是eval()专门用来引用当前作用域变量的语法,它会直接读取全局/局部环境中的pd模块,所以@pd.Timedelta能被识别,但还是绕不开第一个问题里的运算类型限制。
可行解决办法
针对你的场景,有几种替代方案:
- 方案一:用
assign配合lambda(推荐)
完全避开eval()的限制,直接用原生pandas操作:df.assign(date_plus_1d=lambda x: x.date + pd.Timedelta('1D')) - 方案二:提前定义Timedelta变量再传入
eval()
如果一定要用eval(),先把Timedelta实例化为变量,再用@传入:
这种方式既绕开了模块属性解析的问题,又能让delta = pd.Timedelta('1D') df.eval("date + @delta")eval()正确识别Series与Timedelta对象的加法逻辑。 - 方案三:升级pandas到2.0+
pandas 2.0及以上版本已经优化了eval()对时间类型的支持,升级后直接运行df.eval("date + @pd.Timedelta('1D')")就能正常工作。
内容的提问来源于stack exchange,提问作者gherka
相关产品推荐
相关产品推荐

