You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效将多份结构不一致的JSON文件转换为单个Pandas DataFrame?

处理多结构JSON文件生成Pandas DataFrame的优化方案

一、解决AttributeError: 'str' object has no attribute 'read'报错

这个错误本质是文件路径与文件对象的处理混淆:比如你给json.load()传了文件路径字符串(而非打开的文件对象),或者给pd.read_json()的参数类型不符合要求。

以下是正确的生成器处理逻辑,逐文件加载并转换为小DataFrame后yield:

import pandas as pd
import json
from pathlib import Path

def process_single_json(path):
    with open(path, 'r') as f:
        data = json.load(f)
    
    # 提取基础字段、受害者数据,遍历攻击者生成扁平行
    base_fields = {k: v for k, v in data.items() if k not in ['attackers', 'victim']}
    victim_flat = {f'victim_{k}': v for k, v in data['victim'].items()}
    
    rows = []
    for attacker in data['attackers']:
        attacker_flat = {f'attacker_{k}': v for k, v in attacker.items()}
        rows.append({**base_fields, **attacker_flat, **victim_flat})
    
    return pd.DataFrame(rows)

def json_file_generator(file_paths):
    for path in file_paths:
        yield process_single_json(path)

# 调用示例
file_list = list(Path('./your_json_dir').glob('*.json'))
final_df = pd.concat(json_file_generator(file_list), ignore_index=True)

二、性能优化方案对比

1. 生成器+逐文件处理(推荐中小数据量)

  • 优势:无需一次性加载所有文件到内存,pd.concat直接接收生成器,内存占用仅为单文件处理后的大小,避免二次复制所有数据。
  • 关键:不要先把所有小DataFrame存入列表再concat,直接将生成器传入pd.concat,减少内存开销。

2. JSONL中间文件方案(适合超大规模数据)

如果数据量远超内存,先将所有JSON转换为JSONL格式(每行对应一个攻击者+受害者的扁平数据),再分块读取:

import json
from pathlib import Path

def convert_to_jsonl(input_dir, output_path):
    with open(output_path, 'w') as out_f:
        for path in Path(input_dir).glob('*.json'):
            with open(path, 'r') as in_f:
                data = json.load(in_f)
            
            base_fields = {k: v for k, v in data.items() if k not in ['attackers', 'victim']}
            victim_flat = {f'victim_{k}': v for k, v in data['victim'].items()}
            
            for attacker in data['attackers']:
                attacker_flat = {f'attacker_{k}': v for k, v in attacker.items()}
                flat_row = {**base_fields, **attacker_flat, **victim_flat}
                out_f.write(json.dumps(flat_row) + '\n')

# 转换为JSONL
convert_to_jsonl('./your_json_dir', './output.jsonl')
# 分块读取JSONL
chunk_df = pd.read_json('./output.jsonl', lines=True, chunksize=10000)
final_df = pd.concat(chunk_df, ignore_index=True)
  • 优势:支持分块读取,彻底规避内存不足问题;后续读取无需再处理拆分逻辑。
  • 劣势:多一次磁盘IO操作,适合数据量极大的场景。

3. 替换apply(pd.Series)提升速度

原方案中apply(pd.Series)是性能瓶颈,用直接构造扁平字典的方式替代,能大幅提升处理速度(尤其是攻击者数量较多时),示例见第一部分的process_single_json函数。

三、总结

  • 中小数据量:优先用「生成器+扁平字典构造」方案,兼顾内存效率与处理速度。
  • 超大规模数据:先转JSONL再分块读取,彻底解决内存限制问题。
  • 生成器报错核心:确保文件读取时用open()获取文件对象,而非直接传路径字符串给解析函数。

内容的提问来源于stack exchange,提问作者Niko Lass

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 22:45:39