处理多JSON文件时合并字典与合并DataFrame哪种效率更高?
性能对比及优化方案
两种方案的效率结论
逐文件处理为DataFrame后统一拼接的方案,效率远高于攒全局字典后转DataFrame,原因如下:
- 嵌套JSON场景下手动维护全局字典需要自行处理键对齐、嵌套层级扩展、列表展开逻辑,额外开销极高,且完全浪费了pandas
json_normalize等内置方法的C语言优化能力。 - 全局字典的内存占用会随文件量增加持续线性上涨,且每次新增文件都要做全量键匹配,文件量级过万后开销会非常明显。
现有逻辑的可优化点
当前的实现逻辑框架是合理的,只有两个常见的低效点可以调整:
- 不要逐次拼接DataFrame:不要每处理完一个文件就调用一次
pd.concat或append,这两个操作每次都会生成全新的DataFrame对象,带来大量重复内存拷贝。正确做法是把所有处理完成的小DataFrame先存入一个普通Python列表,所有文件处理完后仅执行一次concat操作,性能可提升数百倍。 - 替换
apply(pd.Series)展开列表的写法:该操作是纯Python循环实现,性能极差,替换为pd.DataFrame(df['列表列名'].tolist(), index=df.index)的写法,展开速度可提升10~50倍。
优化后的实现代码示例
import pandas as pd import json from pathlib import Path # 提前配置需要提取的字段,避免加载无用数据 TARGET_META = ["顶层字段1", "顶层字段2", "嵌套字段.二级字段1"] # 存储所有小df的缓存列表 df_buffer = [] for file_path in Path("./json文件存储目录").rglob("*.json"): with open(file_path, "r", encoding="utf-8") as f: raw_data = json.load(f) # 解嵌套时直接指定需要的字段,减少内存占用 tmp_df = pd.json_normalize( raw_data, record_path="需要展开的顶层列表字段名", # 无对应字段可填None meta=TARGET_META, errors="ignore" ) # 高速展开列表列,假设需要展开的列名为list_column if "list_column" in tmp_df.columns: expand_df = pd.DataFrame(tmp_df["list_column"].tolist(), index=tmp_df.index) tmp_df = tmp_df.drop("list_column", axis=1).join(expand_df) df_buffer.append(tmp_df) # 单次拼接所有数据生成最终DataFrame final_df = pd.concat(df_buffer, ignore_index=True)
超大数据量的额外处理方案
如果总数据量超过内存上限,可以把每个处理完的小DataFrame直接写入parquet格式的中间文件,所有文件处理完后再用pandas或pyarrow读入所有parquet文件合并,避免内存溢出。
内容的提问来源于stack exchange,提问作者pariskey
相关产品推荐
相关产品推荐

