Pythonnumpy文件操作实用技巧分享的重点在于把前置条件、操作顺序和容易误判的地方分清楚。
NumPy 提供了高效的二进制文件格式(.npy / .npz),读写速度远快于 CSV,且保留 dtype 和 shape 等元信息。

| 格式 | 适用场景 | 速度 | 压缩 |
|---|---|---|---|
| .npy | 单个数组 | 极快 | 否 |
| .npz | 多个数组 | 极快 | 可压缩 |
| .csv / .txt | 与其他工具交互 | 慢 | 否 |
| memmap | 超大文件(>内存) | 按需 | 否 |
import numpy as nparr = np.arange(1000000).reshape(1000, 1000)# 保存np.save('data.npy', arr)# 文件大小 ≈ arr.nbytes + 128 字节(头信息)# 加载loaded = np.load('data.npy')print(loaded.shape) # (1000, 1000)print(loaded.dtype) # int32(保留原始类型)# 也可以用 savez 的 save 格式存储# 注意: np.load 返回的是 ndarray(对 .npy)或 NpzFile(对 .npz)优势:保留 shape、dtype、字节序等所有元信息,加载即原样。
train_data = np.random.rand(10000, 28, 28)train_labels = np.random.randint(0, 10, 10000)test_data = np.random.rand(2000, 28, 28)test_labels = np.random.randint(0, 10, 2000)# 保存多个数组(键值对)np.savez('dataset.npz', X_train=train_data, y_train=train_labels, X_test=test_data, y_test=test_labels)# 加载data = np.load('dataset.npz')# data 是 NpzFile 对象(类似字典,懒加载)print(data.files) # ['X_train', 'y_train', 'X_test', 'y_test']print(data['X_train'].shape) # (10000, 28, 28)print(data['y_train'].shape) # (10000,)# savez_compressed: 压缩存储(zip 压缩)np.savez_compressed('dataset_compressed.npz', X_train=train_data, y_train=train_labels, X_test=test_data, y_test=test_labels)# 加载方式相同data = np.load('dataset_compressed.npz')# 数据文件 data.txt:# 1.0 2.0 3.0# 4.0 5.0 6.0# 7.0 8.0 9.0data = np.loadtxt('data.txt')print(data)# [[1. 2. 3.]# [4. 5. 6.]# [7. 8. 9.]]# 常用参数data = np.loadtxt('data.csv', delimiter=',', # 分隔符 skiprows=1, # 跳过表头 dtype=np.float32, # 指定类型 usecols=(0, 2), # 只读第 0、2 列 max_rows=100) # 最多读取行数arr = np.random.rand(100, 5)np.savetxt('output.csv', arr, delimiter=',', fmt='%.4f', # 格式: 4 位小数 header='col1,col2,col3,col4,col5', comments='') # 表头前不加 #比 loadtxt 更强大:处理缺失值、混合类型、自动推断。
# 数据含缺失值(用 ? 或空白表示)data = np.genfromtxt('messy.csv', delimiter=',', dtype=None, # 自动推断类型 names=True, # 第 1 行作为列名 missing_values='?', # 缺失值标记 filling_values=0, # 缺失值填充为 0 encoding='utf-8')# 访问结构化数组的列print(data['column_name'])# 常用参数data = np.genfromtxt('data.csv', delimiter=',', skip_header=1, # 跳过的表头行数 skip_footer=1, # 跳过的尾部行数 usecols=(0, 1, 3), # 读取的列索引 dtype=[('name', 'U10'), ('age', 'i4'), ('score', 'f8')])对于超大文件(>内存容量),使用 memmap 按需加载,不会一次性读入内存。
# 1. 创建内存映射文件fp = np.memmap('large.dat', dtype='float32', mode='w+', shape=(100000, 1000))# 此时只分配了虚拟地址空间,不占物理内存# 像普通数组一样操作fp[0, :] = np.random.rand(1000).astype('float32')fp[1, :] = np.random.rand(1000).astype('float32')# 写入磁盘fp.flush() # 强制刷到磁盘del fp # 释放映射# 2. 加载已有的内存映射fp = np.memmap('large.dat', dtype='float32', mode='r', shape=(100000, 1000))# 只加载访问到的部分,不会把整个文件读入内存print(fp[0:10, :5]) # 硬盘只读这 10×5 的数据# 3. 就地修改fp = np.memmap('large.dat', dtype='float32', mode='r+')fp[0, 0] = 3.14 # 直接写入磁盘文件fp.flush()| mode | 说明 |
|---|---|
| 'r' | 只读 |
| 'r+' | 读写(文件必须存在) |
| 'w+' | 创建或覆盖,读写 |
# 10GB 的数据集# ❌ 普通加载:需要 10GB 内存# arr = np.load('huge.npy')# ✅ memmap:内存占用极小arr = np.load('huge.npy', mmap_mode='r') # 以 memmap 方式打开print(arr[10000:10050]) # 只加载这几行# 从字符串读取import iotext = "1,2,3n4,5,6n7,8,9"data = np.genfromtxt(io.StringIO(text), delimiter=',')print(data)# 从字节读取binary_data = b"1.0 2.0n3.0 4.0"data = np.loadtxt(io.BytesIO(binary_data))
# npz 文件只在访问时才加载对应的数组(省内存)data = np.load('dataset.npz')# 此时只有元数据加载,实际数据还在磁盘print(data.files) # 列出键名# 访问时才加载X_train = data['X_train'] # 现在才从磁盘读取# 用完后关闭(释放文件句柄)# data.close()对于 GB 以上的数据集,推荐使用 HDF5 格式(更灵活的分层存储):
# pip install h5pyimport h5py# 保存with h5py.File('dataset.h5', 'w') as f: f.create_dataset('images', data=images_array, compression='gzip') f.create_dataset('labels', data=labels_array, compression='gzip')# 加载(支持切片,不会全读入内存)with h5py.File('dataset.h5', 'r') as f: images = f['images'] print(images.shape) batch = images[0:32] # 只加载 32 张图| 场景 | 推荐格式 |
|---|---|
| 单个 NumPy 数组 | .npy |
| 多个 NumPy 数组 | .npz(压缩用 .npz zipped) |
| 与其他工具(Excel/R)共享 | .csv / .txt |
| 超大文件(>内存) | memmap 或 HDF5 |
| 深度学习训练 | .npy / .npz / HDF5 |
| 中等数据 + 可读性 | .csv |
| 需求 | 代码 |
|---|---|
| 保存单个数组 | np.save('a.npy', arr) |
| 加载单个数组 | np.load('a.npy') |
| 保存多个数组 | np.savez('a.npz', x=x, y=y) |
| 压缩保存 | np.savez_compressed('a.npz', x=x, y=y) |
| 简单文本加载 | np.loadtxt('a.txt') |
| 复杂文本加载 | np.genfromtxt('a.csv', delimiter=',') |
| 保存文本 | np.savetxt('a.csv', arr, delimiter=',') |
| 内存映射(创建) | np.memmap('f.dat', dtype='f4', mode='w+', shape=s) |
| 内存映射(加载) | np.load('f.npy', mmap_mode='r') |
| 强制刷盘 | fp.flush() |
| 列出 npz 键 | data.files |