将pandas DataFrame转为defaultdict并筛选同id下正负匹配的数值
问题解决:pandas DataFrame按id筛选正负匹配行转defaultdict
错误原因
你代码中报错的核心原因是row['amount']是单个整数类型值,isin()是pandas Series才有的方法,不能直接作用于普通数值。同时原有判断逻辑有误:你需要判断的是当前id分组内是否存在和当前金额互为相反数的记录,不能对单行值单独做判断。
实现代码
from collections import defaultdict import pandas as pd d = {'id': [1,1,1,1,2,2,3,3,3,4,4,4,4], 'label':['A','A','B','G','A','BB','C','C','A','BB','B','AA','AA'], 'amount':[2,-12,12,-12,5,-5,2,3,5,3,3,10,-10]} df = pd.DataFrame(d) # 新增金额绝对值列,方便分组判断正负匹配关系 df['abs_amount'] = df['amount'].abs() # 筛选规则:同id、同绝对值金额的分组内同时存在正、负两种金额 mask = df.groupby(['id', 'abs_amount'])['amount'].transform(lambda x: (x.max() > 0) & (x.min() < 0)) filtered_df = df[mask] # 转换为要求的defaultdict格式 res = defaultdict(list) for _, row in filtered_df.iterrows(): res[row['id']].append({'label': row['label'], 'amount': row['amount']}) print(res)
输出验证
运行后得到的结果和你的需求一致,仅注意你给出的期望输出中id2对应的label存在笔误,实际运行结果和原始数据对应,输出如下:
defaultdict(list, {1: [{'label': 'A', 'amount': -12}, {'label': 'B', 'amount': 12}, {'label': 'G', 'amount': -12}], 2: [{'label': 'A', 'amount': 5}, {'label': 'BB', 'amount': -5}], 4: [{'label': 'AA', 'amount': 10}, {'label': 'AA', 'amount': -10}]})
内容的提问来源于stack exchange,提问作者Unicorn07
相关产品推荐
相关产品推荐

