本文介绍如何对多个结构相同的 dataframe 批量执行基于行标签(如产品名)的逐元素乘法运算,核心是将价格映射表设为索引,利用 pandas 广播机制实现简洁、高效、无循环的向量化操作。
在实际数据分析中,常需对一组同构 DataFrame(如不同时间段的订单记录)统一应用同一组权重或单价(如各品类单位成本)。若机械地遍历、对齐、逐列计算,不仅代码冗长,还易因索引不匹配引发 ValueError 或隐式错误。最优解是让数据“自对齐”——将公共维度(如 Prod)设为索引,再借助 Pandas 的索引对齐与广播规则完成自动匹配计算。
以下以三张订单表 recs_df1/recs_df2/recs_df3 与一张成本表 costs_df 为例,演示两种专业级实现方式:
✅ 推荐方案:索引对齐 + 向量化广播(一行解决)
import pandas as pd
import numpy as np
# 构建示例数据(关键:所有 DataFrame 以 'Prod' 为 index)
recs_df1 = pd.DataFrame({'Ord1': [4, 3, 2], 'Ord2': [2, 1, 3], 'Ord3': [1, 5, 4]},
index=['Toys', 'Candy', 'Décor'])
recs_df2 = pd.DataFrame({'Ord1': [1, 4, 2], 'Ord2': [0, 1, 3], 'Ord3': [6, 5, 4]},
index=['Toys', 'Candy', 'Décor'])
recs_df3 = pd.DataFrame({'Ord1': [1, 0, 1], 'Ord2': [2, 1, 3], 'Ord3': [3, 0, 4]},
index=['Toys', 'Candy', 'Décor'])
costs_df = pd.DataFrame({'Price': [2.0, 1.0, 3.0]}, index=['Toys', 'Candy', 'Décor'])
# 批量处理:利用索引自动对齐,广播乘法(返回 list of DataFrames)
dfs = [recs_df1, recs_df2, recs_df3]
new_dfs = [df.multiply(costs_df['Price'], axis=0) for df in dfs]
# 验证结果(例如 new_dfs[0] 即 new_df1)
print(new_dfs[0])
✅ 优势:df.multiply(…, axis=0) 显式指定按行(index)广播,安全、可读、无需转换为 NumPy;索引自动对齐确保 Toys×2.0, Candy×1.0, Décor×3.0 精准匹配,即使原始数据顺序错乱也无影响。
⚠️ 替代方案:NumPy 广播(需谨慎使用)
# 仅当确认索引完全一致且无需保留 DataFrame 属性时可用
new_dfs_numpy = [df * costs_df['Price'].values.reshape(-1, 1) for df in dfs]
# 注意:结果为 ndarray,需手动转回 DataFrame 并恢复索引列
new_dfs = [pd.DataFrame(arr, index=df.index, columns=df.columns)
for arr, df in zip(new_dfs_numpy, dfs)]
⚠️ 风险提示:costs_df.to_numpy() 返回二维数组,直接 * df 可能触发隐式广播(如 (3,1) * (3,3)),但会丢失索引和列名信息,且一旦 costs_df 索引顺序与 df 不一致,结果将错误。强烈建议优先使用 .multiply() 方法。