使用pd.eval()优化Pandas性能时遇AttributeError问题求助
优化Pandas批量匹配逻辑时的
visit_ExtSlice属性错误解决 问题背景
我手头有近3600条结构化数据,前15行示例如下:
col1 col2 col3 col4 col5 col6 col7 col8 0 f43 e1 -44.30 442.24 2353.55 1964.71 326.74 2424.52 1 f58 e1 -44.30 442.24 2353.55 1964.71 326.74 2424.52 2 f13 e2 715.04 1656.92 -142.41 2979.43 2279.57 2629.24 3 f8 e2 715.04 1656.92 -142.41 2979.43 2279.57 2629.24 4 f15 e3 850.45 -80.54 1468.52 2540.86 2108.47 2175.76 5 f19 e3 850.45 -80.54 1468.52 2540.86 2108.47 2175.76 6 f56 e4 2540.86 2108.47 2175.76 497.09 314.43 2498.20 7 f21 e4 2540.86 2108.47 2175.76 497.09 314.43 2498.20 8 f45 e5 1906.87 2632.99 569.87 497.09 314.43 2498.20 9 f59 e5 1906.87 2632.99 569.87 497.09 314.43 2498.20 10 f16 e6 1529.13 2369.10 2995.27 968.80 -10.81 2706.25 11 f41 e6 1529.13 2369.10 2995.27 968.80 -10.81 2706.25 12 f48 e7 607.30 1570.72 2206.87 590.33 33.49 2123.76 13 f38 e7 607.30 1570.72 2206.87 590.33 33.49 2123.76 14 f1 e8 590.33 33.49 2123.76 831.43 2887.28 1306.86 15 f9 e8 590.33 33.49 2123.76 831.43 2887.28 1306.86
原本采用Jezrael的方案处理3600条数据耗时约5秒,为适配未来更大规模的数据集,我尝试用pd.eval()优化性能,却触发如下错误:
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_ExtSlice'
原处理代码
df["v1"] = df.apply(lambda row: row['col3':'col5'].tolist(), axis=1) df["v2"] = df.apply(lambda row: row['col6':'col8'].tolist(), axis=1) v1 = df['v1'].to_numpy() v2 = df['v2'].to_numpy() m = (v1 == v1[:, None]) | (v2 == v2[:, None]) | (v1 == v2[:, None]) | ( v2 == v1[:, None]) np.fill_diagonal(m, False) df['col9'] = np.dot(m, df['col2'] + ',') df['col9'] = df['col9'].str[:-1].replace('', np.nan, regex=True)
尝试优化的报错代码
df["v1"] = df.apply(lambda row: row['col3':'col5'].tolist(), axis=1) df["v2"] = df.apply(lambda row: row['col6':'col8'].tolist(), axis=1) v1 = df['v1'].to_numpy() v2 = df['v2'].to_numpy() # 检查A列当前值是否与A列其他值相等 mask_A_A = pd.eval('v1[:, None] == v1') # 检查A列当前值是否与B列其他值相等 mask_A_B = pd.eval('v1[:, None] == v2') # 检查B列当前值是否与B列其他值相等 mask_B_B = pd.eval('v2[:, None] == v2') # 检查B列当前值是否与A列其他值相等 mask_B_A = pd.eval('v2[:, None] == v1') # 合并掩码并使用numexpr生成col9列 mask = ne.evaluate( '(mask_A_A | mask_A_B | mask_B_B | mask_B_A) & (v1[:, None] != v1) & (v2[:, None] != v2)') col9 = np.where(mask, df['col2'].values[:, None], '') df['col9'] = pd.Series([', '.join(names) if len(names) > 0 else None for names in col9])
环境版本
- Pandas:1.5.3
- numexpr:2.8.4
问题原因与优化方向
经过排查确认:pd.eval()不支持处理包含numpy数组的列,这类场景下的性能优化建议使用Cython或Numba来实现。
内容的提问来源于stack exchange,提问作者Lihka_nonem
相关产品推荐
相关产品推荐

