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

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

有人能解释一下写一个4x11x14的数组到文件中需要什么样的循环吗?

这个数组由4个11 x 14的数组组成,因此我应该用一个漂亮的换行符来格式化它,以便于其他人读取文件。

编辑 : 所以我尝试了 numpy.savetxt 函数:

TypeError: float argument required, not numpy.ndarray

我假设这是因为函数不能处理多维数组?在一个文件中有我想要的解决方案吗?

328506 次浏览

我不确定这是否符合您的要求,因为我认为您有兴趣使文件可读的人,但如果这不是一个主要的关注,只是 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()

再读一遍:

import pprint, pickle


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


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


pkl_file.close()

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

如果您想把它写到磁盘上,这样就可以很容易地以数字数组的形式读回来,那么请查看 numpy.save。腌制它也可以很好地工作,但是对于大型数组来说效率较低(您的数组就不是这样,所以任何一个都完全可以)。

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

编辑: 所以,对于大于2维的数组来说,savetxt似乎不是一个很好的选择... ... 但是仅仅把所有的东西都画出来就可以得出完整的结论:

我刚刚意识到 numpy.savetxt在超过2维的 ndarray 上会窒息... ... 这可能是设计好的,因为在文本文件中没有固有的定义方式来表示额外的维度。

例如,这个(2D 阵列)工作得很好

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

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

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

一种变通方法是将3D (或更大的)数组分割成2D 切片。

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

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

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

结果是:

# 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))。作为一个例子(你可以用一行代码来完成,我只是想详细说明一下) :

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

有专门的库可以做到这一点(加上 python 的包装器)

希望这能帮上忙

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

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

这里有一个例子:

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文件中的名称,您总是可以这样做:

print matdata.keys()

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

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

请查看 < a href = “ http://docs.scipy.org/doc/scipy/reference/generated/scipy.io.savemat.html”> scipy.io.savemat 的文档 和 Scypy.io.loadmat 还有这个教程页面: scipy.IO 文件 IO 教程

ndarray.tofile() 也应该起作用

例如,如果你的数组叫做 a:

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

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

编辑 (归功于凯文 · J · 布莱克的评论 给你) :

自1.5.0版以来,np.tofile()采用了一个可选参数 newline='\n'允许多行输出。 Https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html

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

我基本上只有 for 循环来遍历文件,并用 csv 样式的输出将其逐行写入到输出目标。

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("\n")

If 和 elif 语句用于在数据元素之间添加逗号。不管出于什么原因,当以和数组的形式读入文件时,这些属性会被去掉。我的目标是将文件作为 csv 输出,因此这个方法可以帮助处理这个问题。

希望这个能帮上忙!

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

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)

对多维数组使用 JSON 模块,例如。

import json
with open(filename, 'w') as f:
json.dump(myndarray.tolist(), f)

写入 Python 的 print() 文件:

import numpy as np
import sys


stdout_sys = sys.stdout
np.set_printoptions(precision=8) # Sets number of digits of precision.
np.set_printoptions(suppress=True) # Suppress scientific notations.
np.set_printoptions(threshold=sys.maxsize) # Prints the whole arrays.
with open('myfile.txt', 'w') as f:
sys.stdout = f
print(nparr)
sys.stdout = stdout_sys

使用 定制 set_printoptions()如何显示对象。

文件 I/O 常常是代码中的瓶颈。这就是为什么 ASCII I/O 总是比二进制 I/O 慢的原因。我已经将一些建议的解决方案与 完美情节进行了比较:

enter image description here

重现情节代码:

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

如果你的数组是 numpy.array 或 torch.tensor 并且维度小于4。
用这个密码。

# from util.npa2csv import Visualarr; Visualarr(x)
import numpy as np
import torch


def Visualarr(arr, out = 'array_out.txt'):
dim = arr.ndim
if isinstance(arr, np.ndarray):
# (#Images, #Chennels, #Row, #Column)
if dim == 4:
arr = arr.transpose(3,2,0,1)
if dim == 3:
arr = arr.transpose(2,0,1)


if isinstance(arr, torch.Tensor):
arr = arr.numpy()
    

    

with open(out, 'w') as outfile:
outfile.write('# Array shape: {0}\n'.format(arr.shape))
        

if dim == 1 or dim == 2:
np.savetxt(outfile, arr, fmt='%-7.3f')


elif dim == 3:
for i, arr2d in enumerate(arr):
outfile.write('# {0}-th channel\n'.format(i))
np.savetxt(outfile, arr2d, fmt='%-7.3f')


elif dim == 4:
for j, arr3d in enumerate(arr):
outfile.write('\n# {0}-th Image\n'.format(j))
for i, arr2d in enumerate(arr3d):
outfile.write('# {0}-th channel\n'.format(i))
np.savetxt(outfile, arr2d, fmt='%-7.3f')


else:
print("Out of dimension!")


    



def test_va():
arr = np.random.rand(4,2)
tens = torch.rand(2,5,6,3)
Visualarr(arr)


test_va()

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

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