Python中使用Pandas规范化复杂JSON:嵌套数组扁平化问题
如何用pandas的json_normalize扁平化嵌套数组字段?
首先,你的代码只返回一条记录是因为默认情况下,json_normalize不会自动展开所有嵌套数组——它只会处理顶层的键值对,而把数组字段完整保留为列表。要展开指定的嵌套数组,我们需要明确告诉它要处理哪个数组,同时保留其他顶层字段。
第一步:展开单个嵌套数组(digitalAssetFoodservice)
你需要用到json_normalize的两个关键参数:
record_path:指定要展开的嵌套数组的路径(这里就是'digitalAssetFoodservice')meta:列出需要保留的顶层非数组字段,确保这些字段会和展开后的数组元素一一对应
更新后的代码如下(注意新版本pandas的导入路径已经调整,建议用下面的导入方式):
from pandas import json_normalize # 新版本pandas的正确导入路径 data ={ "id":"001", "counties" : [ {"name":"y"},{"name":"X"}], "extendedDescriptionFrench" : "Fromage Brick Petit Gaspesien", "brand" : "PETIT GASPESIEN", "brandFrench" : "PETIT GASPESIEN", "productLife" : "90", "digitalAssetFoodservice" : [ { "digitalAssetFormatFoodservice" : "JPG", "digitalAssetGDTIFoodservice" : "754000000016500000000002167445", "digitalAssetImageVersionDateTimeFoodservice" : "2016-06-28T20:06:06.000-04:00", "digitalAssetStateFoodservice" : "P" }, { "digitalAssetFormatFoodservice" : "JPG", "digitalAssetGDTIFoodservice" : "754000000016500000000002167597", "digitalAssetImageTypeFoodservice" : "M", "digitalAssetImageVersionDateTimeFoodservice" : "2016-06-28T20:06:06.000-04:00" }, { "digitalAssetFormatFoodservice" : "JPG", "digitalAssetGDTIFoodservice" : "754000000016500000000002167687", "digitalAssetImageTypeFoodservice" : "C", "digitalAssetImageVersionDateTimeFoodservice" : "2016-06-28T20:06:06.000-04:00", "digitalAssetStateFoodservice" : "C" } ] } # 展开digitalAssetFoodservice数组,同时保留顶层字段 df = json_normalize( data, record_path='digitalAssetFoodservice', meta=['id', 'counties', 'extendedDescriptionFrench', 'brand', 'brandFrench', 'productLife'] ) print(df)
运行这段代码后,你会得到3条记录(对应digitalAssetFoodservice里的3个元素),每条记录都会带上顶层的id、brand等字段,数组里的键会变成独立的列。
第二步:处理多个嵌套数组字段
如果你的数据里有多个嵌套数组(比如这里的counties和digitalAssetFoodservice),需要分情况处理:
情况1:多个数组是独立的,需要展开为笛卡尔积
比如你想让每个counties元素都和每个digitalAssetFoodservice元素配对,这时候需要分两次展开:
- 先展开第一个数组(比如
counties),得到包含顶层数据和未展开的第二个数组的中间结果 - 再对中间结果展开第二个数组
代码示例:
# 第一步:先展开counties数组 df_counties = json_normalize( data, record_path='counties', meta=['id', 'extendedDescriptionFrench', 'brand', 'brandFrench', 'productLife', 'digitalAssetFoodservice'] ) # 第二步:展开digitalAssetFoodservice数组 df_final = json_normalize( df_counties.to_dict('records'), # 把中间DataFrame转为字典列表 record_path='digitalAssetFoodservice', meta=['id', 'name', 'extendedDescriptionFrench', 'brand', 'brandFrench', 'productLife'] ) print(df_final)
这段代码会得到6条记录(2个counties元素 × 3个digitalAsset元素),每个组合都保留了所有相关字段。
情况2:数组是嵌套层级的(比如数组里的元素还有子数组)
如果是这种结构,你可以用列表指定record_path的层级,比如record_path=['parent_array', 'child_array'],就能直接展开最内层的数组,同时保留上层的字段。
小提示
- 注意pandas版本:旧版本的
json_normalize在pandas.io.json下,新版本已经移到pandas模块直接导入,建议用from pandas import json_normalize避免报错。 - 如果数组字段里有缺失的键,
json_normalize会自动填充NaN,不用担心列缺失的问题。
内容的提问来源于stack exchange,提问作者Usman Rafiq
相关产品推荐
相关产品推荐

