Skip to content

NumPy - 文件 I/O

NumPy 提供了将 ndarray 对象(NumPy 数组)保存到磁盘并将其重新加载到内存中的函数。这对于持久化结果、共享数据或处理大于可用内存的数据集至关重要。

主要的输入/输出函数有:

  • np.save() 和 np.load(): 处理 NumPy 的原生二进制文件格式(.npy)。高效地存储单个 NumPy 数组。
  • np.savez() 和 np.load(): 处理 NumPy 的归档格式(.npz),可以在一个文件中存储多个数组(未压缩)。
  • np.savez_compressed() 和 np.load(): 类似于 savez,但将多个数组保存在压缩的 .npz 归档文件中。适用于大型数组。
  • np.savetxt() 和 np.loadtxt(): 处理纯文本文件(例如,.txt,.csv,即逗号分隔值文件)。人类可读,但效率较低,且可能会丢失精度。
  • np.genfromtxt(): 一个更强大的函数,用于读取结构化文本文件,能够处理缺失值。

NumPy 的 .npy 格式是标准的方式,用于将一个单个 NumPy 数组保存到文件。它存储数据、形状 (shape)、数据类型 (dtype) 和其他元数据 (metadata),以便即使在不同的机器上也能准确地重建数组。

将单个数组保存到磁盘文件,自动添加 .npy 扩展名(如果未指定)。

import numpy as np
a = np.array([1, 2, 3, 4, 5])
filename = 'my_array.npy' # Explicitly add .npy is good practice
np.save(filename, a)
print(f"Array saved to {filename}")

从 .npy 或 .npz 文件加载数组。

import numpy as np
filename = 'my_array.npy'
try:
b = np.load(filename)
print(f"Array loaded from {filename}:")
print(b)
print(f"Data type: {b.dtype}")
except FileNotFoundError:
print(f"Error: File '{filename}' not found. Please run the save example first.")

输出(如果 my_array.npy 存在):

Array saved to my_array.npy
Array loaded from my_array.npy:
[1 2 3 4 5]
Data type: int64

np.save() 和 np.load() 函数有一个 allow_pickle 参数。默认情况下(自 NumPy 1.16.3 起 allow_pickle=False),出于安全原因,加载 pickle 过的对象是禁用的,因为从不受信任的来源加载 pickle 数据可能执行任意代码。仅在信任文件来源时才将 allow_pickle 设置为 True。

要将多个数组保存到单个文件,请使用 np.savez() 或 np.savez_compressed()。

import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.arange(5)
archive_filename = 'my_archive.npz'
# Save arrays, assigning names ('arr1', 'arr2') within the archive
np.savez(archive_filename, arr1=a, arr2=b)
print(f"Multiple arrays saved to {archive_filename}")
# Load the archive
data = np.load(archive_filename)
print("\nArrays loaded from archive:")
print(f"Array 'arr1':\n{data['arr1']}")
print(f"Array 'arr2':\n{data['arr2']}")
# Check the files contained in the archive
print(f"\nFiles in archive: {data.files}")
data.close() # Good practice to close the file object

输出:

Multiple arrays saved to my_archive.npz
Arrays loaded from archive:
Array 'arr1':
[[1 2]
[3 4]]
Array 'arr2':
[0 1 2 3 4]
Files in archive: ['arr1', 'arr2']

np.savez_compressed() 的工作方式相同,但使用压缩,从而生成更小的文件,代价是保存/加载时间稍慢。

np.savetxt() 和 np.loadtxt() 用于以纯文本格式存储和检索数组数据。这对于与非 Python 软件(如电子表格)进行互操作或进行人工检查很有用,但效率低于二进制格式。

import numpy as np
a = np.array([[1, 2.5, 3.1], [4.0, 5.6, 6.9]])
text_filename = 'my_text_data.csv'
# Save the array to a CSV file, specifying format and delimiter
np.savetxt(text_filename, a, fmt='%.2f', delimiter=',', header='col1,col2,col3')
print(f"Array saved to {text_filename}")
# Load the array back from the text file
# We need to skip the header row
b = np.loadtxt(text_filename, delimiter=',', skiprows=1)
print(f"\nArray loaded from {text_filename}:")
print(b)
print(f"Data type: {b.dtype}")

输出:

Array saved to my_text_data.csv
Array loaded from my_text_data.csv:
[[1. 2.5 3.1]
[4. 5.6 6.9]]
Data type: float64

savetxt 和 loadtxt 提供了诸如 delimiter(分隔符)、fmt(格式说明符)、header(头部)、footer(尾部)、comments(注释)和 skiprows(跳过的行数)等参数,用于自定义输出和输入解析。

对于更复杂的文本文件,特别是包含缺失值的文本文件,考虑使用 np.genfromtxt(),它在处理错误和填充缺失数据方面提供了更大的灵活性。

  • .npy: 最适合快速准确地保存/加载单个 NumPy 数组。是 NumPy 之间数据交换的标准格式。
  • .npz: 适合将多个相关数组捆绑到一个文件。
  • .npz (压缩): 当文件大小是主要考虑因素且压缩开销可以接受时使用。
  • .txt/.csv: 最适合人类阅读、与非 Python 工具(如电子表格)共享数据,或需要纯文本时使用。注意浮点数潜在的精度损失。