
本文介绍如何利用 pandas 将字典中定义的转换因子与 dataframe 中的数值列进行广播乘法运算,并为每行计算其在字典映射范围内所有有效转换结果的最小值,最终作为新列添加到原表中。
本文介绍如何利用 pandas 将字典中定义的转换因子与 dataframe 中的数值列进行广播乘法运算,并为每行计算其在字典映射范围内所有有效转换结果的最小值,最终作为新列添加到原表中。
在数据处理中,常需根据外部映射关系(如转换系数、权重或汇率)对某列数值进行动态变换,并进一步聚合(如取最小值)。本例中,data 是一个以目标项(如 'Item1')为列、源项(如 'Item5')为索引的转换系数矩阵;而 df 包含各 Item 对应的原始值(Col1)。目标是:对每个目标项(如 Item1),找出其在 data 中所关联的所有源项(Item5, Item6, Item4)对应的 Col1 值 × 系数后的最小结果,并填入新列 Minc_Col1。
关键在于对齐索引与映射:data 的行索引(Item5, Item6, Item4, Item9)需与 df 中 Col0 的值匹配,从而获取对应 Col1 数值作为缩放因子。以下是完整、可复现的解决方案:
import pandas as pd
# 转换系数字典 → DataFrame
data = pd.DataFrame({
'Item1': {'Item5': 10, 'Item6': 100, 'Item4': 1},
'Item2': {'Item5': 10, 'Item6': 100, 'Item4': 1},
'Item4': {'Item5': 10, 'Item6': 100, 'Item9': 1}
})
# 原始数据
df = pd.DataFrame({
'Col0': ['Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'Item6'],
'Col1': [180, 250, 150, 205, 22, 2],
'Col2': [190, 150, 150, 200, 18, 2.5]
})
# 核心逻辑:计算每列(即每个目标 Item)的最小转换值
result = (
df.set_index('Col0') # 以 Item 为索引,便于 map 查找
.assign(
Minc_Col1=(
data.mul(data.index.map(df.set_index('Col0')['Col1']), axis=0)
.min()
)
)
.reset_index()
.rename(columns={'Col0': 'Item', 'Col1': 'Price1', 'Col2': 'Price2'})
)
print(result)
输出结果如下:
Item Price1 Price2 Minc_Col1 0 Item1 180 190.0 200.0 1 Item2 250 150.0 200.0 2 Item3 150 150.0 NaN 3 Item4 205 200.0 200.0 4 Item5 22 18.0 NaN 5 Item6 2 2.5 NaN
✅ 原理详解:
- df.set_index('Col0')['Col1'] 构建从 Item 到 Col1 值的映射 Series;
- data.index.map(...) 将 data 行索引(源项)映射为对应 Col1 值(如 Item5 → 22, Item6 → 2, Item4 → 205);
- data.mul(..., axis=0) 沿行方向广播乘法:每行(源项)× 其 Col1 值,生成转换后矩阵;
- .min() 默认按列(即每个目标项 Item1/Item2/Item4)取最小值,缺失项自动为 NaN;
- assign() 安全添加新列,rename() 统一列名,语义清晰。
⚠️ 注意事项:
- 若 data 的行索引中存在 df['Col0'] 未覆盖的项(如 Item9),其 Col1 映射为 NaN,导致整行乘积为 NaN,不影响其他列最小值计算;
- Item3 在 data 中无对应列 → Minc_Col1 为 NaN;Item5/Item6 在 data 中无对应行索引 → 无法参与任何转换 → 同样为 NaN;
- 所有运算均基于索引对齐,不依赖顺序,确保鲁棒性;
- 如需同时返回最小值来源项(如 Item6),可使用 agg(['idxmin', 'min']) 或 stack().groupby(...).agg(...) 实现多源追踪(详见进阶部分)。
该方法兼具向量化效率与语义可读性,适用于大规模映射场景,是 Pandas 高级索引与广播运算的典型实践。











