如何按月份自定义分块读取大CSV至Pandas DataFrame
按月份分块读取超大CSV文件
因为pd.read_csv()的chunksize参数仅支持固定行数分块,无法直接按时间规则(如月份)拆分,所以需要换一种思路:先定位每个月份对应的行索引范围,再逐范围读取数据。
步骤1:获取各月份对应的行索引范围
先分块读取时间戳列(内存占用远小于全量读取),记录每个年月对应的所有数据行索引,再整理出每个月份的起始/结束行位置:
import pandas as pd from collections import defaultdict # 配置参数,根据实际情况修改 CSV_PATH = "my_file.csv" TIME_COL_NAME = "timestamp" # 替换为你的时间戳列名 TEMP_CHUNK_SIZE = 1_000_000 # 临时分块大小,选内存可承受的最大值 # 存储每个年月对应的行索引 year_month_row_map = defaultdict(list) current_data_row = 0 # 记录当前处理到的全局数据行索引(从0开始,对应表头后的第一行) # 分块读取时间列,提取年月并记录行索引 for chunk in pd.read_csv( CSV_PATH, usecols=[TIME_COL_NAME], parse_dates=[TIME_COL_NAME], chunksize=TEMP_CHUNK_SIZE ): chunk["year_month"] = chunk[TIME_COL_NAME].dt.to_period("M") for ym, group in chunk.groupby("year_month"): # 计算当前块内该年月对应的全局行索引范围 start_in_chunk = group.index[0] end_in_chunk = group.index[-1] global_rows = range(current_data_row + start_in_chunk, current_data_row + end_in_chunk + 1) year_month_row_map[ym].extend(global_rows) current_data_row += len(chunk) # 整理成(年月,起始行索引,结束行索引)的列表,并按时间排序 month_ranges = [] for ym, rows in year_month_row_map.items(): month_ranges.append((ym, min(rows), max(rows))) month_ranges.sort(key=lambda x: x[0])
步骤2:按月份范围读取数据
根据第一步得到的行索引范围,用skiprows和nrows参数精准读取每个月份的完整数据块:
# 逐块读取并处理每个月份的数据 for ym, start_idx, end_idx in month_ranges: # 计算需要跳过的行数:表头1行 + 前面的start_idx条数据 skip_rows = 1 + start_idx if start_idx > 0 else 0 # 计算要读取的行数 read_rows = end_idx - start_idx + 1 # 读取当前月份的分块 month_chunk = pd.read_csv( CSV_PATH, skiprows=skip_rows, nrows=read_rows, parse_dates=[TIME_COL_NAME] ) # 这里替换为你的业务处理逻辑 print(f"处理 {ym} 数据,共 {len(month_chunk)} 行") # process_month_data(month_chunk)
注意事项
- 如果你的CSV没有表头,需要添加
header=None参数,并调整行索引的计算逻辑(比如无需跳过表头行)。 - 若读取时间列时仍有内存压力,可进一步调小
TEMP_CHUNK_SIZE。 dt.to_period("M")会自动区分跨年同月份(如2023-10和2024-10),避免分块混淆。
内容的提问来源于stack exchange,提问作者LostinSpatialAnalysis
相关产品推荐
相关产品推荐

