Python numpy文件操作技巧分享

 更新时间:2026年08月05日 09:53:53   作者:菜冻鱼  
还在纠结NumPy数组怎么存?本文带你搞懂npy、npz、CSV、memmap和HDF5的用法与区别,无论是单数组的极速读写,还是多数组压缩保存,甚至处理超出内存的超大文件,你都能找到最合适的NumPy文件格式方案,让数据加载又快又稳

概述

NumPy 提供了高效的二进制文件格式(.npy / .npz),读写速度远快于 CSV,且保留 dtype 和 shape 等元信息。

格式适用场景速度压缩
.npy单个数组极快
.npz多个数组极快可压缩
.csv / .txt与其他工具交互
memmap超大文件(>内存)按需

.npy— 单数组保存与加载 

import numpy as np

arr = 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、字节序等所有元信息,加载即原样。

.npz— 多数组保存与加载

未压缩版本

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')

文本格式(CSV / TXT)

np.loadtxt()— 加载简单文本

# 数据文件 data.txt:
# 1.0 2.0 3.0
# 4.0 5.0 6.0
# 7.0 8.0 9.0

data = 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)          # 最多读取行数

np.savetxt()— 保存文本

arr = np.random.rand(100, 5)

np.savetxt('output.csv', arr,
           delimiter=',',
           fmt='%.4f',                   # 格式: 4 位小数
           header='col1,col2,col3,col4,col5',
           comments='')                  # 表头前不加 #

np.genfromtxt()— 处理复杂文本 

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')])

内存映射(Memory-Mapped Files)

对于超大文件(>内存容量),使用 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()

memmap 模式

mode说明
'r'只读
'r+'读写(文件必须存在)
'w+'创建或覆盖,读写

memmap vs 普通加载

# 10GB 的数据集
# ❌ 普通加载:需要 10GB 内存
# arr = np.load('huge.npy')

# ✅ memmap:内存占用极小
arr = np.load('huge.npy', mmap_mode='r')   # 以 memmap 方式打开
print(arr[10000:10050])  # 只加载这几行

从标准 IO 读取

# 从字符串读取
import io

text = "1,2,3\n4,5,6\n7,8,9"
data = np.genfromtxt(io.StringIO(text), delimiter=',')
print(data)

# 从字节读取
binary_data = b"1.0 2.0\n3.0 4.0"
data = np.loadtxt(io.BytesIO(binary_data))

np.savez的懒加载

# npz 文件只在访问时才加载对应的数组(省内存)
data = np.load('dataset.npz')

# 此时只有元数据加载,实际数据还在磁盘
print(data.files)      # 列出键名

# 访问时才加载
X_train = data['X_train']   # 现在才从磁盘读取

# 用完后关闭(释放文件句柄)
# data.close()

HDF5 格式(大数据推荐)

对于 GB 以上的数据集,推荐使用 HDF5 格式(更灵活的分层存储):

# pip install h5py
import 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

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • python实现定时器的5种方法

    python实现定时器的5种方法

    本文主要介绍了python实现定时器的5种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • python爬虫xpath模块简介示例代码

    python爬虫xpath模块简介示例代码

    xpath是最常用且最便捷高效的一种解析方式,通用型强,其不仅可以用于python语言中,还可以用于其他语言中,数据解析建议首先xpath,这篇文章主要介绍了python爬虫xpath模块简介,需要的朋友可以参考下
    2023-02-02
  • python 批量将PPT导出成图片集的案例

    python 批量将PPT导出成图片集的案例

    这篇文章主要介绍了python 批量将PPT导出成图片集的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • 使用Python脚本实现批量网站存活检测遇到问题及解决方法

    使用Python脚本实现批量网站存活检测遇到问题及解决方法

    本文是小编自己编写的一个使用python实现批量网站存活检测。在项目测试中非常有用。本文给大家分享了遇到的问题及解决方案,非常不错,具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-10-10
  • Python实现批量修改指定目录下图片的大小

    Python实现批量修改指定目录下图片的大小

    批量修改指定目录下图片大小通常是在需要对大量图片进行统一处理的情况下使用的,本文主要为大家详细介绍了如何利用Python实现批量修改图片大小,需要的可以参考下
    2023-10-10
  • python请求域名requests.(url = 地址)报错

    python请求域名requests.(url = 地址)报错

    本文主要介绍了python请求域名requests.(url = 地址)报错,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Python字符串本身作为bytes进行解码的问题

    Python字符串本身作为bytes进行解码的问题

    这篇文章主要介绍了解决Python字符串本身作为bytes进行解码的问题,文末给大家补充介绍了,Python字符串如何转为bytes对象?Python字符串和bytes类型怎么互转,需要的朋友可以参考下
    2022-11-11
  • Python构建XML树结构的方法示例

    Python构建XML树结构的方法示例

    这篇文章主要介绍了Python构建XML树结构的方法,结合实例形式分析了Python创建与打印xml数结构的实现步骤与相关操作技巧,需要的朋友可以参考下
    2017-06-06
  • 学习python 的while循环嵌套

    学习python 的while循环嵌套

    这篇文章主要为大家介绍了python 的while循环嵌套,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • python SQLAlchemy 中的Engine详解

    python SQLAlchemy 中的Engine详解

    这篇文章主要介绍了python SQLAlchemy 中的Engine详解,Engine 翻译过来就是引擎的意思,汽车通过引擎来驱动,而 SQLAlchemy 是通过 Engine 来驱动,Engine 维护了一个连接池(Pool)对象和方言(Dialect),需要的朋友可以参考下
    2019-07-07

最新评论