使用NumPy读取百万行级超大文件提取第一列小于20000数值的问题
大文件数值提取的优化实现
现有代码的异常原因
- 全量内存加载问题:
np.loadtxt会一次性将整个文件内容读入内存,超百万行的文本文件哪怕只取第一列,也会因为内存占用过高触发MemoryError异常 - 语法错误:判断条件中写的
20,000不符合Python语法规则,代码运行时会直接抛出语法错误,Python书写数值不能直接插入千位分隔符
可行的解决方案
方案1:逐行流式读取(适配任意大小文件,内存占用极低)
不需要借助numpy全量加载,直接逐行遍历文件内容,在读取过程中完成值过滤:
import numpy as np filtered_result = [] # 以只读模式逐行打开文件,不会一次性加载全量内容 with open("./muon.txt", "r") as file_handle: for line in file_handle: # 拆分每行内容,仅提取第一列转成整数 col1_value = int(line.strip().split()[0]) if col1_value < 20000: filtered_result.append(col1_value) # 转成numpy数组供后续计算使用 final_array = np.array(filtered_result, dtype=np.int32)
这个方案的内存占用基本和文件大小无关,哪怕是数GB级的超大文件也能正常运行。
方案2:numpy分块读取(保留numpy的处理效率)
如果需要沿用numpy的向量化处理能力,可以通过分块循环读取的方式,每读一小块数据就立刻做过滤,避免全量数据占满内存:
import numpy as np filtered_chunks = [] chunk_line_count = 10000 # 单次读取的行数,可根据可用内存调整大小 offset = 0 # 已经读过的行数,作为下次读取的跳过值 while True: try: # 每次仅读取指定行数的内容,跳过之前已经读过的部分 chunk = np.loadtxt( "./muon.txt", usecols=0, skiprows=offset, max_rows=chunk_line_count, dtype=np.int32 # 明确指定整型类型,比默认浮点类型节省一半内存 ) # 在当前块内完成值过滤,不需要的数据直接丢弃 filtered_part = chunk[chunk < 20000] filtered_chunks.append(filtered_part) offset += chunk_line_count except StopIteration: # 读到文件末尾时退出循环 break # 合并所有过滤后的块为最终数组 final_array = np.concatenate(filtered_chunks)
实现注意点
- 读取时直接通过
usecols参数跳过第二列,不要把不需要的列加载进内存 - 明确指定数据类型,整数列用
np.int32存储,比numpy默认的float64类型内存占用低75% - 不要等全量文件读完再做值过滤,在读取过程中逐块筛选不需要的数值,减少冗余内存占用
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

