大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
相关产品推荐
相关产品推荐

