pandas去重失败 嵌套JSON扁平化后前3列数据仍重复问题
Pandas展平嵌套JSON时去重失效问题排查
问题描述
使用pandas移除嵌套数据集中的重复字段时,现有代码输出结果仍存在重复,调用drop_duplicates()方法无法正常去除重复项,需要确认是展平逻辑错误还是处理流程设计冗余。
- 异常表现:导出的CSV结果中,前3列(codeId、日期、收益率)始终存在重复,其余属性列无重复问题。

待处理原始数据
{ "codeId": "fc-5599", "financeInfo": [ { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-02-28", "totalReturn": -0.0424735070051586, "financeInfoAttributes": [ { "attributeId": "a-256", "value": "12.032791372796499" }, { "attributeId": "a-257", "value": "9.975964795996589" }, { "attributeId": "a-258", "value": "4.719852927810759" }, { "attributeId": "a-259", "value": "4.18144793134823" } ] } ] }
当前处理代码
items = [] for i in response_finance['results']: items.append(i) df = pd.DataFrame(items) df1 = df.loc[:, ['codeId', 'financeInfo']] for i in df1.columns: df1 = df1.explode(i) flat_df1 = pd.json_normalize(json.loads(df1.to_json(orient="records"))) df2 = flat_df1.loc[:, ['codeId', 'financeInfo.date', 'financeInfo.totalReturn', 'financeInfo.financeInfoAttributes']] for i in df2.columns: df2 = df2.explode(i) flat_df2 = pd.json_normalize(json.loads(df2.to_json(orient="records"))) result = pd.DataFrame(flat_df2) result.drop_duplicates(subset=None, inplace=True) result.to_csv('data.csv', index=True)
问题根因
- 原始数据自带重复:源数据的
financeInfo数组中本身就存在5条完全一致的2022-01-30收益记录,这是重复的基础来源。 - 去重逻辑默认特性导致失效:2022-01-30的记录没有
financeInfoAttributes字段,展平后对应位置为NaN值。pandas默认判定NaN != NaN,因此drop_duplicates()会把带有NaN、其余字段完全一致的行判定为不重复,无法完成去重。 - 处理流程存在冗余设计:
- 循环对所有列执行
explode没有必要,仅对存储数组/列表的列执行explode即可,对字符串、数值这类标量列explode属于无效操作。 - 多次执行
to_json->json.loads->json_normalize的转换链完全多余,徒增性能消耗和类型转换异常风险。
- 循环对所有列执行
修正方案
直接用json_normalize按层级展平数据,仅对数组列做explode,去重时将NaN统一处理为相同占位符即可,优化后代码如下:
import pandas as pd import json # 直接展平第一层嵌套,指定记录路径和保留的顶层字段 df = pd.json_normalize( response_finance['results'], record_path='financeInfo', meta=['codeId'], errors='ignore' ) # 仅对存储属性数组的列做explode df = df.explode('financeInfoAttributes', ignore_index=True) # 展平内层属性字段 flat_df = pd.json_normalize( df['financeInfoAttributes'].fillna({}).to_list() ).add_prefix('financeInfoAttributes.') # 合并所有字段 result = pd.concat([df.drop(columns=['financeInfoAttributes']), flat_df], axis=1) # 临时填充NaN为统一占位符完成去重,之后还原空值 result = result.fillna('__NAN_PLACEHOLDER__').drop_duplicates(keep='first').replace('__NAN_PLACEHOLDER__', pd.NA) result.to_csv('data.csv', index=False)
处理后1月30日的重复记录只会保留1条,2月28日的4条属性记录正常保留,无多余重复。
内容的提问来源于stack exchange,提问作者user8422715
相关产品推荐
相关产品推荐

