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

16GB内存下读取8GB大CSV至Pandas DataFrame遇内存错误求解

解决大CSV文件读取为Pandas DataFrame的内存问题

核心原因分析

直接用pd.concat合并分块数据仍触发内存错误,本质是所有分块最终会被同时加载到内存中,而Pandas DataFrame在内存中的占用量通常是原始CSV的2-5倍(尤其是字符串列),8GB CSV对应的内存需求可能超过16GB可用空间。NameError则是因为代码中的process是占位函数,需要自行实现处理逻辑。

解决方案步骤

1. 优先优化数据类型,大幅降低内存占用

这是最有效的前置操作,通过压缩数据类型减少单块数据的内存消耗:

  • 对字符串列:如果列的唯一值占比低(比如小于20%),转为category类型;
  • 对数值列:用更小的整数/浮点数类型替代默认的int64/float64;
  • 仅读取需要的列:通过usecols参数过滤无关列。

示例代码:

import pandas as pd
import gc

# 先读取少量样本探查列属性
sample_df = pd.read_csv(r'C:\folder\test.csv', sep=";", encoding="utf-8", decimal=",", nrows=1000)

# 优化数值列类型
def optimize_numeric_dtypes(df):
    for col in df.select_dtypes(include=['int64', 'float64']).columns:
        # 根据数值范围选择最小可用类型
        if df[col].dtype == 'int64':
            if df[col].min() >= 0 and df[col].max() <= 255:
                df[col] = df[col].astype('uint8')
            elif df[col].min() >= -128 and df[col].max() <= 127:
                df[col] = df[col].astype('int8')
            elif df[col].min() >= -32768 and df[col].max() <= 32767:
                df[col] = df[col].astype('int16')
        elif df[col].dtype == 'float64':
            # 若无高精度需求,转float32
            df[col] = df[col].astype('float32')
    return df

# 优化字符串列(基数低转category)
for col in sample_df.select_dtypes(include=['object']).columns:
    unique_ratio = sample_df[col].nunique() / len(sample_df)
    if unique_ratio < 0.2:
        sample_df[col] = sample_df[col].astype('category')

# 获取优化后的 dtype 映射
optimized_dtypes = sample_df.dtypes.to_dict()

2. 分块读取+高效格式暂存,避免一次性加载

将分块数据保存为内存效率更高的feather或parquet格式(比pkl更节省空间且读取更快),再逐步合并:

chunk_size = 500000  # 根据内存情况调整,建议比之前更小
chunk_files = []

# 分块读取并保存
for idx, chunk in enumerate(pd.read_csv(
    r'C:\folder\test.csv',
    sep=";",
    encoding="utf-8",
    decimal=",",
    dtype=optimized_dtypes,
    chunksize=chunk_size,
    usecols=list(optimized_dtypes.keys())  # 仅读取需要的列
)):
    # 再次优化当前分块的类型
    chunk = optimize_numeric_dtypes(chunk)
    # 保存为feather文件
    chunk_path = f'C:\\folder\\chunk_{idx}.feather'
    chunk.to_feather(chunk_path)
    chunk_files.append(chunk_path)
    # 及时释放内存
    del chunk
    gc.collect()

# 逐步合并feather文件,每次只加载一块到内存
df_list = []
for file in chunk_files:
    df_chunk = pd.read_feather(file)
    df_list.append(df_chunk)
    del df_chunk
    gc.collect()

# 最终合并为完整DataFrame
dfcompl = pd.concat(df_list, ignore_index=True)

3. 解决process未定义的问题

原代码中的process(chunk)是示例占位函数,若你需要在分块时做数据清洗/转换,可自行实现该函数,例如:

def process(chunk):
    # 示例:删除空值列、转换日期格式
    chunk = chunk.dropna(subset=['Column1'])
    chunk['DateColumn'] = pd.to_datetime(chunk['DateColumn'], format='%Y-%m-%d')
    return chunk

额外提示

  • 若合并后仍内存不足,可考虑按需处理:即不合并成完整DataFrame,而是基于分块文件进行逐块计算,最后汇总结果;
  • 关闭Pandas的low_memory参数(low_memory=False)可避免部分类型推断导致的内存波动,但需确保dtype已手动指定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 22:31:56