如何基于另一DataFrame或列的条件删除行——重复账单与冲销金额的处理需求
处理重复账单并排除对应冲销记录的Pandas实现
我来帮你搞定这个需求!你已经能提取所有重复账单了,现在需要进一步调整逻辑——把有对应冲销的账单按冲销次数扣除,只保留真正重复且未被完全冲销的记录对吧?
先明确下核心业务规则:
- 对于同一
Case+Part_Number的组合:- 统计**正向金额(Charges)**的出现次数
- 统计**负向冲销金额(Credits)**的出现次数(冲销金额的绝对值需和正向金额一致)
- 最终保留的正向记录数 = 正向次数 - 冲销次数,仅保留结果>0的记录
原始数据回顾
先把你的数据用表格列出来,方便对照:
原始DataFrame
| Case | Part_Number | Cost |
|---|---|---|
| 111 | 2G | 53.00 |
| 112 | 7G | 25.00 |
| 112 | 7G | 25.00 |
| 113 | 8G | 20.00 |
| 113 | 8G | -20.00 |
| 114 | 9G | 15.00 |
| 115 | 2G | 53.00 |
| 115 | 2G | 53.00 |
| 115 | 2G | -53.00 |
目标结果
| Case | Part_Number | Cost |
|---|---|---|
| 111 | 2G | 53.00 |
| 112 | 7G | 25.00 |
| 112 | 7G | 25.00 |
| 114 | 9G | 15.00 |
| 115 | 2G | 53.00 |
解决方案代码
这里用Pandas实现,逻辑清晰且易维护:
import pandas as pd # 构建原始DataFrame(替换成你的实际数据源即可) df = pd.DataFrame({ 'Case': [111, 112, 112, 113, 113, 114, 115, 115, 115], 'Part_Number': ['2G', '7G', '7G', '8G', '8G', '9G', '2G', '2G', '2G'], 'Cost': [53.00, 25.00, 25.00, 20.00, -20.00, 15.00, 53.00, 53.00, -53.00] }) # 1. 拆分收费与冲销记录,给冲销记录标记对应正向金额的绝对值 charges = df[df['Cost'] > 0].copy() credits = df[df['Cost'] < 0].copy() credits['Abs_Cost'] = credits['Cost'].abs() # 2. 统计每个账单组合的收费次数与冲销次数 charge_counts = charges.groupby(['Case', 'Part_Number']).size().reset_index(name='Charge_Count') credit_counts = credits.groupby(['Case', 'Part_Number']).size().reset_index(name='Credit_Count') # 3. 计算每个组合需要保留的记录数,过滤掉无需保留的组合 merged_counts = pd.merge(charge_counts, credit_counts, on=['Case', 'Part_Number'], how='left').fillna(0) merged_counts['Keep_Count'] = merged_counts['Charge_Count'] - merged_counts['Credit_Count'] valid_groups = merged_counts[merged_counts['Keep_Count'] > 0] # 4. 给收费记录添加组内序号,筛选出前N条(N=Keep_Count) charges['Group_Index'] = charges.groupby(['Case', 'Part_Number']).cumcount() + 1 final_df = pd.merge(charges, valid_groups, on=['Case', 'Part_Number']) final_df = final_df[final_df['Group_Index'] <= final_df['Keep_Count']] # 5. 清理结果,保留目标列 final_df = final_df[['Case', 'Part_Number', 'Cost']].reset_index(drop=True) print(final_df)
代码逻辑解释
- 步骤1:拆分正向收费和负向冲销数据,给冲销记录添加绝对值字段,确保后续能精准匹配对应金额的收费记录。
- 步骤2:统计每个账单组合的出现次数,比如Case115+2G的收费次数是2,冲销次数是1。
- 步骤3:计算每个组合需要保留的记录数,Case113+8G的保留数为0,直接排除;Case115+2G保留1条。
- 步骤4:给每个收费组内的记录添加序号,只保留前N条(N=Keep_Count),实现扣除冲销次数的效果。
- 步骤5:清理辅助字段,得到和目标格式完全一致的结果。
运行代码后,输出的final_df就完全符合你的需求啦!
内容的提问来源于stack exchange,提问作者Link157
相关产品推荐
相关产品推荐

