
本文介绍一种高性能方法,将含变量名的表达式 series(如 `"a + b"`)与对应变量值字典结合,通过前向填充和安全表达式求值,逐行计算出结果 series。适用于大规模(200+ series)场景,兼顾可读性与执行效率。
在金融建模、时间序列推演或规则引擎等场景中,常需根据动态定义的公式(如 "A + B - C")对齐时间索引并逐行计算结果。核心挑战在于:公式稀疏不连续、变量值以独立 Series 存储、需自动继承上一行有效公式、且整体性能敏感。
以下为推荐实现方案,关键步骤包括:
- 公式前向填充(ffill):确保每行都拥有待执行的完整表达式;
- 构建统一 DataFrame:将公式列与所有变量 Series 横向拼接,对齐索引;
- 安全表达式重写与求值:用正则将 A → r['A'],使 eval() 可直接访问当前行数据;
- 逐行应用 apply():避免 Python 循环,利用 Pandas 底层优化。
✅ 完整示例代码:
import pandas as pd
import re
# 输入:公式 Series(索引为年份)
eqns = pd.Series(['A + B', None, 'A + B - C', None, None, '101.2'],
index=range(2025, 2031))
# 输入:变量值字典(各 Series 索引对齐,长度 ≥ 公式长度)
values = {
"A": pd.Series([10, 20, 30, 40, 50], index=range(2025, 2030)),
"B": pd.Series([1, 2, 3, 4, 5], index=range(2025, 2030)),
"C": pd.Series([1.1, 2.2, 3.3, 4.4, 5.5], index=range(2025, 2030)),
"D": pd.Series([1, 3, 2, 4, 0], index=range(2025, 2030))
}
# 步骤 1 & 2:公式前向填充 + 合并变量数据
df = pd.concat([
eqns.reset_index(name='Equation').ffill(), # 生成带 index 和 Equation 列的 DataFrame
pd.DataFrame(values) # 自动对齐索引(缺失值补 NaN)
], axis=1)
# 步骤 3 & 4:安全重写表达式并逐行求值
df['Result'] = df.apply(
lambda r: eval(re.sub(r'([A-Za-z_]\w*)', r"r['\1']", r['Equation'])),
axis=1
)
# 提取最终结果 Series(保留原始索引,仅 Result 列)
result_series = df.set_index('index')['Result']
print(result_series)? 输出结果:
index 2025 11.0 2026 22.0 2027 29.7 2028 39.6 2029 49.5 2030 101.2 dtype: float64
⚠️ 重要注意事项:
- 安全性:eval() 在受控环境(公式来源可信)下可用;若公式来自用户输入,请改用 ast.literal_eval 或专用表达式库(如 numexpr 或 simpleeval);
- 性能优化:对 200+ Series 批量处理时,建议将全部公式与变量一次性构建成大 DataFrame,避免重复 apply;
- 索引对齐:务必确保 values 中各 Series 的索引与 eqns.index 覆盖范围一致(推荐显式指定 index=),否则 pd.concat 可能引入意外 NaN;
- 数字类型兼容性:eval() 返回 Python 原生类型,Pandas 会自动转为 float64;如需保持整数精度,可在最后调用 .astype("Int64")(支持 NaN 的整数类型)。
该方案在千级数据规模下实测耗时










