如何用Pandas仅加载指定列处理大CSV并输出全列?
优化Pandas读取超大CSV的方案:仅读取必需列
完全可以通过仅读取任务必需的列来大幅降低read_csv的耗时,这是处理超大CSV文件时最有效的优化手段之一。结合你的任务流程,我们可以分两种场景实现优化:
场景1:最终输出需要保留原CSV的所有列
如果你的结果需要完整保留原CSV的所有字段,直接只读部分列无法满足拼接需求,但可以分两个阶段处理,先快速完成筛选逻辑,再精准读取需要保留的行:
阶段1:轻量读取必要列,确定需保留的索引
仅读取索引列(primary_idx_list)和目标处理列(that_col),完成匹配、标记删除行的逻辑,记录需要保留的行索引:
# 定义必需列:索引列 + 目标处理列 required_cols = primary_idx_list + [that_col] # 仅读取必需列,大幅减少IO和内存开销 csv2_df_light = pd.read_csv( csv2, sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, dtype=str, keep_default_na=False, usecols=required_cols # 指定仅读取这些列 ) csv1_df_light = pd.read_csv( csv1, sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, dtype=str, keep_default_na=False, usecols=required_cols ) # 设置索引,用于行匹配 csv2_df_light.set_index(primary_idx_list, inplace=True, verify_integrity=verify_integrity) csv1_df_light.set_index(primary_idx_list, inplace=True, verify_integrity=verify_integrity) # 执行字段处理逻辑 def resolver(v1, v2): return '$Delete' if v1 == 'A' and v2 == 'B' else (v1 if v1 == 'A' and v2 == 'C' else (v2 if pd.notna(v2) else v1)) csv2_df_light[that_col] = csv1_df_light[that_col].combine(csv2_df_light[that_col], resolver) # 筛选需要保留的索引:csv1中未在csv2出现的行 + csv2中未标记删除的行 keep_csv1_idx = csv1_df_light.index[~csv1_df_light.index.isin(csv2_df_light.index)] keep_csv2_idx = csv2_df_light.index[csv2_df_light[that_col] != '$Delete']
阶段2:分块读取完整数据并筛选目标行
通过分块读取原CSV,只保留阶段1确定的索引行,避免一次性加载超大文件到内存:
# 定义分块读取并筛选的工具函数 def read_filtered_csv(file_path, keep_idx, idx_cols): chunks = [] # 分块读取,chunksize可根据内存调整 for chunk in pd.read_csv( file_path, sep='\x1D', engine='python', skiprows=1, skipfooter=1, header=0, dtype=str, keep_default_na=False, chunksize=10000 ): chunk.set_index(idx_cols, inplace=True) # 筛选当前块中需要保留的行 filtered_chunk = chunk.loc[chunk.index.isin(keep_idx)] chunks.append(filtered_chunk) return pd.concat(chunks) # 读取筛选后的完整数据 csv1_filtered = read_filtered_csv(csv1, keep_csv1_idx, primary_idx_list) csv2_filtered = read_filtered_csv(csv2, keep_csv2_idx, primary_idx_list) # 拼接并输出结果 result_df = pd.concat([csv1_filtered, csv2_filtered]) result_df.to_csv(...)
场景2:最终输出仅需保留索引列和目标列
如果你的结果不需要原CSV的全部字段,直接在阶段1结束后即可拼接输出,此时read_csv的耗时会降到最低:
# 拼接筛选后的轻量DataFrame result_light_df = pd.concat([csv1_df_light.loc[keep_csv1_idx], csv2_df_light.loc[keep_csv2_idx]]) result_light_df.to_csv(...)
额外优化建议
- 替换为C引擎:如果可以先通过命令行工具(如
sed)去掉首尾行,建议将engine='python'改为engine='c',C引擎的读取速度远快于Python引擎(注意C引擎不支持skipfooter参数)。 - 保持现有优化参数:你已经设置了
dtype=str和keep_default_na=False,这能避免Pandas自动推断数据类型的额外开销,继续保持。
内容的提问来源于stack exchange,提问作者SpaceyBot
相关产品推荐
相关产品推荐

