pandas使用chunksize读取大文件时如何直接跳转到指定chunk处理
解决方案
你遇到的耗时本质是pandas迭代遍历前499个chunk时,会将所有行解析为DataFrame对象,哪怕你没有用到这些数据也会产生大量解析开销。pandas原生没有提供直接切片跳转到指定chunk的能力,因为CSV是无固定偏移索引的文本格式,无法直接计算第N个chunk的字节位置,以下是三种可行的解决方案:
方案1:预生成行偏移索引(最优,一次生成永久使用)
首次读取文件时生成每个chunk对应的字节偏移量索引并存储,后续读取指定chunk时可以直接通过文件指针跳转定位,完全跳过前面行的解析开销,速度最快。
第一步:生成偏移量索引(仅需执行一次)
import pandas as pd import pickle chunk_size = 100000 file_path = "/path/to/file/file.TXT" offset_index = {} with open(file_path, "rb") as f: # 读取表头 header = f.readline() # 第1个chunk对应索引0的起始偏移 offset_index[0] = f.tell() chunk_idx = 1 line_count = 0 while line := f.readline(): line_count += 1 if line_count == chunk_size: offset_index[chunk_idx] = f.tell() chunk_idx += 1 line_count = 0 # 存储索引和表头信息 with open("file_offset_index.pkl", "wb") as f: pickle.dump((offset_index, header), f)
第二步:读取指定范围chunk
import pandas as pd import pickle chunk_size = 100000 file_path = "/path/to/file/file.TXT" sep = "," # 替换为你实际的文件分隔符 # 加载预存的索引 with open("file_offset_index.pkl", "rb") as f: offset_index, header = pickle.load(f) header_cols = header.decode().strip().split(sep) # 遍历需要的第500到560个chunk(注意索引从0开始的话对应499到559,按需调整) for chunk_idx in range(499, 560): with open(file_path, "rb") as f: # 跳转到对应chunk的起始字节位置 f.seek(offset_index[chunk_idx]) # 只读当前chunk的行数 df = pd.read_csv(f, nrows=chunk_size, header=None, sep=sep, low_memory=False) df.columns = header_cols # 在此处执行业务逻辑
方案2:使用skiprows跳过前N行(无需预生成索引,速度中等)
如果不想预生成索引,可以直接通过skiprows参数跳过前面499个chunk的所有行,pandas会直接从指定行开始解析,内部的行计数是纯字节扫描,远快于解析为DataFrame的开销,比你原有遍历的方式快很多。
import pandas as pd chunk_size = 100000 # 跳过前499个chunk的行数,如有表头需注意调整偏移量,可先用小文件测试参数 skip_rows = 499 * chunk_size # 只读需要的60个chunk的总行数 read_rows = 60 * chunk_size df_iter = pd.read_csv( "/path/to/file/file.TXT", chunksize=chunk_size, low_memory=False, skiprows=skip_rows, nrows=read_rows ) for df_ia in df_iter: # 直接获取到第500到560个chunk的内容,无需判断索引 # 在此处执行业务逻辑
方案3:使用itertools.islice简化写法(仅简化代码,速度无提升)
如果接受原有遍历速度,只是想要类似切片的简洁写法,可以用itertools.islice对迭代器做切片,本质还是会遍历前面的499个chunk并丢弃,速度和你原有代码一致。
import pandas as pd from itertools import islice chunk_iter = pd.read_csv( "/path/to/file/file.TXT", chunksize=100000, iterator=True, low_memory=False ) # 切片取第499到559索引对应的chunk,即你需要的第500到560个chunk for df_ia in islice(chunk_iter, 499, 560): # 在此处执行业务逻辑
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

