如何使用numpy.load加载2GB级npy文件的特定行或列?
如何从大体积npy文件中仅加载特定行/列?
你说得对,numpy.load()本身确实没有直接只加载特定行或列的参数——它默认会把整个数组一次性读进内存,2GB的文件虽然能扛,但如果是更大的文件就会很头疼。不过有几个实用的办法能解决这个问题:
方法1:用np.memmap做内存映射(临时救急首选)
内存映射可以让你像操作普通numpy数组一样访问文件内容,但不会把整个文件加载到内存里,只有你实际访问的部分才会被读入。步骤很简单:
import numpy as np # 首先你需要知道原数组的形状和数据类型(可以先小范围加载或者查看原保存代码) # 比如假设你的数组是(100000, 2000)的float64类型 mmap_arr = np.memmap( 'your_large_array.npy', dtype=np.float64, mode='r', # 只读模式,避免误修改文件 shape=(100000, 2000) ) # 现在就可以像普通数组一样切片取特定行/列了 # 示例:取第50到100行,第10、20、30列 selected_data = mmap_arr[50:101, [10,20,30]].copy() # copy可选,把数据转成普通numpy数组 # 用完记得删除映射对象,释放资源 del mmap_arr
如果不知道原数组的形状和dtype,可以先读取npy文件的头部信息(不会加载整个数组):
import numpy as np with open('your_large_array.npy', 'rb') as f: # 读取npy文件的魔法头和数组元信息 version = np.lib.format.read_magic(f) shape, fortran_order, dtype = np.lib.format.read_array_header_1_0(f) print(f"数组形状:{shape},数据类型:{dtype}")
方法2:转存为HDF5格式(长期频繁访问首选)
如果以后经常需要随机读取特定行/列,把npy转成HDF5格式会更灵活——HDF5本身就是为大规模数据的高效存储和访问设计的,支持直接索引任意子集。需要用到h5py库(先安装:pip install h5py):
import h5py import numpy as np # 第一步:把npy转成HDF5(只需要做一次) large_arr = np.load('your_large_array.npy') with h5py.File('your_large_array.h5', 'w') as f: f.create_dataset('data', data=large_arr, compression='gzip') # 可选压缩,节省磁盘空间 # 之后每次读取特定行/列就很方便了 with h5py.File('your_large_array.h5', 'r') as f: # 示例1:取第100行所有列 row_100 = f['data'][100, :] # 示例2:取第0、5、10列的前200行 cols_subset = f['data'][:200, [0,5,10]] # 示例3:取任意索引的行(比如随机选的行号) random_rows = f['data'][[123, 456, 789], :]
方法3:手动计算偏移量(不推荐,仅应急)
如果上面的方法都用不了,你可以手动计算文件偏移量来读取特定行。原理是npy文件头部之后就是连续的数组数据,每行的字节数是每行元素数 * dtype.itemsize。但这个方法容易出错,比如要处理字节序、头部长度等细节问题,除非万不得已不建议用。
总结一下:如果只是偶尔读取特定子集,用np.memmap最快;如果长期需要频繁访问,转HDF5是更稳妥的方案。
内容的提问来源于stack exchange,提问作者Liwellyen




