如何优化Pandas读取大CSV文件速度并降低内存占用?
针对大型CSV读取优化与低内存适配的解决方案
一、优化read_csv读取速度
你的当前代码瓶颈主要来自engine='python'(多字符分隔符\x1D和skipfooter限制只能用Python引擎,而它比C引擎慢数倍),可从以下方向优化:
- 换用Polars库读取(优先推荐)
Polars原生支持多字符分隔符,读取速度远快于Pandas,且内存效率更高,同时支持直接跳过首尾行:
import polars as pl # 读取文件,跳过首行和末行,指定分隔符与全字符串类型 df = pl.read_csv( input_file, separator="\x1D", dtype=str, skip_rows=1, # 跳过首行 skip_footer=1, # 跳过末行 ignore_errors=True ) # 如需后续用Pandas处理,可转换格式 df_pd = df.to_pandas()
- 预处理文件后用轻量化方式读取
先用命令行工具(如sed)去掉首尾行,再用csv.reader处理多字符分隔符后转成DataFrame,速度比直接用Pandas Python引擎更快:
# 预处理:去掉第1行和最后1行,输出到临时文件 sed '1d;$d' input.csv > temp_cleaned.csv
import csv import pandas as pd with open('temp_cleaned.csv', 'r') as f: reader = csv.reader(f, delimiter='\x1D') header = next(reader) rows = list(reader) df = pd.DataFrame(rows, columns=header, dtype=str)
- 启用PyArrow后端优化字符串存储
如果必须用Pandas Python引擎,可开启dtype_backend='pyarrow'(需安装PyArrow库),用PyArrow的高效字符串类型替代默认的object类型,减少内存占用同时提升读取速度:
pd.read_csv( input_file, sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, dtype=str, keep_default_na=False, dtype_backend='pyarrow' )
二、低内存系统下的适配方案
- 用Polars替代Pandas
Polars采用列式存储,内存占用通常仅为Pandas的30%-50%,且支持高效的join操作(交集),无需全量加载数据到内存:
import polars as pl # 读取两个文件 df1 = pl.read_csv( "file1.csv", separator="\x1D", dtype=str, skip_rows=1, skip_footer=1 ) df2 = pl.read_csv( "file2.csv", separator="\x1D", dtype=str, skip_rows=1, skip_footer=1 ) # 基于交差列(示例为`key_col`)获取交集行 common_rows = df1.join(df2, on='key_col', how='inner') # 如需Pandas格式,可转换 common_rows_pd = common_rows.to_pandas()
- 利用SQLite数据库处理交集
将CSV分块导入内存数据库,通过SQL查询获取交集,无需全量加载数据到内存:
import sqlite3 import pandas as pd # 连接内存SQLite数据库 conn = sqlite3.connect(':memory:') chunk_size = 100000 # 分块导入第一个文件 for chunk in pd.read_csv( "file1.csv", sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, dtype=str, keep_default_na=False, chunksize=chunk_size ): chunk.to_sql('table1', conn, if_exists='append', index=False) # 分块导入第二个文件 for chunk in pd.read_csv( "file2.csv", sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, dtype=str, keep_default_na=False, chunksize=chunk_size ): chunk.to_sql('table2', conn, if_exists='append', index=False) # 查询交集(替换`key_col`为实际交差列) query = """ SELECT * FROM table1 INNER JOIN table2 ON table1.key_col = table2.key_col """ common_rows = pd.read_sql(query, conn) conn.close()
- 预计算交差列哈希,过滤后加载
先读取第一个文件的交差列生成哈希集合,再分块读取第二个文件时只保留在集合内的行,大幅减少内存占用:
import pandas as pd # 读取第一个文件的交差列(替换为实际交差列名) df1_keys = pd.read_csv( "file1.csv", sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, usecols=['key_col1', 'key_col2'], dtype=str, keep_default_na=False ) # 生成哈希集合(用元组作为唯一键) key_set = set(tuple(row) for row in df1_keys.values) # 定义过滤函数 def filter_chunk(chunk): # 生成每行的交差列元组 chunk['key_tuple'] = chunk[['key_col1', 'key_col2']].apply(tuple, axis=1) # 过滤出在集合内的行 filtered = chunk[chunk['key_tuple'].isin(key_set)].drop('key_tuple', axis=1) return filtered # 分块读取并过滤第二个文件 df2_filtered = pd.concat([ filter_chunk(chunk) for chunk in pd.read_csv( "file2.csv", sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, dtype=str, keep_default_na=False, chunksize=100000 ) ]) # 与第一个文件合并获取最终交集 common_rows = df1.merge(df2_filtered, on=['key_col1', 'key_col2'])
内容的提问来源于stack exchange,提问作者SpaceyBot
相关产品推荐
相关产品推荐

