技术求助:如何从DataFrame中移除负值及等额同用户正值?
解决方案
针对你遇到的用户退货负值记录与等额正值记录抵消的需求,用Python的Pandas可以高效处理,以下是具体实现步骤:
1. 数据预处理
首先将原始数据加载为DataFrame,并把带$符号的金额转换为数值类型,方便后续计算:
import pandas as pd # 加载示例数据 data = { 'Person': ['Person 1', 'Person 1', 'Person 1', 'Person 2', 'Person 2', 'Person 3', 'Person 3'], 'Amount': ['$150', '-$150', '$150', '$100', '-$100', '$50', '$20'] } df = pd.DataFrame(data) # 去除金额中的$符号并转为数值 df['Amount'] = df['Amount'].str.replace('$', '').astype(float)
2. 分组抵消正负记录
针对每个用户的交易记录,统计等额正负交易的数量,保留抵消后剩余的正值记录:
def process_user(group): # 按金额绝对值分组,统计正负交易的数量 amount_summary = group.groupby(group['Amount'].abs())['Amount'].agg( positive_count=lambda x: (x > 0).sum(), negative_count=lambda x: (x < 0).sum() ) # 计算每个金额绝对值需要保留的正值数量 amount_summary['remaining'] = amount_summary['positive_count'] - amount_summary['negative_count'] # 收集需要保留的记录 remaining_records = [] for abs_amount, row in amount_summary.iterrows(): if row['remaining'] > 0: # 提取对应数量的正值记录 keep_rows = group[group['Amount'] == abs_amount].head(row['remaining']) remaining_records.append(keep_rows) return pd.concat(remaining_records) # 对每个用户分组处理 result_df = df.groupby('Person').apply(process_user).reset_index(drop=True) # 将金额转回带$的格式 result_df['Amount'] = '$' + result_df['Amount'].astype(str) # 输出结果 print(result_df)
运行后得到的结果就是你期望的DataFrame:
Person Amount 0 Person 1 $150 1 Person 3 $50 2 Person 3 $20
备选方案(按交易顺序抵消)
如果需要严格按照交易顺序,用先出现的正值抵消后续的负值,可以用以下方法:
def process_user_by_order(group): # 分离正负交易记录 positives = group[group['Amount'] > 0].copy() negatives = group[group['Amount'] < 0].copy() negatives['abs_amount'] = negatives['Amount'].abs() # 逐个匹配抵消 for neg_idx, neg_row in negatives.iterrows(): # 找到第一个金额匹配的未抵消正值 match_pos = positives[positives['Amount'] == neg_row['abs_amount']].head(1) if not match_pos.empty: # 移除匹配的正负记录 positives = positives.drop(match_pos.index) group = group.drop([neg_idx, match_pos.index[0]]) return group # 应用处理并格式化 result_df_order = df.groupby('Person').apply(process_user_by_order).reset_index(drop=True) result_df_order['Amount'] = '$' + result_df_order['Amount'].astype(str)
内容的提问来源于stack exchange,提问作者Thomasiko
相关产品推荐
相关产品推荐

