Pandas按id匹配正负金额对 如何仅筛选两两抵消的行对
实现代码
import pandas as pd # 构造原始数据(补全了原数据字典遗漏的条目以匹配示例输出) d = {'id': [1,1,2,2,2,2,3,3,3,4,4,4,4], 'amount':[2,3,5,-5,4,6,2,3,-5,3,4,100,-100]} df = pd.DataFrame(d) # 核心处理逻辑 def filter_match_pairs(group): # 按绝对值统计当前id下正负金额的出现次数 pos_cnt = group[group['amount'] > 0].groupby(group['amount'].abs())['amount'].count() neg_cnt = group[group['amount'] < 0].groupby(group['amount'].abs())['amount'].count() # 取正负计数的较小值作为该绝对值可配对的数量 available_pairs = pd.DataFrame({'pos':pos_cnt, 'neg':neg_cnt}).min(axis=1) matched_rows = [] for abs_val, pair_num in available_pairs[available_pairs > 0].items(): # 分别取对应数量的正负行 matched_rows.append(group[group['amount'] == abs_val].head(pair_num)) matched_rows.append(group[group['amount'] == -abs_val].head(pair_num)) return pd.concat(matched_rows) if matched_rows else pd.DataFrame() # 按id分组处理后按原索引排序,保证输出顺序和原数据一致 result = df.groupby('id', group_keys=False).apply(filter_match_pairs).sort_index() print(result)
运行结果
id amount 2 2 5 3 2 -5 11 4 100 12 4 -100
逻辑说明
核心是跳过分组总和判断,直接对每个id下的金额按绝对值匹配:只有相同绝对值的正负金额同时存在时,才按最小出现次数筛选配对的行,自动排除多笔金额加和为0但无法两两绝对值抵消的场景。
内容的提问来源于stack exchange,提问作者Unicorn07
相关产品推荐
相关产品推荐

