分组合并DataFrame后去重失败,JSON生成重复数据问题排查
问题描述
有如下两个DataFrame:
DataFrame 1: df1
| UniqueId | VendorId | Fname | LName | VendorAccNo |
|---|---|---|---|---|
| 001 | 12 | ABC | XYZ | 8787888 |
| 002 | 13 | XYZ | FFF | 8787888 |
| 003 | 14 | PQR | ZZZ | 8787888 |
| 005 | 16 | MMM | TTT | 5432100 |
| 006 | 17 | BBB | XXX | 5432100 |
| 007 | 18 | CCC | PPP | 8787888 |
DataFrame 2: df2
| VendorXNo | PhNo | Active | Type | ActiveTime |
|---|---|---|---|---|
| 8787888 | 45789 | Y | W | 2019-05-22 09:36:04 |
| 8787888 | 45789 | Y | W | 2019-05-22 09:36:04 |
| 8787888 | 12345 | N | M | 2019-05-23 09:36:04 |
| 8787888 | 45789 | Y | W | 2019-05-24 09:36:04 |
| 8787888 | 56742 | Y | W | 2019-05-25 09:36:04 |
| 8787888 | 45789 | Y | H | 2019-05-26 09:36:04 |
| 5432100 | 11111 | Y | W | 2019-05-25 09:37:04 |
| 5432100 | 22222 | Y | H | 2019-05-26 09:38:04 |
需基于VendorAccNo与VendorXNo关联两个DataFrame生成JSON,同时去除df2中的重复数据。现有实现代码如下:
df_merged = pd.merge(df1, df2, left_on='VendorAccNo', right_on='VendorXNo', how='left') result = df_merged.groupby(['VendorXNo']).apply(lambda x: x[[ 'PhNo', 'Active', 'Type', 'ActiveTime']].to_dict('records')).reset_index(name='Phone Info') uniquedf = ~df_merged['Phone Info'].map(lambda x: tuple(sorted(x.items()))).duplicated()
执行去重代码时报错:
list object has no attribute items
若不添加去重代码,生成的JSON中每个UniqueId对应的Phone Info会重复多次(本该仅5条记录却重复15次),示例如下:
{ "UniqueId" : "001", "VendorId" : "12", "Fname" : "ABC", "Lname" : "XYZ", "VendorAccNo" : "8787888", "Phone Info" : [ { "PhNo": "45789", "Do Not Contact": "Y", "Change Date Time": "2019-05-22 09:36:04", "Phone Type": "WORK" }, // ------ 该记录在每个UniqueId的JSON中重复15次,而正确应为5条记录。 ] }
请问这段代码存在什么问题?为何去重操作会失败?
问题分析与解决方案
代码核心问题
错误的列访问与类型误解
Phone Info是result数据框的列,而非df_merged的列——你错误地在df_merged中访问这个不存在的列。退一步说,即使访问result['Phone Info'],每个元素是字典列表,而列表没有items()方法,这就是报错list object has no attribute items的直接原因。重复数据的根源:关联前未去重
df2本身存在完全重复的行(比如前两行),直接merge会让这些重复行与df1中对应VendorAccNo的每一行做笛卡尔积关联,导致数据量大幅膨胀,最终分组后Phone Info里会包含大量重复字典,生成JSON时自然重复多次。
正确实现流程
步骤1:先清理df2的重复数据
从源头消除重复,避免关联时的数据膨胀:
# 去除df2中完全重复的行,保留首次出现的记录 df2_clean = df2.drop_duplicates()
步骤2:关联去重后的df2与df1
用清理后的df2做关联,减少无效行:
df_merged = pd.merge(df1, df2_clean, left_on='VendorAccNo', right_on='VendorXNo', how='left')
步骤3:分组生成结构化的Phone Info
按df1的唯一标识字段分组,确保每个UniqueId对应正确的去重电话记录:
result = df_merged.groupby(['UniqueId', 'VendorId', 'Fname', 'LName', 'VendorAccNo']) \ .apply(lambda x: x[['PhNo', 'Active', 'Type', 'ActiveTime']].to_dict('records')) \ .reset_index(name='Phone Info')
步骤4:生成目标JSON
将结果转换为JSON格式:
import json json_output = result.to_json(orient='records', indent=2) print(json_output)
方案有效性说明
- 先对df2去重,从根源避免了merge后的笛卡尔积膨胀,减少了不必要的重复行。
- 分组时包含df1的所有唯一标识字段,确保每个UniqueId对应的
Phone Info是该账号下的去重电话记录,不会出现重复多次的情况。
内容的提问来源于stack exchange,提问作者Virendra Wadekar
相关产品推荐
相关产品推荐

