解决Pandas读取4GB大型CSV文件筛选行时出现MemoryError的问题
解决Pandas处理4GB CSV时的MemoryError问题
这个问题非常常见——Pandas默认会把整个CSV文件加载到内存中,4GB的文件显然会超出普通机器的内存容量。下面给你几个针对性的解决方案,你可以根据自己的需求选择:
1. 分块读取处理(最易上手的Pandas原生方案)
通过read_csv的chunksize参数,把大文件拆成小块逐次处理,每次只加载部分数据到内存,处理完就写入结果文件。
import pandas as pd # 定义要排除的城市 communes_to_exclude = ["PERPIGNAN"] output_file = "filtered_stock_etablissement.csv" # 每次读取10000行(可根据你的内存情况调整这个数值) chunk_size = 10000 for chunk_idx, chunk in enumerate(pd.read_csv( r"C:StockEtablissement_utf8(1)\StockEtablissement_utf8.csv", sep=",", chunksize=chunk_size )): # 过滤掉目标城市的行 filtered_chunk = chunk[~chunk["libelleCommuneEtablissement"].isin(communes_to_exclude)] # 第一块写入时创建文件并写表头,后续块只追加数据 if chunk_idx == 0: filtered_chunk.to_csv(output_file, index=False, mode="w") else: filtered_chunk.to_csv(output_file, index=False, mode="a", header=False) print(f"已处理第 {chunk_idx+1} 块数据")
优势:完全沿用你熟悉的Pandas语法,不需要额外学习新工具,内存占用可控。
2. 手动指定数据类型减少内存占用
Pandas自动推断的数据类型往往比较“冗余”(比如把字符串列设为object,把小数值设为int64),手动指定更高效的类型能大幅降低内存消耗。
步骤:
- 先读取一小部分数据查看列类型:
sample_df = pd.read_csv( r"C:StockEtablissement_utf8(1)\StockEtablissement_utf8.csv", sep=",", nrows=1000 ) print(sample_df.dtypes)
- 根据输出结果,为列指定更节省内存的类型:
dtype_config = { # 重复值多的字符串列用category类型,内存占用可降至原来的1/10甚至更低 "libelleCommuneEtablissement": "category", # 数值列根据实际范围调整,比如用int32代替int64(如果数值没超过2^31-1) "some_numeric_column": "int32", # 其他列同理调整... } # 用指定类型读取文件(如果优化后内存足够容纳整个文件) df = pd.read_csv( r"C:StockEtablissement_utf8(1)\StockEtablissement_utf8.csv", sep=",", dtype=dtype_config ) filtered_df = df[~df["libelleCommuneEtablissement"].isin(communes_to_exclude)] filtered_df.to_csv("filtered_output.csv", index=False)
优势:如果优化后内存能容纳整个文件,处理速度会比分块快很多。
3. 使用Python内置csv模块(内存占用最低)
如果只是简单的行过滤操作,完全不需要用Pandas,直接用Python原生的csv模块逐行处理,内存占用几乎可以忽略。
import csv communes_to_exclude = {"PERPIGNAN"} # 用集合做查找,速度比列表快 input_path = r"C:StockEtablissement_utf8(1)\StockEtablissement_utf8.csv" output_path = "filtered_stock_etablissement.csv" with open(input_path, "r", encoding="utf-8") as infile, open(output_path, "w", encoding="utf-8", newline="") as outfile: # 按字典格式读取每一行 reader = csv.DictReader(infile, delimiter=",") writer = csv.DictWriter(outfile, fieldnames=reader.fieldnames) # 写入表头 writer.writeheader() # 逐行过滤并写入 for row in reader: if row["libelleCommuneEtablissement"] not in communes_to_exclude: writer.writerow(row)
优势:内存占用极低,适合处理超大文件,且不需要安装额外依赖。
4. 使用Dask DataFrame(适合复杂Pandas操作)
如果你除了过滤还需要做更多Pandas风格的数据分析,可以用Dask——它是专门处理超大数据集的工具,API和Pandas几乎一致,会自动分块并行处理。
import dask.dataframe as dd communes_to_exclude = ["PERPIGNAN"] # 读取文件,Dask自动拆分数据块 ddf = dd.read_csv( r"C:StockEtablissement_utf8(1)\StockEtablissement_utf8.csv", sep="," ) # 执行过滤操作(Dask会延迟计算,直到调用to_csv才真正执行) filtered_ddf = ddf[~ddf["libelleCommuneEtablissement"].isin(communes_to_exclude)] # 保存结果为单个CSV文件 filtered_ddf.to_csv("filtered_dask_output.csv", single_file=True, index=False)
优势:支持几乎所有Pandas的操作,能处理远超内存的数据集,还能利用多核CPU加速。
内容的提问来源于stack exchange,提问作者Daniel Pochoclin Rouffart
相关产品推荐
相关产品推荐

