关于python:如何将多维数组写入文本文件?

How to write a multidimensional array to a text file?

在另一个问题中,如果我能提供我遇到问题的阵列,其他用户会提供一些帮助。但是,我甚至在一个基本的I/O任务上失败,例如将数组写入一个文件。

有人能解释一下我需要什么样的循环来将4x11x14 numpy数组写入文件吗?

这个数组由四个11 x 14数组组成,所以我应该用一个漂亮的换行符来格式化它,以使其他数组更容易读取文件。

编辑:所以我尝试了numpy.savetxt函数。奇怪的是,它给出了以下错误:

1
TypeError: float argument required, not numpy.ndarray

我假设这是因为函数不适用于多维数组?有我想在一个文件中找到的解决方案吗?


如果你想把它写到磁盘上,这样它就可以很容易地作为一个numpy数组读回,那么可以查看numpy.save。酸洗也可以,但对于大型阵列来说效率较低(你的阵列不是这样,所以两者都非常好)。

如果你想让它具有人类可读性,可以查看numpy.savetxt

编辑:所以,对于尺寸大于2的阵列来说,savetxt似乎不是一个很好的选择…但要想得出所有结论:

我刚刚意识到numpy.savetxt在超过2维的Ndarrays上阻塞了…这可能是通过设计实现的,因为没有内在定义的方法来指示文本文件中的其他维度。

例如,这个(一个二维数组)工作正常

1
2
3
import numpy as np
x = np.arange(20).reshape((4,5))
np.savetxt('test.txt', x)

同样的事情也会失败(有一个相当不具格式性的错误:TypeError: float argument required, not numpy.ndarray),对于一个3D阵列:

1
2
3
import numpy as np
x = np.arange(200).reshape((4,5,10))
np.savetxt('test.txt', x)

一个解决方法是将3D(或更高版本)数组分解为二维切片。例如。

1
2
3
4
x = np.arange(200).reshape((4,5,10))
with file('test.txt', 'w') as outfile:
    for slice_2d in x:
        np.savetxt(outfile, slice_2d)

然而,我们的目标是清晰的人类可读性,同时仍然可以很容易地用numpy.loadtxt读回。因此,我们可以更详细一点,并使用注释掉的行来区分切片。默认情况下,numpy.loadtxt将忽略以#开头的任何行(或commentskwarg指定的任何字符)。(这看起来比实际情况更详细…)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np

# Generate some test data
data = np.arange(200).reshape((4,5,10))

# Write the array to disk
with open('test.txt', 'w') as outfile:
    # I'm writing a header here just for the sake of readability
    # Any line starting with"#" will be ignored by numpy.loadtxt
    outfile.write('# Array shape: {0}
'
.format(data.shape))

    # Iterating through a ndimensional array produces slices along
    # the last axis. This is equivalent to data[i,:,:] in this case
    for data_slice in data:

        # The formatting string indicates that I'm writing out
        # the values in left-justified columns 7 characters in width
        # with 2 decimal places.  
        np.savetxt(outfile, data_slice, fmt='%-7.2f')

        # Writing out a break to indicate different slices...
        outfile.write('# New slice
'
)

这将产生:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Array shape: (4, 5, 10)
0.00    1.00    2.00    3.00    4.00    5.00    6.00    7.00    8.00    9.00  
10.00   11.00   12.00   13.00   14.00   15.00   16.00   17.00   18.00   19.00  
20.00   21.00   22.00   23.00   24.00   25.00   26.00   27.00   28.00   29.00  
30.00   31.00   32.00   33.00   34.00   35.00   36.00   37.00   38.00   39.00  
40.00   41.00   42.00   43.00   44.00   45.00   46.00   47.00   48.00   49.00  
# New slice
50.00   51.00   52.00   53.00   54.00   55.00   56.00   57.00   58.00   59.00  
60.00   61.00   62.00   63.00   64.00   65.00   66.00   67.00   68.00   69.00  
70.00   71.00   72.00   73.00   74.00   75.00   76.00   77.00   78.00   79.00  
80.00   81.00   82.00   83.00   84.00   85.00   86.00   87.00   88.00   89.00  
90.00   91.00   92.00   93.00   94.00   95.00   96.00   97.00   98.00   99.00  
# New slice
100.00  101.00  102.00  103.00  104.00  105.00  106.00  107.00  108.00  109.00
110.00  111.00  112.00  113.00  114.00  115.00  116.00  117.00  118.00  119.00
120.00  121.00  122.00  123.00  124.00  125.00  126.00  127.00  128.00  129.00
130.00  131.00  132.00  133.00  134.00  135.00  136.00  137.00  138.00  139.00
140.00  141.00  142.00  143.00  144.00  145.00  146.00  147.00  148.00  149.00
# New slice
150.00  151.00  152.00  153.00  154.00  155.00  156.00  157.00  158.00  159.00
160.00  161.00  162.00  163.00  164.00  165.00  166.00  167.00  168.00  169.00
170.00  171.00  172.00  173.00  174.00  175.00  176.00  177.00  178.00  179.00
180.00  181.00  182.00  183.00  184.00  185.00  186.00  187.00  188.00  189.00
190.00  191.00  192.00  193.00  194.00  195.00  196.00  197.00  198.00  199.00
# New slice

只要我们知道原始数组的形状,就很容易读回它。我们只需要做一个numpy.loadtxt('test.txt').reshape((4,5,10))。举个例子(你可以在一行中这样做,我只是想详细说明一下事情):

1
2
3
4
5
6
7
8
9
10
11
12
# Read the array from disk
new_data = np.loadtxt('test.txt')

# Note that this returned a 2D array!
print new_data.shape

# However, going back to 3D is easy if we know the
# original shape of the array
new_data = new_data.reshape((4,5,10))

# Just to check that they're the same...
assert np.all(new_data == data)


我不确定这是否符合您的要求,因为我认为您有兴趣让人们阅读该文件,但如果这不是主要问题,只需pickle即可。

要保存它:

1
2
3
4
5
6
7
8
import pickle

my_data = {'a': [1, 2.0, 3, 4+6j],
           'b': ('string', u'Unicode string'),
           'c': None}
output = open('data.pkl', 'wb')
pickle.dump(my_data, output)
output.close()

要读回:

1
2
3
4
5
6
7
8
import pprint, pickle

pkl_file = open('data.pkl', 'rb')

data1 = pickle.load(pkl_file)
pprint.pprint(data1)

pkl_file.close()


如果您不需要一个人类可读的输出,您可以尝试的另一个选项是将数组保存为一个matlab .mat文件,它是一个结构化数组。我不喜欢matlab,但是我能用很少的几行代码读写.mat,这一点很方便。

与JoeKington的答案不同,这样做的好处在于,您不需要知道.mat文件中数据的原始形状,也就是说,在读取时不需要重新整形。而且,与使用pickle不同,.mat文件可以通过matlab读取,也可能是其他一些程序/语言。

下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np
import scipy.io

# Some test data
x = np.arange(200).reshape((4,5,10))

# Specify the filename of the .mat file
matfile = 'test_mat.mat'

# Write the array to the mat file. For this to work, the array must be the value
# corresponding to a key name of your choice in a dictionary
scipy.io.savemat(matfile, mdict={'out': x}, oned_as='row')

# For the above line, I specified the kwarg oned_as since python (2.7 with
# numpy 1.6.1) throws a FutureWarning.  Here, this isn't really necessary
# since oned_as is a kwarg for dealing with 1-D arrays.

# Now load in the data from the .mat that was just saved
matdata = scipy.io.loadmat(matfile)

# And just to check if the data is the same:
assert np.all(x == matdata['out'])

如果忘记了数组在.mat文件中命名的键,则可以始终执行以下操作:

1
print matdata.keys()

当然,您可以使用更多的键来存储许多数组。

所以是的——用你的眼睛是看不懂的,但写和读数据只需要两行,我认为这是一个公平的权衡。

查看scipy.io.savemat的文档和scipy.io.loadmat还有这个教程页面:scipy.io文件IO教程


ndarray.tofile()也应该起作用。

例如,如果您的数组名为a

1
a.tofile('yourfile.txt',sep="",format="%s")

但不确定如何获取换行格式。

编辑(这里是Kevin J.Black的评论):

Since version 1.5.0, np.tofile() takes an optional parameter
newline='
'
to allow multi-line output.
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html


有专门的图书馆可以做到这一点。(加上python的包装纸)

  • netcdf4:http://www.unidata.ucar.edu/software/netcdf/
  • netcdf4 python接口:http://www.unidata.ucar.edu/software/netcdf/software.html python

  • HDF5:http://www.hdfgroup.org/hdf5/

  • 小精灵

    希望这有帮助


    只需在三个嵌套循环中遍历数组,并将其值写入文件。对于阅读,您只需使用相同的精确循环结构。您将以正确的顺序获得值,以便再次正确地填充数组。


    泡菜最适合这些情况。假设您有一个名为x_train的ndarray。您可以将其转储到文件中,然后使用以下命令将其还原:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import pickle

    ###Load into file
    with open("myfile.pkl","wb") as f:
        pickle.dump(x_train,f)

    ###Extract from file
    with open("myfile.pkl","rb") as f:
        x_temp = pickle.load(f)


    我有一种方法可以使用一个简单的filename.write()操作来完成它。它对我来说很好,但是我处理的数组有大约1500个数据元素。

    我基本上只需要for循环迭代文件,并以csv样式的输出将其逐行写入输出目标。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import numpy as np

    trial = np.genfromtxt("/extension/file.txt", dtype = str, delimiter =",")

    with open("/extension/file.txt","w") as f:
        for x in xrange(len(trial[:,1])):
            for y in range(num_of_columns):
                if y < num_of_columns-2:
                    f.write(trial[x][y] +",")
                elif y == num_of_columns-1:
                    f.write(trial[x][y])
            f.write("
    "
    )

    if和elif语句用于在数据元素之间添加逗号。无论出于什么原因,当以nd数组的形式读取文件时,这些都会被剥离出来。我的目标是将文件输出为csv,所以这个方法有助于处理这个问题。

    希望这有帮助!