如何将多维数组写入文本文件?

Ivo*_*pse 103 python file-io numpy

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

任何人都可以解释我需要将4x11x14 numpy数组写入文件需要什么样的循环?

这个数组包含四个11 x 14数组,所以我应该用一个漂亮的换行符来格式化它,以便在其他数据上更容易读取文件.

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

TypeError: float argument required, not numpy.ndarray
Run Code Online (Sandbox Code Playgroud)

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

Joe*_*ton 182

如果你想将它写入磁盘,以便它可以很容易地作为一个numpy数组读回来,请查看numpy.save.酸洗它也可以正常工作,但它对于大型阵列效率较低(不是你的,所以要么完全没问题).

如果您希望它是人类可读的,请查看numpy.savetxt.

编辑: 所以,savetxt对于具有> 2维度的数组来说,它似乎不是一个很好的选择...但是只是为了得出所有内容的完整结论:

我刚刚意识到numpy.savetxtndarray上有两个以上维度的窒息......这可能是设计的,因为没有固有的方法来指示文本文件中的其他维度.

例如,这个(2D数组)工作正常

import numpy as np
x = np.arange(20).reshape((4,5))
np.savetxt('test.txt', x)
Run Code Online (Sandbox Code Playgroud)

虽然同样的事情会失败(有一个相当无意义的错误:)TypeError: float argument required, not numpy.ndarray对于3D数组:

import numpy as np
x = np.arange(200).reshape((4,5,10))
np.savetxt('test.txt', x)
Run Code Online (Sandbox Code Playgroud)

一种解决方法是将3D(或更高)数组分解为2D切片.例如

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)
Run Code Online (Sandbox Code Playgroud)

但是,我们的目标是显然是人类可读的,同时仍然可以轻松地重新阅读numpy.loadtxt.因此,我们可能会更冗长,并使用注释掉的行来区分切片.默认情况下,numpy.loadtxt将忽略任何以#(或由commentskwarg 指定的任何字符)开头的行.(这看起来比实际上更冗长......)

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}\n'.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\n')
Run Code Online (Sandbox Code Playgroud)

这会产生:

# 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
Run Code Online (Sandbox Code Playgroud)

只要我们知道原始数组的形状,重新读回来就很容易.我们可以做到numpy.loadtxt('test.txt').reshape((4,5,10)).作为一个例子(你可以在一行中做到这一点,我只是详细说明事情):

# 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)
Run Code Online (Sandbox Code Playgroud)

  • 来自我的+1,另见`numpy.loadtxt`(http://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html) (2认同)
  • 现在有一个更简单的解决方案来解决这个问题: yourStrArray = np.array([str(val) for val in yourMulDArray],dtype='string'); np.savetxt('YourTextFile.txt',yourStrArray,fmt='%s') (2认同)

Dom*_*ger 29

我不确定这是否符合您的要求,因为我认为您有兴趣让人们可以阅读该文件,但如果这不是主要关注点,那就是pickle它.

要保存它:

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()
Run Code Online (Sandbox Code Playgroud)

读回来:

import pprint, pickle

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

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

pkl_file.close()
Run Code Online (Sandbox Code Playgroud)


ase*_*ram 10

如果您不需要人类可读的输出,您可以尝试的另一个选项是将数组保存为MATLAB .mat文件,这是一个结构化数组.我鄙视MATLAB,但是我可以.mat在很少的行中读写一个这样的事实很方便.

与乔金顿的回答,这样做的好处是,你不需要知道数据的原始形状.mat的文件,即无需通过阅读来重塑.而且,不像使用pickle,一个.mat文件可以通过MATLAB读取,可能还有一些其他程序/语言.

这是一个例子:

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'])
Run Code Online (Sandbox Code Playgroud)

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

print matdata.keys()
Run Code Online (Sandbox Code Playgroud)

当然,您可以使用更多密钥存储许多阵列.

所以是的 - 用你的眼睛看不懂,但只需2行就可以写入和读取数据,我认为这是一个公平的权衡.

看看scipy.io.savematscipy.io.loadmat 以及本教程页面的文档:scipy.io文件IO教程


Nic*_*mer 8

文件 I/O 通常会成为代码的瓶颈。这就是为什么重要的是要知道 ASCII I/O 总是比二进制 I/O 慢很多。我将一些建议的解决方案与perfplot进行了比较:

在此输入图像描述

重现情节的代码:

import json
import pickle

import numpy as np
import perfplot
import scipy.io


def numpy_save(data):
    np.save("test.dat", data)


def numpy_savetxt(data):
    np.savetxt("test.txt", data)


def numpy_savetxt_fmt(data):
    np.savetxt("test.txt", data, fmt="%-7.2f")


def pickle_dump(data):
    with open("data.pkl", "wb") as f:
        pickle.dump(data, f)


def scipy_savemat(data):
    scipy.io.savemat("test.dat", mdict={"out": data})


def numpy_tofile(data):
    data.tofile("test.txt", sep=" ", format="%s")


def json_dump(data):
    with open("test.json", "w") as f:
        json.dump(data.tolist(), f)


perfplot.save(
    "out.png",
    setup=np.random.rand,
    n_range=[2 ** k for k in range(20)],
    kernels=[
        numpy_save,
        numpy_savetxt,
        numpy_savetxt_fmt,
        pickle_dump,
        scipy_savemat,
        numpy_tofile,
        json_dump,
    ],
    equality_check=None,
)
Run Code Online (Sandbox Code Playgroud)


ato*_*3ls 7

ndarray.tofile() 也应该工作

例如,如果你的数组被调用a:

a.tofile('yourfile.txt',sep=" ",format="%s")
Run Code Online (Sandbox Code Playgroud)

不知道如何获得换行格式.

编辑(信用凯文J.黑色的评论点击这里):

从版本1.5.0开始,np.tofile()采用可选参数 newline='\n'以允许多行输出. https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html


Kev*_*tel 5

您还可以以文件类型存储 NumPy 多维数组数据.npy(它是二进制文件)。

  1. 使用 numpysave()函数将数据存储到文件中:
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) #shape (3x3)
np.save('filename.npy', a)
Run Code Online (Sandbox Code Playgroud)
  1. load()使用 numpy函数卸载:
b = np.load('filename.npy')
Run Code Online (Sandbox Code Playgroud)