You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python:基于另一DataFrame匹配行将指定列数据移至上一行

问题描述

我有两个DataFrame:
df1:

Name Month  Amount  Status
0   Bill   Apr       0           
1   Bill   May       0           
2   Bill   Jun     100  member
3  Sally   Apr       0           
4  Sally   May       0           
5  Sally   Jun     200  member
6    Tom   Apr       0           
7    Tom   May     300  member
8    Tom   Jun       0           

df2:

Name Month
0  Bill   Jun
1   Tom   May

需求:更新df1,当df1的Name和Month与df2匹配时,将该行的Amount和Status值移至同一用户的上一行,原行的这两个字段置为0。已知每个匹配行都存在对应的上一行,且数据已按Name和Month正确排序。

预期结果:

Name Month  Amount  Status
0   Bill   Apr       0           
1   Bill   May     100  member           
2   Bill   Jun       0
3  Sally   Apr       0           
4  Sally   May       0           
5  Sally   Jun     200  member
6    Tom   Apr     300  member          
7    Tom   May       0
8    Tom   Jun       0           

我知道可以用iterrows()实现,但有没有更直接高效的方法?


高效实现方案

用pandas的向量化操作结合布尔索引就能完成,完全避免循环,比iterrows()效率高得多,尤其适合大数据量场景:

步骤1:标记需要处理的匹配行

先把df2的Name和Month组合成元组集合,再用这个集合匹配df1的对应行,生成掩码:

# 生成需匹配的(Name, Month)元组集合
match_pairs = set(df2.apply(tuple, axis=1))
# 标记df1中符合匹配条件的行
mask = df1[['Name', 'Month']].apply(tuple, axis=1).isin(match_pairs)

步骤2:将匹配行的值移动到上一行

利用shift(1)获取匹配行的上一行位置,直接赋值对应字段:

# 把匹配行的Amount和Status值赋值给同一用户的上一行
df1.loc[mask.shift(1).fillna(False), ['Amount', 'Status']] = df1.loc[mask, ['Amount', 'Status']].values

步骤3:清空原匹配行的字段

将匹配行的Amount置0,Status清空:

df1.loc[mask, 'Amount'] = 0
df1.loc[mask, 'Status'] = ''

完整可运行代码

import pandas as pd

# 构造示例数据
df1 = pd.DataFrame({
    'Name': ['Bill', 'Bill', 'Bill', 'Sally', 'Sally', 'Sally', 'Tom', 'Tom', 'Tom'],
    'Month': ['Apr', 'May', 'Jun', 'Apr', 'May', 'Jun', 'Apr', 'May', 'Jun'],
    'Amount': [0, 0, 100, 0, 0, 200, 0, 300, 0],
    'Status': ['', '', 'member', '', '', 'member', '', 'member', '']
})

df2 = pd.DataFrame({
    'Name': ['Bill', 'Tom'],
    'Month': ['Jun', 'May']
})

# 执行处理逻辑
match_pairs = set(df2.apply(tuple, axis=1))
mask = df1[['Name', 'Month']].apply(tuple, axis=1).isin(match_pairs)

df1.loc[mask.shift(1).fillna(False), ['Amount', 'Status']] = df1.loc[mask, ['Amount', 'Status']].values
df1.loc[mask, 'Amount'] = 0
df1.loc[mask, 'Status'] = ''

print(df1)

运行后即可得到预期结果,全程基于pandas的向量化运算,性能远高于循环遍历的iterrows()。

内容的提问来源于stack exchange,提问作者Maxxmilo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:29:53