Pandas json_normalize处理深层嵌套JSON时drivers数组未扁平化问题
max_level 参数仅对对象类型的嵌套层级生效,不会自动展开数组类型的嵌套值,因此specs.drivers这个车手列表会原样保留。
你之前单独使用record_path参数只返回drivers子集,是因为缺少meta参数声明需要保留的父级字段,展开数组时父级的车辆、基础配置信息没有被关联到展开后的行上。另外你写的pd.normalize是笔误,正确方法名为pd.json_normalize。
解决方案
方案1:单步完成全量扁平化(性能最优)
调用json_normalize时同时传入record_path(指定要展开的数组路径)和meta(指定需要保留的父级字段路径),即可自动关联所有字段,无需后续拼接:
import pandas as pd df = pd.json_normalize( indict, # 指定需要展开为多行的嵌套数组路径 record_path=["specs", "drivers"], # 列出所有需要保留的非数组父级字段,嵌套字段按层级写为列表路径 meta=[ "make", "model", "year", ["specs", "engine"], ["specs", "gearbox"], ["specs", "suspension"] ], # 给drivers展开的字段加统一前缀,避免和父级字段重名 record_prefix="driver." )
如果drivers数组存储的是字符串、数字这类简单值而非结构化对象,去掉record_prefix参数即可,展开后可通过df = df.rename(columns={0: "driver_name"})重命名生成的列。
方案2:分步扁平化(适配已生成初步DataFrame的场景)
如果你已经完成了第一次扁平化、拿到了带未展开specs.drivers列的DataFrame,可以通过explode拆分数组后二次扁平化,不用重新执行全量normalize:
# 沿用之前的初步扁平化逻辑 df = pd.json_normalize(indict, max_level=5) # 1. 将drivers数组拆分为单行单个车手的格式 df = df.explode("specs.drivers").reset_index(drop=True) # 2. 把拆分出的drivers结构化字段扁平化,加前缀后和原表拼接 drivers_col = pd.json_normalize(df["specs.drivers"]).add_prefix("driver.") df = pd.concat([df.drop(columns=["specs.drivers"]), drivers_col], axis=1)
注意事项
- 使用单步方案时,
meta参数里的嵌套字段必须严格按照JSON层级写为列表路径,比如specs下的engine不能直接写"engine",必须写为["specs", "engine"],否则会触发KeyError。 - 如果单条数据的
drivers数组为空,单步方案默认会丢弃这条数据,需要保留空值行的话,额外传入参数errors="ignore"即可。 - 分步方案的灵活性更高,如果后续还有其他数组类型的嵌套字段需要展开,重复
explode+二次normalize的流程即可,不需要提前枚举所有父级字段。
内容的提问来源于stack exchange,提问作者gdogg371
相关产品推荐
相关产品推荐

