如何基于多列关联在Pandas中实现不同DataFrame的算术运算?
在Pandas中基于关联列执行DataFrame算术运算
数据背景
现有两个DataFrame:
DF1
| ColA | Colb | Stock | Date |
|---|---|---|---|
| A | 1 | 3 | 2022-12-26 |
| B | 2 | 3 | 2022-12-26 |
| C | 3 | 3 | 2022-12-26 |
DF2
| ColA | Colb | Sales | Date |
|---|---|---|---|
| A | 1 | 1 | 2022-12-26 |
| B | 2 | 1 | 2022-12-26 |
| C | 3 | 1 | 2022-12-26 |
需求
基于任意数量的关联列(此处为ColA、Colb、Date这些共同列),计算当日最终库存:Stock - Sales,预期结果如下:
当日最终库存
| ColA | Colb | Stock | Date |
|---|---|---|---|
| A | 1 | 2 | 2022-12-26 |
| B | 2 | 2 | 2022-12-26 |
| C | 3 | 2 | 2022-12-26 |
对应的等效SQL代码如下:
SELECT DF1.ColA, DF1.Colb, DF1.Date, DF1.Stock - coalesce(DF2.Sales, 0) AS Stock FROM DF1 LEFT JOIN DF2 ON DF1.ColA = DF2.ColA AND DF1.Colb = DF2.Colb AND DF1.Date = DF2.Date
Pandas实现方法
提供两种实用的实现方式:
方法一:merge+算术运算(贴近SQL左连接逻辑)
先通过merge执行左连接关联指定列,再计算库存并整理结果:
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({ 'ColA': ['A', 'B', 'C'], 'Colb': [1, 2, 3], 'Stock': [3, 3, 3], 'Date': ['2022-12-26']*3 }) df2 = pd.DataFrame({ 'ColA': ['A', 'B', 'C'], 'Colb': [1, 2, 3], 'Sales': [1, 1, 1], 'Date': ['2022-12-26']*3 }) # 指定关联列 join_cols = ['ColA', 'Colb', 'Date'] # 左连接两个DataFrame merged_df = df1.merge(df2, on=join_cols, how='left') # 计算最终库存,用fillna(0)处理DF2无匹配的情况 merged_df['Stock'] = merged_df['Stock'] - merged_df['Sales'].fillna(0) # 保留需要的列 result_df = merged_df[join_cols + ['Stock']] print(result_df)
方法二:set_index+算术运算(简洁高效)
将共同列设为索引,直接执行减法运算后恢复索引:
import pandas as pd # 构造示例数据 df1 = pd.DataFrame({ 'ColA': ['A', 'B', 'C'], 'Colb': [1, 2, 3], 'Stock': [3, 3, 3], 'Date': ['2022-12-26']*3 }) df2 = pd.DataFrame({ 'ColA': ['A', 'B', 'C'], 'Colb': [1, 2, 3], 'Sales': [1, 1, 1], 'Date': ['2022-12-26']*3 }) # 指定关联列 index_cols = ['ColA', 'Colb', 'Date'] # 设置索引后执行减法,fill_value=0处理无匹配的情况 result_df = (df1.set_index(index_cols)['Stock'] - df2.set_index(index_cols)['Sales'] .fillna(0)).reset_index() print(result_df)
两种方法均可满足需求:方法一逻辑直观,适合需要保留中间数据或后续多步处理的场景;方法二代码更简洁,适合仅需完成算术运算的场景。
内容的提问来源于stack exchange,提问作者Ari Frid
相关产品推荐
相关产品推荐

