嵌套JSON转Pandas DataFrame部分数据解析不全该如何修复?
根因分析
你当前遇到的问题完全是由自定义函数中列类型判断的逻辑缺陷导致的,和你猜测的数据存在结构差异、空值的情况完全吻合:
- 原函数判断列表/字典列时使用了
.all()方法,要求整列所有元素都是对应类型才会被纳入展开处理队列 - 前10行数据刚好所有行的嵌套字段都是规范的列表/字典类型,所以判断通过,展开正常
- 当样本量变大或随机采样时,只要某一列存在1个非目标类型值(比如NaN、空值、字符串、数值等异常值),
.all()就会返回False,整列直接被跳过,自然不会展开datapoints字段
修复方案
调整列类型判断逻辑,兼容存在异常值的情况,同时对非目标类型的单元格做兜底处理,避免展开时报错,修复后的函数如下:
import pandas as pd import numpy as np def flatten_nested_json_df(df): df = df.reset_index() # 重置索引,生成从0到数据长度的整数索引 # 调整判断逻辑:只要列中存在列表/字典类型的元素就纳入处理,不需要整列全是 def has_list(col): return col.apply(lambda x: isinstance(x, list)).any() def has_dict(col): return col.apply(lambda x: isinstance(x, dict)).any() list_columns = df.columns[df.apply(has_list)].tolist() dict_columns = df.columns[df.apply(has_dict)].tolist() while len(list_columns) > 0 or len(dict_columns) > 0: new_columns = [] for col in dict_columns: # 非dict类型的单元格兜底转为空dict,避免normalize报错 horiz_exploded = pd.json_normalize( df[col].apply(lambda x: x if isinstance(x, dict) else {}) ).add_prefix(f'{col}.') horiz_exploded.index = df.index df = pd.concat([df, horiz_exploded], axis=1).drop(columns=[col]) new_columns.extend(horiz_exploded.columns) for col in list_columns: # 非list类型的单元格兜底转为空list,避免explode报错 df = df.drop(columns=[col]).join( df[col].apply(lambda x: x if isinstance(x, list) else []).explode().to_frame() ) new_columns.append(col) # 对新生成的列重新判断类型 list_columns = df[new_columns].columns[df[new_columns].apply(has_list)].tolist() dict_columns = df[new_columns].columns[df[new_columns].apply(has_dict)].tolist() return df
补充说明
如果你的数据中存在大量空值,可以在调用函数前先根据业务需求过滤掉全空的行,或者直接保留空值,上述函数会自动将空值对应的展开字段设为NaN,不影响整体流程。
内容的提问来源于stack exchange,提问作者Sathish Kumar
相关产品推荐
相关产品推荐

