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

大CSV含float列表列,json.loads处理后内存暴涨问题求助

解决大CSV解析float列表内存暴增的问题

这问题我之前处理过类似的,核心原因是Python原生float对象和列表的内存开销远大于紧凑的数值类型数组——单个Python float要占~28字节,而numpy的float64只需要8字节,再加上列表本身的对象开销,解析后内存直接暴涨是必然的。结合你的场景,给你几个能快速见效的方案:

1. 解析时直接转成numpy数组,替代Python列表

把原本解析成Python list的操作改成转成numpy数组,这是最立竿见影的优化。修改你的预处理逻辑:

import numpy as np
import json

def parse_to_numpy(s):
    # 直接解析为numpy float64数组,比Python list省70%+内存
    return np.array(json.loads(s), dtype=np.float64)

# 用converters参数在读取时直接处理
df = pd.read_csv('your_large_file.csv', converters={'float_nums': parse_to_numpy})

# 或者修改你的preprocess函数
def preprocess(df):
    df['float_nums'] = df['float_nums'].apply(parse_to_numpy)

这样每个float_nums列的元素是numpy数组,内存占用会直接降到原来的1/3甚至更低。

2. 分块读取处理,避免一次性加载全量数据

如果文件大到单块加载都撑不住,用pandas的chunksize参数分块读取,处理一块就保存一块,释放内存后再处理下一块:

import gc
import os
chunk_size = 10000  # 根据你的内存情况调整,比如1万行一块
output_path = 'processed_chunks/'

# 确保输出目录存在
os.makedirs(output_path, exist_ok=True)

for idx, chunk in enumerate(pd.read_csv('your_large_file.csv', chunksize=chunk_size)):
    # 解析并转成numpy数组
    chunk['float_nums'] = chunk['float_nums'].apply(parse_to_numpy)
    # 保存为Parquet格式(比CSV高效N倍)
    chunk.to_parquet(f'{output_path}chunk_{idx}.parquet', compression='snappy')
    # 手动删除引用并触发垃圾回收
    del chunk
    gc.collect()

处理完所有块后,如果需要合并,可以用pd.read_parquet批量读取后拼接:

import glob
parquet_files = glob.glob(f'{output_path}*.parquet')
df = pd.concat([pd.read_parquet(f) for f in parquet_files], ignore_index=True)

3. 永久转换为Parquet存储,从根源解决内存问题

CSV本身是文本格式,存储数值列表效率极低,处理完后把数据转成Parquet格式——它是列存储、支持压缩,还能直接保留numpy数组的紧凑格式,下次读取时内存占用会大幅降低,速度也更快:

# 处理完后保存
df.to_parquet('final_processed_data.parquet', compression='snappy')

# 后续读取时直接加载,内存占用会比CSV解析后小很多
df = pd.read_parquet('final_processed_data.parquet')

4. 极端场景:用Dask处理超大规模数据

如果数据已经大到单台机器内存完全扛不住,试试用Dask替代Pandas——它能自动分块并行处理,不需要把全量数据加载到内存:

import dask.dataframe as dd

ddf = dd.read_csv('your_large_file.csv', converters={'float_nums': parse_to_numpy})
# 处理逻辑和Pandas几乎一致,比如过滤、计算等
ddf = ddf[ddf['some_column'] > 0]
# 保存为Parquet
ddf.to_parquet('dask_processed_data.parquet', compression='snappy')

这些方法组合起来,应该能把你的内存占用从170GB降到几十GB甚至更低,优先试试前两个方案,见效最快。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:18:10