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

如何将38GB超大JSON文件转换为DataFrame并避免内存错误?

38GB超大JSON转Pandas DataFrame解决内存错误方案

我有一个38GB的超大JSON文件,结构如下:

{
  "Text": [
    {
      "a": 6,
      "b": 2022,
      "c": 11,
      "d": "2022-11-24",
      "e": "567",
      "f": "ww",
      "i": "00",
      "j": 4,
      "k": "y",
      "l": null,
      "m": 3,
      "n": 7,
      "o": "54",
      "b": null,
      "q": "yes",
      "r": 77,
      "c": "yes",
      "t": 6,
      "y": 8,
      "v": "yy",
      "w": "yy",
      "x": "o",
      "y": "100                                                                                                                          ",
      "z": "r"
    },
    {...},
    {...}
  ]
}

我尝试用以下代码转换为Pandas DataFrame,但运行时出现内存错误:

df=pd.DataFrame([])
with open('data.json',encoding='utf-8-sig') as f:
    l=f.read()
    c=json.loads(l)
    v=list(c.keys())[0]
    data=(c[v])

    for line in itertools.islice(data,2):
        json_nor=json_normalize(line)
        df=df.append(json_nor, ignore_index = True)

解决方法

1. 流式解析JSON,避免一次性加载全量数据

你的代码直接把38GB文件全部读入内存,必然触发内存错误。可以用ijson库流式读取JSON数组中的每个对象,分批次处理:

import ijson
import pandas as pd
from pandas import json_normalize

# 先收集小DataFrame列表,最后一次性合并
df_list = []
with open('data.json', encoding='utf-8-sig') as f:
    # 定位到Text数组下的每个元素
    objects = ijson.items(f, 'Text.item')
    for obj in objects:
        df_list.append(json_normalize(obj))

# 合并所有小DataFrame
df = pd.concat(df_list, ignore_index=True)

如果内存依然紧张,可以每处理固定数量的对象就保存到磁盘,避免内存堆积:

import ijson
import pandas as pd
from pandas import json_normalize

chunk_size = 10000
chunk_count = 0
df_list = []

with open('data.json', encoding='utf-8-sig') as f:
    objects = ijson.items(f, 'Text.item')
    for idx, obj in enumerate(objects):
        df_list.append(json_normalize(obj))
        # 每10000条数据保存一次
        if (idx + 1) % chunk_size == 0:
            chunk_count += 1
            pd.concat(df_list, ignore_index=True).to_csv(f'chunk_{chunk_count}.csv', index=False)
            df_list = []  # 清空列表释放内存
    # 处理剩余的未达批量的数据
    if df_list:
        chunk_count += 1
        pd.concat(df_list, ignore_index=True).to_csv(f'chunk_{chunk_count}.csv', index=False)

# 合并所有分块CSV
df = pd.concat([pd.read_csv(f'chunk_{i}.csv') for i in range(1, chunk_count+1)], ignore_index=True)

2. 提前指定数据类型,压缩内存占用

Pandas自动推断数据类型可能造成内存浪费,提前为字段指定更紧凑的类型:

dtype_spec = {
    'a': 'int8',
    'b': 'Int32',  # 用Nullable类型处理null值
    'c': 'category',  # 重复值多的字符串用category类型
    'd': 'datetime64[ns]',
    'e': 'int16',
    # 其他字段根据实际值范围和类型指定
}

# 合并时指定类型
df = pd.concat(df_list, ignore_index=True, dtype=dtype_spec)
# 读取CSV时也可指定
df = pd.read_csv('chunk_1.csv', dtype=dtype_spec, parse_dates=['d'])

3. 替换低效的df.append(),改用pd.concat()

df.append()会频繁复制数据,效率极低。改用列表收集小DataFrame后一次性pd.concat(),能大幅降低内存开销和运行时间。

4. 用Dask处理超大规模数据

如果单进程Pandas仍无法处理,可以用Dask DataFrame,它支持并行分块处理,语法和Pandas兼容:

import dask.dataframe as dd
from dask import delayed
import ijson

@delayed
def process_chunk(chunk):
    return json_normalize(chunk)

chunks = []
current_chunk = []
chunk_size = 10000

with open('data.json', encoding='utf-8-sig') as f:
    objects = ijson.items(f, 'Text.item')
    for idx, obj in enumerate(objects):
        current_chunk.append(obj)
        if (idx + 1) % chunk_size == 0:
            chunks.append(process_chunk(current_chunk))
            current_chunk = []
    if current_chunk:
        chunks.append(process_chunk(current_chunk))

# 构建Dask DataFrame
dask_df = dd.from_delayed(chunks)
# 直接导出到分块CSV
dask_df.to_csv('dask_output_*.csv', index=False)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:00:48