如何扁平化含列表与字典的Python嵌套字典并导出为电子表格?
处理深度嵌套字典(含字典列表混合)的递归扁平化方案
我完全懂你遇到的痛点——这种嵌套层级不固定、字典和列表交叉混合的结构,用pd.io.json.json_normalize()加explode的组合,要么在数据量大的时候慢到离谱,要么遇到深层嵌套直接失效。我之前处理类似的多源数据时也踩过这个坑,给你分享一个专门解决这种场景的递归扁平化方案,亲测好用:
核心思路
递归遍历每个元素:
- 遇到字典:把当前层级的键作为父键,继续递归处理子字典的键值对;
- 遇到列表:遍历列表里的每一个元素,为每个元素生成独立的键(加上索引避免冲突),如果元素还是字典/列表就继续递归;
- 遇到普通值:直接把键值对存入结果。
这样最终得到的是一个完全扁平化的字典,所有层级的信息都通过下划线连接的键名保留,转成DataFrame后就能直接导出Excel或写入数据库。
实现代码
import pandas as pd def flatten_nested(data, parent_key='', sep='_'): items = [] for k, v in data.items(): # 拼接当前层级的键名,用下划线区分父子层级 new_key = f"{parent_key}{sep}{k}" if parent_key else k if isinstance(v, dict): # 递归处理子字典,把当前键作为父键传递下去 items.extend(flatten_nested(v, new_key, sep).items()) elif isinstance(v, list): # 遍历列表中的每个元素,逐个展开 for idx, elem in enumerate(v): # 为列表元素添加索引后缀,避免同层级键名冲突 list_item_key = f"{new_key}_{idx}" if isinstance(elem, (dict, list)): # 列表元素仍是嵌套结构,继续递归 items.extend(flatten_nested(elem, list_item_key, sep).items()) else: # 列表元素是普通值,直接存入键值对 items.append((list_item_key, elem)) else: # 普通键值对,直接存入 items.append((new_key, v)) return dict(items) def nested_to_dataframe(data): # 兼容单个字典或字典列表的输入 input_list = data if isinstance(data, list) else [data] # 批量扁平化所有元素 flattened_records = [flatten_nested(item) for item in input_list] # 转成DataFrame,自动补全缺失列(用NaN填充) return pd.DataFrame(flattened_records) # 测试你的示例数据 mydict = {'Carcompany': {'Brand': 'Ford', 'Factory': {'Country': 'Germany', 'Workers': {'Engineers': '150', 'Mechanics': '200'}, 'FactoryDetails': [{'FactoryCode': '1', 'FactoryCity': 'Cologne', 'FactoryCityDetail': [{'Shifts': 'Day', 'Days': '7'}, {'Shifts': 'Night', 'Days': '5'}]}, {'FactoryCode': '2', 'FactoryCity': 'Berlin', 'FactoryCityDetail': {'Shifts': 'Night', 'Days': '5'}}]}}} # 生成DataFrame flat_df = nested_to_dataframe(mydict) # 查看结果 print(flat_df) # 导出到Excel flat_df.to_excel('flattened_car_data.xlsx', index=False) # 如果要写入关系型数据库,可以用df.to_sql()方法,配合SQLAlchemy连接
关键优势
- 适配任意嵌套深度:不管你的字典嵌套多少层,只要是字典和列表的混合结构,都能完整展开;
- 速度更快:一次性递归展开所有层级,避免了
explode多次循环带来的性能损耗; - 保留层级信息:键名用下划线拼接(比如
Carcompany_Factory_FactoryDetails_0_FactoryCityDetail_0_Shifts),能清晰看到原始数据的层级关系; - 灵活兼容:支持单个字典或字典列表的输入,DataFrame会自动处理不同条目之间的列缺失。
可选优化
- 如果不需要列表元素的索引后缀,可以把
list_item_key = f"{new_key}_{idx}"改成new_key,但注意这样会覆盖同键的列表元素,只保留最后一个; - 可以在递归函数里添加过滤逻辑,跳过不需要展开的特定键;
- 如果键名太长,可以自定义分隔符(比如把
sep='_'改成sep='.')。
内容的提问来源于stack exchange,提问作者pscl
相关产品推荐
相关产品推荐

