如何在追加模式下使用numpy.save?大数据集读写问题
解决numpy.save不支持追加模式的问题
我太懂你这个困扰了——numpy.save确实没有追加模式,每次调用都会直接覆盖掉目标文件,这也是我当初处理大型批量数据集时踩过的坑之一。你代码里的循环执行三次np.save('myfile', Matrix),最后myfile.npy里只会保留第三次生成的5行矩阵,所以用[1:7]切片自然拿不到跨批次的正确数据。
下面给你几个实用的解决方案,根据你的数据集规模来选:
1. 用np.savez打包多批次数据(适合中等规模)
如果你的数据集还没大到吃满内存,可以先把所有批次的数组存到列表里,最后用np.savez一次性打包保存。这个方法简单直观,不需要额外依赖:
import numpy as np n = 5 dim = 5 batch_list = [] # 先收集所有批次数据 for _ in range(3): matrix = np.random.choice(np.arange(10, 40, dim), size=(n, dim)) batch_list.append(matrix) # 保存到npz文件(支持压缩版np.savez_compressed) np.savez('my_batches.npz', *batch_list) # 加载并拼接成完整矩阵 loaded_data = np.load('my_batches.npz') full_matrix = np.concatenate([loaded_data[f'arr_{i}'] for i in range(len(batch_list))]) # 现在可以正常切片了 M1 = full_matrix[1:7].copy() print(M1)
2. 用numpy.memmap动态写入(适合超大数据集)
如果数据大到没法一次性放进内存,可以用np.memmap创建一个可动态扩展的内存映射文件,分批写入数据。这样文件会直接存在磁盘上,不用占用太多内存:
import numpy as np n = 5 dim = 5 total_batches = 3 dtype = np.int64 # 初始化一个空的内存映射文件 fp = np.memmap('my_large_data.npy', dtype=dtype, mode='w+', shape=(0, dim)) for _ in range(total_batches): matrix = np.random.choice(np.arange(10, 40, dim), size=(n, dim)) # 扩展文件的行数 new_shape = (fp.shape[0] + n, dim) fp = np.memmap('my_large_data.npy', dtype=dtype, mode='r+', shape=new_shape) # 写入当前批次的数据到末尾 fp[-n:] = matrix # 关闭映射(删除变量触发) del fp # 加载时用mmap_mode='r'只读访问,支持切片 loaded_fp = np.load('my_large_data.npy', mmap_mode='r') M1 = loaded_fp[1:7].copy() print(M1)
3. 用HDF5格式(最推荐的大数据方案)
如果经常处理大型数据集,强烈推荐用HDF5格式(借助h5py库)。它天生支持追加写入、随机访问,还能分块存储,是处理海量数据的工业级方案:
首先得安装h5py:
pip install h5py
然后是示例代码:
import numpy as np import h5py n = 5 dim = 5 # 以追加模式打开HDF5文件 with h5py.File('my_hdf5_data.h5', 'a') as f: for _ in range(3): matrix = np.random.choice(np.arange(10, 40, dim), size=(n, dim)) if 'dataset' not in f: # 第一次创建可扩展的数据集,maxshape设为(None, dim)表示行数可无限扩展 dset = f.create_dataset('dataset', data=matrix, maxshape=(None, dim)) else: dset = f['dataset'] # 扩展数据集的行数 dset.resize(dset.shape[0] + n, axis=0) # 写入新批次数据到末尾 dset[-n:] = matrix # 加载时直接切片读取,不用加载整个数据集 with h5py.File('my_hdf5_data.h5', 'r') as f: M1 = f['dataset'][1:7][...].copy() print(M1)
总结一下:
- 小到中等规模数据:优先用
np.savez,简单省事 - 超大规模内存放不下:用
h5py,功能最强大、最灵活;memmap作为备选
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

