You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移至Python3后pandas eval结合where函数报错排查

问题解答

报错原因

这个错误不是Python3迁移直接导致,而是伴随Python3升级时pandas版本更新引发的行为变化。原代码中:

  • val_per函数接收的ASSET和PRODUCT是numpy数组(由MAIN_df.eval传递列数据时生成)
  • pd.eval在处理这些数组参数时,会尝试将它们存入内部的命名空间字典,而numpy数组属于不可哈希类型,无法作为字典的键,因此抛出TypeError。

解决方案

无需在where中嵌套pd.eval,直接对numpy数组进行向量化布尔运算即可,既解决报错又提升效率:

修改后的代码

import pandas as pd, numpy as np
from numpy import where, nan

d = {'ASSET': ['X','X','A','X','B'], 'PRODUCT': ['Z','Y','Z','C','Y']}
MAIN_df = pd.DataFrame(data=d)

def val_per(ASSET, PRODUCT):
    # 直接用numpy数组的布尔运算替代pd.eval
    return where((ASSET == 'X') & (PRODUCT == 'Z'), 0.04,
                 where(PRODUCT == 'Y', 0.08, 1.5))

MAIN_2_df = MAIN_df.assign(PCT=val_per(MAIN_df['ASSET'].values, MAIN_df['PRODUCT'].values))

更简洁的写法(无需自定义函数)

直接在assign中完成逻辑,避免函数调用的额外开销:

MAIN_2_df = MAIN_df.assign(
    PCT=np.where(
        (MAIN_df['ASSET'] == 'X') & (MAIN_df['PRODUCT'] == 'Z'),
        0.04,
        np.where(MAIN_df['PRODUCT'] == 'Y', 0.08, 1.5)
    )
)

补充说明

  • 原代码中使用MAIN_df.eval("@val_per(ASSET, PRODUCT)")的方式,在旧版pandas中可能通过兼容逻辑绕过了哈希检查,但新版pandas严格遵循字典键必须可哈希的规则,因此触发报错。
  • 向量化运算(直接操作numpy数组)是pandas/numpy的最优实践,比嵌套pd.eval的效率更高,代码可读性也更强。

内容的提问来源于stack exchange,提问作者DisplayNumber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 01:10:34