
本文介绍使用pandas分块读取gb级csv文件(如2亿行),通过列名安全访问数据、计算列间比值/差值及行间变化量,并流式写入结果,避免内存溢出。
处理数百兆乃至数GB的CSV文件时,绝不能一次性加载到内存——这会导致MemoryError或系统卡死。正确做法是采用分块(chunking)+ 流式计算 + 迭代写入策略。以下是一个健壮、可扩展的完整解决方案。
✅ 正确做法:分块处理 + 列名索引 + 差分计算
首先明确关键修正点:
- for row in chunk: 遍历的是列名(str),不是行数据 → 应改用 .iterrows() 或向量化操作;
- pd.write_csv() 不存在 → 正确方法是 chunk.to_csv(..., mode='a', header=False);
- 行间差值(如 width_diff = current['Width'] - previous['Width'])需保存上一块的末行,或使用 .diff()(推荐);
- 对于超大数据,优先使用向量化运算(快且内存友好),避免逐行循环。
✅ 推荐实现(含列计算 + 行差分 + 增量保存)
import pandas as pd
file_in = r"B:\Users\user\Documents\huge-dataset.csv"
file_out = r"B:\Users\user\Documents\aggregate.csv"
# 第一次写入时保留表头,后续追加不写表头
first_chunk = True
for chunk in pd.read_csv(file_in, chunksize=100_000):
# ✅ 使用列名安全计算(自动广播,无需循环)
chunk['ratio'] = chunk['Width'] / chunk['Length'] # 避免除零?可加 fillna 或 clip
chunk['width_length_diff'] = chunk['Width'] - chunk['Length']
# ✅ 行间差分:当前行 Width 减前一行 Width(首行为 NaN)
chunk['width_diff_from_prev'] = chunk['Width'].diff()
# ✅ 可选:跨块连续差分(若需全局时序连续性)
# 需在循环外维护 prev_last_width,此处为简化省略;多数场景 .diff() 已满足需求
# ✅ 流式写入:mode='a' 追加,header=first_chunk 控制仅首块写表头
chunk[['DateTime', 'ratio', 'width_length_diff', 'width_diff_from_prev']].to_csv(
file_out,
mode='a',
header=first_chunk,
index=False
)
first_chunk = False
print(f"✅ 处理完成,结果已保存至 {file_out}")⚠️ 注意事项与最佳实践
- 避免 .iterrows():它返回 (index, Series),速度慢且破坏向量化优势;99% 场景用直接列运算(如 chunk['A'] + chunk['B'])即可。
-
空值与异常处理:
chunk['ratio'] = (chunk['Width'] / chunk['Length']).replace([float('inf'), -float('inf')], float('nan')) -
内存优化技巧:
- 指定 dtype(如 dtype={'Count': 'uint32', 'Age': 'uint8'})减少内存占用;
- 使用 usecols=['DateTime','Width','Length'] 仅读取必要列;
- 对 DateTime 列添加 parse_dates=['DateTime'] 并设 infer_datetime_format=True 加速解析。
- 行间依赖进阶:若需严格跨块的“上一行”(如累计差分),可在每块处理前保存上一块末行值,并在当前块首行手动计算差值,再调用 .diff() 处理剩余行。
✅ 总结
面对超大CSV,核心原则是:向量化 > 迭代,分块 > 全量,流式写入 > 内存暂存。利用 pandas.read_csv(chunksize=...) + 列名索引 + .diff() + to_csv(mode='a') 四步组合,即可安全、高效完成列运算与行间分析,全程内存可控,代码简洁可靠。










