NumPy 读写文件

2021-09-24 19:18 更新

此页面处理常见应用程序,有关 I/O 例程的完整集合,请参阅输入和输出

读取文件和CSV文件

没有缺失值

使用 numpy.loadtxt

有缺失值

使用 numpy.getfromtxt

numpy.getfromtxt要么:

  • 返回一个屏蔽数组,屏蔽掉缺失值(如果usemask = True
  • 用中指定的值 填充缺失值filling_values(默认np.nan为浮点数,-1 为整数)。

使用非空白分隔符

>>> print(open("csv.txt").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 还可以解析具有缺失值的以空格分隔的数据文件,如果 每个字段都有一个固定的宽度:使用宽度作为分隔符参数。

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


>>> f = open("fixedwidth.txt").read()  # doctest: +SKIP
>>> print(f)  # doctest: +SKIP
1   2      3
44      6
7   88889


## Showing spaces as ^
>>> print(f.replace(" ","^"))  # doctest: +SKIP
1^^^2^^^^^^3
44^^^^^^6
7^^^88889


>>> np.genfromtxt("fixedwidth.txt", delimiter=4)  # doctest: +SKIP
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参数。

>>> print(open("nan.txt").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。

>>> print(open("skip.txt").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,那么如果缺失数据由一个或多个空格组成,则将被识别。

>>> f = open("tabs.txt").read()  
>>> print(f)  
1       2       3
44              6
7       888     9


## Tabs vs. spaces
>>> print(f.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.savenumpy.saveznumpy.savez_compressed
  • 使用内存映射。见numpy.lib.format.open_memmap

写入文件供 NumPy 读取

二进制

使用 numpy.save, 或 来存储多个数组numpy.savez 或numpy.savez_compressed

为了安全性和可移植性,allow_pickle=False除非 dtype 包含需要酸洗的 Python 对象,否则设置 。

掩码数组,其他任意数组子类也不能。can't currently be saved

人类可读

numpy.savenumpy.savez创建二进制文件。要编写人类可读的文件,请使用numpy.savetxt. 该数组只能是一维或二维的,并且没有用于多个文件的 savetxtz

大型数组

请参阅写入或读取大型数组。

读取任意格式的二进制文件("binary blob")

使用结构化数组 例子: 该.wav文件头是前面的44字节块data_size的实际声音数据的字节数:

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

.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

写入或读取大型数组

太大而无法放入内存的数组可以像使用内存映射的普通内存中数组一样处理。

  • 原始数组数据写入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 一起使用的更多功能齐全的格式和库包括:

  • HDF5:h5py或PyTables。
  • 扎尔:这里。
  • NetCDF : scipy.io.netcdf_file.

有关 memmap、Zarr 和 HDF5 之间的权衡,请参阅 pythonspeed.com。

写入文件供其他(非 NumPy)工具读取

与其他工具交换数据的格式包括 HDF5、Zarr 和 NetCDF(请参阅写入或读取大型数组)。

写入或读取 JSON 文件

NumPy 数组不能直接 JSON 序列化。

使用 pickle 文件保存/恢复

尽可能避免;泡菜对于错误或恶意构建的数据并不安全。

使用numpy.savenumpy.load。Set allow_pickle=False,除非数组 dtype 包含 Python 对象,在这种情况下需要酸洗。

从 Pandas DataFrame 转换为 NumPy 数组

pandas.DataFrame.to_numpy

使用tofile和保存/恢复fromfile

一般来说,更喜欢numpy.savenumpy.load

numpy.ndarray.tofilenumpy.fromfile丢失有关字节顺序和精度的信息,因此不适用于除临时存储之外的任何其他内容。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号