读取和写入文件#
此页面介绍了常见的应用程序;有关 I/O 例程的完整集合,请参阅 输入和输出.
读取文本和 CSV 文件#
无缺失值#
使用 numpy.loadtxt
.
有缺失值#
使用 numpy.genfromtxt
.
返回一个 掩码数组 **掩盖缺失值**(如果
usemask=True
),或者**用在
filling_values
中指定的**值填充缺失值(默认为浮点数的np.nan
,整数的 -1)。
使用非空白分隔符#
>>> with open("csv.txt", "r") as f:
... print(f.read())
1, 2, 3
4,, 6
7, 8, 9
掩码数组输出#
>>> np.genfromtxt("csv.txt", delimiter=",", usemask=True)
masked_array(
data=[[1.0, 2.0, 3.0],
[4.0, --, 6.0],
[7.0, 8.0, 9.0]],
mask=[[False, False, False],
[False, True, False],
[False, False, False]],
fill_value=1e+20)
数组输出#
>>> np.genfromtxt("csv.txt", delimiter=",")
array([[ 1., 2., 3.],
[ 4., nan, 6.],
[ 7., 8., 9.]])
数组输出,指定填充值#
>>> np.genfromtxt("csv.txt", delimiter=",", dtype=np.int8, filling_values=99)
array([[ 1, 2, 3],
[ 4, 99, 6],
[ 7, 8, 9]], dtype=int8)
空白分隔#
numpy.genfromtxt
也可以解析具有缺失值的空白分隔数据文件,如果
**每个字段具有固定宽度**:将宽度用作 delimiter 参数。
# File with width=4. The data does not have to be justified (for example, # the 2 in row 1), the last column can be less than width (for example, the 6 # in row 2), and no delimiting character is required (for instance 8888 and 9 # in row 3) >>> with open("fixedwidth.txt", "r") as f: ... data = (f.read()) >>> print(data) 1 2 3 44 6 7 88889 # Showing spaces as ^ >>> print(data.replace(" ","^")) 1^^^2^^^^^^3 44^^^^^^6 7^^^88889 >>> np.genfromtxt("fixedwidth.txt", delimiter=4) array([[1.000e+00, 2.000e+00, 3.000e+00], [4.400e+01, nan, 6.000e+00], [7.000e+00, 8.888e+03, 9.000e+00]])
**一个特殊的值(例如“x”)表示缺失的字段**:将其用作 missing_values 参数。
>>> with open("nan.txt", "r") as f: ... print(f.read()) 1 2 3 44 x 6 7 8888 9
>>> np.genfromtxt("nan.txt", missing_values="x") array([[1.000e+00, 2.000e+00, 3.000e+00], [4.400e+01, nan, 6.000e+00], [7.000e+00, 8.888e+03, 9.000e+00]])
**您想跳过具有缺失值的**行:设置 invalid_raise=False。
>>> with open("skip.txt", "r") as f: ... print(f.read()) 1 2 3 44 6 7 888 9
>>> np.genfromtxt("skip.txt", invalid_raise=False) __main__:1: ConversionWarning: Some errors were detected ! Line #2 (got 2 columns instead of 3) array([[ 1., 2., 3.], [ 7., 888., 9.]])
**分隔空白字符与指示缺失数据的空白字符不同。** 例如,如果列以
\t
分隔,则如果缺失数据包含一个或多个空格,就会识别出缺失数据。>>> with open("tabs.txt", "r") as f: ... data = (f.read()) >>> print(data) 1 2 3 44 6 7 888 9 # Tabs vs. spaces >>> print(data.replace("\t","^")) 1^2^3 44^ ^6 7^888^9 >>> np.genfromtxt("tabs.txt", delimiter="\t", missing_values=" +") array([[ 1., 2., 3.], [ 44., nan, 6.], [ 7., 888., 9.]])
读取 .npy 或 .npz 格式的文件#
选择
使用
numpy.load
。它可以读取由numpy.save
、numpy.savez
或numpy.savez_compressed
中的任何一个生成的使用内存映射。参见
numpy.lib.format.open_memmap
.
写入要由 NumPy 读取的文件#
二进制#
使用 numpy.save
,或者存储多个数组 numpy.savez
或 numpy.savez_compressed
.
为了 安全性和可移植性,请设置 allow_pickle=False
,除非 dtype 包含 Python 对象,这需要使用 pickle。
掩码数组 目前 无法 保存
,其他任意数组子类也是如此。
人类可读#
numpy.save
和 numpy.savez
创建二进制文件。要 **写入人类可读的文件**,请使用 numpy.savetxt
。数组只能是一维或二维,并且没有 `savetxtz` 用于多个文件。
大型数组#
参见 写入或读取大型数组.
读取任意格式的二进制文件(“二进制块”)#
使用 结构化数组.
示例
The .wav
文件头是紧接在 data_size
字节实际声音数据之前的 44 字节块
chunk_id "RIFF"
chunk_size 4-byte unsigned little-endian integer
format "WAVE"
fmt_id "fmt "
fmt_size 4-byte unsigned little-endian integer
audio_fmt 2-byte unsigned little-endian integer
num_channels 2-byte unsigned little-endian integer
sample_rate 4-byte unsigned little-endian integer
byte_rate 4-byte unsigned little-endian integer
block_align 2-byte unsigned little-endian integer
bits_per_sample 2-byte unsigned little-endian integer
data_id "data"
data_size 4-byte unsigned little-endian integer
The .wav
文件头作为 NumPy 结构化 dtype
wav_header_dtype = np.dtype([
("chunk_id", (bytes, 4)), # flexible-sized scalar type, item size 4
("chunk_size", "<u4"), # little-endian unsigned 32-bit integer
("format", "S4"), # 4-byte string, alternate spelling of (bytes, 4)
("fmt_id", "S4"),
("fmt_size", "<u4"),
("audio_fmt", "<u2"), #
("num_channels", "<u2"), # .. more of the same ...
("sample_rate", "<u4"), #
("byte_rate", "<u4"),
("block_align", "<u2"),
("bits_per_sample", "<u2"),
("data_id", "S4"),
("data_size", "<u4"),
#
# the sound data itself cannot be represented here:
# it does not have a fixed size
])
header = np.fromfile(f, dtype=wave_header_dtype, count=1)[0]
此 .wav
示例仅用于说明;要在现实生活中读取 .wav
文件,请使用 Python 的内置模块 wave
.
(改编自 Pauli Virtanen,Advanced NumPy,根据 CC BY 4.0 许可。)
写入或读取大型数组#
**无法放入内存的大型数组**可以使用内存映射像普通内存中数组一样处理。
使用
numpy.ndarray.tofile
或numpy.ndarray.tobytes
写入的原始数组数据可以使用numpy.memmap
读取array = numpy.memmap("mydata/myarray.arr", mode="r", dtype=np.int16, shape=(1024, 1024))
使用
numpy.save
输出的文件(即使用 numpy 格式)可以使用numpy.load
和mmap_mode
关键字参数读取large_array[some_slice] = np.load("path/to/small_array", mmap_mode="r")
内存映射缺少数据分块和压缩等功能;可以使用 NumPy 的更全面的格式和库包括
Zarr: 这里.
NetCDF:
scipy.io.netcdf_file
.
有关 memmap、Zarr 和 HDF5 之间权衡的更多信息,请参见 pythonspeed.com.
写入供其他(非 NumPy)工具读取的文件#
与其他工具 **交换数据** 的格式包括 HDF5、Zarr 和 NetCDF(参见 写入或读取大型数组)。
写入或读取 JSON 文件#
NumPy 数组和大多数 NumPy 标量 **不是** 直接 JSON 可序列化。相反,请使用针对 NumPy 类型的自定义 json.JSONEncoder
,您可以在您喜欢的搜索引擎中找到。
使用 pickle 文件保存/恢复#
尽量避免;pickle 对错误或恶意构造的数据不安全。
使用 numpy.save
和 numpy.load
。设置 allow_pickle=False
,除非数组 dtype 包含 Python 对象,在这种情况下需要使用 pickle。
numpy.load
和 pickle
子模块还支持取消使用 NumPy 1.26 创建的文件的 pickle。
从 pandas DataFrame 转换为 NumPy 数组#
使用 tofile
和 fromfile
保存/恢复#
通常,优先使用 numpy.save
和 numpy.load
.
numpy.ndarray.tofile
和 numpy.fromfile
会丢失有关字节序和精度的信息,因此不适合用作除临时存储之外的任何目的。