如何正确保存和加载 numpy.array()数据?

我想知道,如何正确地保存和加载 numpy.array数据。目前我使用的是 numpy.savetxt()方法。例如,如果我得到一个数组 markers,它看起来像这样:

enter image description here

我试图通过使用以下方法来保存它:

numpy.savetxt('markers.txt', markers)

在其他脚本中,我尝试打开以前保存的文件:

markers = np.fromfile("markers.txt")

这就是我得到的。

enter image description here

保存的数据首先看起来像这样:

0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00

但是当我使用相同的方法保存刚刚加载的数据时,比如 numpy.savetxt(),它看起来是这样的:

1.398043286095131769e-76
1.398043286095288860e-76
1.396426376485745879e-76
1.398043286055061908e-76
1.398043286095288860e-76
1.182950697433698368e-76
1.398043275797188953e-76
1.398043286095288860e-76
1.210894289234927752e-99
1.398040649781712473e-76

我做错了什么?另外,我没有其他的“后台”操作。只是存储和加载,这就是我得到的。先谢谢你。

302512 次浏览

我发现最可靠的方法是使用 np.savetxtnp.loadtxt,而不是 np.fromfile,因为 np.fromfile更适合用 tofile编写的二进制文件。np.fromfilenp.tofile方法写和读二进制文件,而 np.savetxt写文本文件。 例如:

a = np.array([1, 2, 3, 4])
np.savetxt('test1.txt', a, fmt='%d')
b = np.loadtxt('test1.txt', dtype=int)
a == b
# array([ True,  True,  True,  True], dtype=bool)

或者:

a.tofile('test2.dat')
c = np.fromfile('test2.dat', dtype=int)
c == a
# array([ True,  True,  True,  True], dtype=bool)

我使用前一种方法,即使速度较慢,并且创建较大的文件(有时) : 二进制格式可以依赖于平台(例如,文件格式取决于系统的字节顺序)。

NumPy 数组有一种 平台独立格式,可以用 np.savenp.load保存和读取:

np.save('test3.npy', a)    # .npy extension is added if not given
d = np.load('test3.npy')
a == d
# array([ True,  True,  True,  True], dtype=bool)

np.fromfile() 有一个 sep=关键字参数:

如果文件是文本文件,则项之间的分隔符。空(“”)分隔符意味着文件应该被视为二进制文件。分隔符中的空格(“”)匹配零个或多个空格字符。只包含空格的分隔符必须至少匹配一个空格。

sep=""的默认值意味着 np.fromfile()尝试将其读取为二进制文件,而不是空格分隔的文本文件,因此您将得到无意义的值。如果你使用 np.fromfile('markers.txt', sep=" "),你会得到你想要的结果。

然而,正如其他人指出的那样,np.loadtxt()是将文本文件转换为数字数组的首选方法,除非文件需要人类可读,否则通常最好使用二进制格式(例如 np.load()/np.save())。

np.save('data.npy', num_arr) # save
new_num_arr = np.load('data.npy') # load

简短的回答是: 您应该使用 np.savenp.load

使用这些函数的优势在于,它们是由 Numpy 库的开发人员制作的,并且已经可以工作了(另外,为了提高处理速度,它们可能进行了很好的优化)。

例如:

import numpy as np
from pathlib import Path


path = Path('~/data/tmp/').expanduser()
path.mkdir(parents=True, exist_ok=True)


lb,ub = -1,1
num_samples = 5
x = np.random.uniform(low=lb,high=ub,size=(1,num_samples))
y = x**2 + x + 2


np.save(path/'x', x)
np.save(path/'y', y)


x_loaded = np.load(path/'x.npy')
y_load = np.load(path/'y.npy')


print(x is x_loaded) # False
print(x == x_loaded) # [[ True  True  True  True  True]]

详细回答:

最后,它确实取决于您的需要,因为您也可以将其保存为人类可读的格式(参见 将 NumPy 数组转储到 csv 文件中) ,如果您的文件非常大,甚至可以使用其他库(参见 在磁盘上保存数字数组的最佳方法进行扩展讨论)。

但是,(因为在问题中使用了“正确”这个词,所以进行了扩展)我仍然认为应该开箱即用地使用 numpy 函数(以及大多数代码!) 最有可能满足大多数用户的需求。最重要的原因是 已经起作用了。出于任何其他原因试图使用其他东西可能会让你陷入一个意想不到的长兔子洞,去找出为什么它不起作用,并强迫它起作用。

举个例子,试着用腌黄瓜来保存它。我只是为了好玩才这么做的,我花了至少30分钟才意识到 pickle 不会保存我的东西,除非我用 wb以字节模式打开和读取文件。搜索问题、测试可能的解决方案、理解错误信息等都需要时间。.这是一个小细节,但事实上,它已经要求我打开一个文件复杂的事情在意想不到的方式。为了增加这一点,它需要我重新阅读这个(顺便说一句,这有点令人困惑) : 模式 a,a + ,w,w + 和 r + 在内置开放函数中的区别?

因此,如果有一个接口可以满足你的需求,使用它,除非你有一个(非常)很好的理由(例如,与 matlab 的兼容性或出于某种原因,你真的想读取文件和打印 Python 真的不符合你的需求,这可能是值得怀疑的)。此外,如果您需要优化它,您很可能会在以后发现(而不是花费数年时间调试无用的东西,如打开一个简单的 Numpy 文件)。

因此使用接口/numpy offer 。它可能不是完美的,但它最有可能是罚款,特别是对于一个图书馆已经存在了很长时间。

我已经用 numpy 在很多方面花费了保存和加载数据的时间,所以尽情享受吧。希望这个能帮上忙!

import numpy as np
import pickle
from pathlib import Path


path = Path('~/data/tmp/').expanduser()
path.mkdir(parents=True, exist_ok=True)


lb,ub = -1,1
num_samples = 5
x = np.random.uniform(low=lb,high=ub,size=(1,num_samples))
y = x**2 + x + 2


# using save (to npy), savez (to npz)
np.save(path/'x', x)
np.save(path/'y', y)
np.savez(path/'db', x=x, y=y)
with open(path/'db.pkl', 'wb') as db_file:
pickle.dump(obj={'x':x, 'y':y}, file=db_file)


## using loading npy, npz files
x_loaded = np.load(path/'x.npy')
y_load = np.load(path/'y.npy')
db = np.load(path/'db.npz')
with open(path/'db.pkl', 'rb') as db_file:
db_pkl = pickle.load(db_file)


print(x is x_loaded)
print(x == x_loaded)
print(x == db['x'])
print(x == db_pkl['x'])
print('done')

关于我所学到的一些评论:

  • 正如预期的那样,这已经很好地压缩了 np.save(参见 https://stackoverflow.com/a/55750128/1601580) ,不需要打开任何文件即可工作。干净。放松。有效率。好好利用。
  • np.savez使用未压缩的格式(参见 医生)将多个数组保存为未压缩的 .npz格式的单个文件。如果您决定使用它(我们警告过您不要使用标准解决方案,因此可能会出现 bug!)您可能会发现需要使用参数名称来保存它,除非您想使用默认名称。因此,如果第一个已经工作(或任何作品使用它!) ,不要使用这个
  • Pickle 还允许任意的代码执行。
  • 人类可读的文件造价昂贵等等,可能不值得。
  • 有一种叫做 hdf5的大文件。酷! https://stackoverflow.com/a/9619713/1601580

请注意,这并不是一个详尽的答案,但对于其他资源,请检查以下内容: