输入和输出

日期2011-11-17(最后修改),2006-05-20(创建)

简介

本页提供了一些示例,说明如何将 !NumPy 数组读入或写入文件,无论是 ASCII 还是二进制文件。演示的各种方法都有大量且有时复杂的选项,调用帮助以获取详细信息。

我们将考虑一个简单的示例,其中我们创建一个名为 `data` 的全零数组,将其写入文件 `myfile.txt`(对于二进制情况,为 myfile.dat),并将其读入 `read_data`。

本文档可以通过讨论更复杂的情况(例如多个数组)以及讨论所呈现的各种方法的成本/效益来改进。

文本文件

SciPy

可以使用 `savetxt` 来写入文件。到目前为止,读取文本数据的最简单方法是通过 genfromtxt(或派生便利函数 recfromtxt 和 recfromcsv)。

In [ ]
>>> from numpy import *
>>> data = zeros((3,3))
>>>#Write data:
>>> savetxt("myfile.txt", data)
>>>#Read:
>>> data = genfromtxt("myfile.txt") }}}

== Matplotlib (pylab) ==

Matplotlib  provides an easy solution which seems to load data faster than read_array:

{{{#!python numbers=disable
>>> from numpy import *
>>> from pylab import load           # warning, the load() function of numpy will be shadowed
>>> from pylab import save
>>> data = zeros((3,3))
>>> save('myfile.txt', data)
>>> read_data = load("myfile.txt")

numPy

In [ ]
>>> savetxt('myfile.txt', data, fmt="%12.6G")    # save to file
In [ ]
>>> from numpy import *
>>> data = genfromtxt('table.dat', unpack=True)

csv 文件

请注意,csv 代表“逗号分隔值”。这意味着分隔符(也称为分隔符),即用于分隔文件中各个值的字符,是一个逗号。在上面的示例中,默认分隔符是一个空格,但所有上述方法都有一个选项(请参阅其各自的帮助以获取详细信息),该选项可以设置为逗号以读取或写入 csv 文件。

更复杂的示例

或者,假设您已将 numpy 导入为 N,您可能希望读取任意列类型。您还可以返回一个 recarray,它允许您为数组分配“列标题”。

In [ ]
def read_array(filename, dtype, separator=','):
    """ Read a file with an arbitrary number of columns.
        The type of data in each column is arbitrary
        It will be cast to the given dtype at runtime
    """
    cast = N.cast
    data = [[] for dummy in xrange(len(dtype))]
    for line in open(filename, 'r'):
        fields = line.strip().split(separator)
        for i, number in enumerate(fields):
            data[i].append(number)
    for i in xrange(len(dtype)):
        data[i] = cast[dtype[i]](data[i])
    return N.rec.array(data, dtype=dtype)

然后可以使用相应的 dtype 调用它

In [ ]
mydescr = N.dtype([('column1', 'int32'), ('column2Name', 'uint32'), ('col3', 'uint64'), ('c4', 'float32')])
myrecarray = read_array('file.csv', mydescr)

二进制文件

二进制文件的优点是文件大小大大减少。付出的代价是失去了人类可读性,并且在某些格式中,失去了可移植性。

让我们考虑上一个示例中的数组。

带元数据的文件格式

最简单的可能性是使用 's 自己的二进制文件格式。见,和。

In [ ]
>>> numpy.save('test.npy', data)
>>> data2 = numpy.load('test.npy')

您可以使用 . 将多个数组保存在单个文件中。加载 . 文件时,您将获得一个类型为 . 的对象。您可以像这样获取数组列表并加载单个数组

In [ ]
>>> numpy.savez('foo.npz', a=a,b=b)
>>> foo = numpy.load('foo.npz')
>>> foo.files
['a', 'b']
>>> a2 = foo['a']
>>> b2 = foo['b']

在较旧的系统上,标准是使用 Python 的 pickle 模块来对数组进行 pickle 处理。

原始二进制

这些文件格式只是写出数组的内部表示。这是平台相关的,不包含有关数组形状或数据类型的任何信息,但速度快且易于使用。

SciPy 提供了来自 scipy.io.numpyio 的 fwrite()。您必须设置数据的尺寸,以及可选的类型(整数、短整型、浮点数等;请参见 1)。

要读取二进制文件,scipy.io.numpyio 提供了 fread()。您必须知道数组的数据类型、大小和形状。

In [ ]
>>> from scipy.io.numpyio import fwrite, fread
>>> data = zeros((3,3))
>>>#write:  fd = open('myfile.dat', 'wb')
>>> fwrite(fd, data.size, data)
>>> fd.close()
>>>#read:
>>> fd = open('myfile.dat', 'rb')
>>> datatype = 'i'
>>> size = 9
>>> shape = (3,3)
>>> read_data = fread(fd, size, datatype)
>>> read_data = data.reshape(shape)

或者,您可以简单地使用 和 。 以下面的示例为例

In [ ]
>>> data.tofile('myfile.dat')
>>> fd = open('myfile.dat', 'rb')
>>> read_data = numpy.fromfile(file=fd, dtype=numpy.uint8).reshape(shape)
In [ ]
numpy data type. The option {{{fromfile(..., count=<number>)}}} specifies the number of data entries of that type you want to read in (the default -1 means read in the whole file, which is what you usually want). However, the method is not recommended for data storage and transfer between different platforms, since no byteorder and datatype information is stored (see also the docstrings).
If you want that, use {{{numpy}}}'s own binary file format. See {{{numpy.save}}}, {{{numpy.savez}}} and {{{numpy.load}}}.
{{{#! python numbers=disable
>>> numpy.save('test.npy', data)
>>> data2 = numpy.load('test.npy')

另一种(但已弃用)方法是完全控制字节序(字节顺序)、存储顺序(行优先、列优先)以用于秩 > 1 数组和写入和读回的数据类型。 写入

In [ ]
>>> from scipy.io import npfile
>>> shape = (3,3)
>>> data = numpy.random.random(shape)
>>> npf = npfile('test.dat', order='F', endian='<', permission='wb')
>>> npf.write_array(data)
>>> npf.close()

以及读回

In [ ]
>>> npf = npfile('test.dat', order='F', endian='<', permission='rb')
>>> data2 = npf.read_array(float, shape=shape)
>>> npf.close()

将 Fortran 或 C 数组写入带有元数据的二进制文件

libnpy 是一个小型库,它提供简单的例程,用于使用 NumPy 自身的二进制格式将 C 或 Fortran 数组保存到数据文件。有关此格式的说明,请执行以下操作

In [ ]
>>> from numpy.lib import format
>>> help(format)

这是一个最小的 C 示例 `cex.c`

In [ ]
#include"npy.h"
int main(){
    double a[2][4] = { { 1, 2, 3, 4 },
                       { 5, 6, 7, 8 } };
    int shape[2] = { 2, 4 }, fortran_order = 0;

    npy_save_double("ca.npy", fortran_order, 2, shape, &a[0][0]);
    return 0;
}

该程序创建一个文件 `ca.npy`,您可以以通常的方式将其加载到 Python 中。

In [ ]
>>> ca = np.load('ca.npy')
>>> print ca
[[ 1.  2.  3.  4.]
 [ 5.  6.  7.  8.]]

相应的 Fortran 程序 `fex.f95` 如下所示

In [ ]
program fex
    use fnpy
    use iso_c_binding
    implicit none

    integer  :: i
    real(C_DOUBLE) :: a(2,4) = reshape([(i, i=1,8)], [2,4])

    call save_double("fa.npy", shape(a), a)
end program fex

但 NumPy 数组的条目现在遵循 Fortran(列优先)顺序。

In [ ]
>>> fa = np.load('fa.npy')
>>> print fa
[[ 1.  3.  5.  7.]
 [ 2.  4.  6.  8.]]

源代码分发中的 `README` 文件解释了如何使用 `make` 编译库。

如果您将 `npy.h` 和 `libnpy.a` 放置在与 `cex.c` 相同的目录中,那么您可以使用以下命令构建可执行文件 `cex`

In [ ]
gcc -o cex cex.c libnpy.a

类似地,将 `npy.mod` 和 `libnpy.a` 放置在与 `fex.f95` 相同的目录中,使用以下命令构建 `fex`

In [ ]
gfortran -o fex fex.f95 libnpy.a

部分作者:Unknown[5],VincentNijs,Unknown[56],FredericPetit,Elby,MartinSpacek,Unknown[57],Unknown[58],Unknown[53],AMArchibald,Unknown[59],Unknown[60],Unknown[61],Unknown[62],MikeToews