使用Python将结果保存为YAML文件

8

在搜索了一个小时之后,我被困在了这个小问题上。我想把代码中的矩阵存储在.yaml文件中。

以下是从我的代码中得到的内容:

Matrix
[[  1.00665266e+03   0.00000000e+00   5.08285432e+02]
 [  0.00000000e+00   1.01086937e+03   3.45995536e+02]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00]]

我尝试保存这个矩阵(在我的代码中,mtx是缩写名称)

fname = "calibrationC300.yaml"

data = dict(
    Matrix = mtx,
)

with open(fname, "w") as f:
    yaml.dump(data, f, default_flow_style=False)   

但是我在我的YAML文件中读到的内容完全是错误的(只是坏的转换?)

Matrix: !!python/object/apply:numpy.core.multiarray._reconstruct
  args:
  - &id001 !!python/name:numpy.ndarray ''
  - !!python/tuple [0]
  - b
  state: !!python/tuple
  - 1
  - !!python/tuple [3, 3]
  - !!python/object/apply:numpy.dtype
    args: [f8, 0, 1]
    state: !!python/tuple [3, <, null, null, null, -1, -1, 0]
  - false
  - !!binary |
    cWM87e1YkEAAAAAAAAAAAIUEEyb5SH1AAAAAAAAAAACp/Z3yc2qQQFv0vPqb5nZAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAPA/

这是我第一次使用Yaml文件,我做错了什么吗? 在Yaml文件中有没有一种方法可以获取以简单形式(与代码获得的方式相同)表示的矩阵? 谢谢您提前。


你的目标是什么 - 获得适合作为numpy脚本输入的内容,适合作为不同工具输入的可移植内容,还是人类可读的内容? - John Carter
@JohnCarter 更偏爱这三件事。作为我的numpy脚本的输入,我刚刚使用了numpy.savez解决了它。 - marcoresk
假设您正在使用PyYAML,请参见:https://dev59.com/4cXsa4cB1Zd3GeqPztWV#75508284 - luator
3个回答

7

float和numpy.float64之间的区别。Yaml使用更复杂的方式表示numpy.float64。如果您喜欢更易读的yaml,可以改为使用float。请参阅以下示例:

print(yaml.dump({'test': 1, 'data':float(0.2)}, default_flow_style=False))
print(yaml.dump({'test': 2, 'data':numpy.float64(0.2)}, default_flow_style=False))

输出结果为:

data: 0.2

test: 1

data: !!python/object/apply:numpy.core.multiarray.scalar
- !!python/object/apply:numpy.dtype
  args:
  - f8
  - 0
  - 1
  state: !!python/tuple
  - 3
  - <
  - null
  - null
  - null
  - -1
  - -1
  - 0
- !!binary |
  mpmZmZmZyT8=

test: 2

df.to_dict('records') 可以将数据框转换为普通的 Python 字典。 - Kevin Zhu

4

这里唯一的问题似乎是您对如何将numpy内部转储为YAML的期望。

一个简单的检查你得到的YAML是否正确的方法是,加载你所转储的内容:

import ruamel.yaml
import numpy
import pprint

mtx = [[1.00665266e+03, 0.00000000e+00, 5.08285432e+02],
       [0.00000000e+00, 1.01086937e+03, 3.45995536e+02],
       [0.00000000e+00, 0.00000000e+00, 1.00000000e+00],]

data = dict(Matrix=mtx)

yaml_str = ruamel.yaml.dump(data, default_flow_style=False)
data = ruamel.yaml.load(yaml_str)
print(data)

这将会给出:

{'Matrix': [[1006.65266, 0.0, 508.285432], [0.0, 1010.86937, 345.995536], [0.0, 0.0, 1.0]]}
numpy使用的特殊类型不会被转储为简单(可读)的YAML格式,无法保证可以重新加载。对于一些结构可能是可以的,尽管这很容易导致歧义,并且据我所知,为了简化,没有针对任何numpy类型进行这样的操作。
当然,你可以在不需要numpy提供其还原信息的情况下转储该YAML,方法如下:
ruamel.yaml.round_trip_dump(data, sys.stdout)

这将会产生:

Matrix:
- - 1006.65266
  - 0.0
  - 508.285432
- - 0.0
  - 1010.86937
  - 345.995536
- - 0.0
  - 0.0
  - 1.0

更易读,但不会在你再次从其YAML表示中load()时自动变成numpy.multiarray。


在你的例子中,mtx 不是一个 np.multiarray 而是一个普通的列表(并且 np.multiarray 被这个列表覆盖了)。你肯定是想要 mtx = numpy.multiarray([[...], ...]) - moi
@moi 我当然不是指 mtx = numpy.multiarray([[...], ...]),因为那样会导致与 OP 抱怨的非可读 YAML 完全相同的结果,并且不会得到所呈现的结果。当然,mtx 不是一个 np.multiarray,它们为什么会是呢?它们只是在多重赋值语句中被赋予相同的值。当然,你可以争论在这里分配给 np.multiarray 没有任何意义,但那是完全不同的事情。 - Anthon
好的,我明白了。所以如果它没有任何作用,你可能想把它从你的答案中删除,因为它会让人困惑(至少是我)。 - moi

1
我虽然也不是专家,但生成的yaml文件看起来是正确的。你可以看到原始类型默认情况下呈现得很好。对于其他类型,您可能需要采取一些措施。在文档中阅读更多信息。
祝你好运!
(我没有足够的声誉来发表评论,否则我会将此帖子留作评论。)

@我会尝试查看您的链接,谢谢。您知道是否有一种方法可以将我的矩阵以与代码中获得的相同形式保存吗?(我已经为您的答案点赞,现在您有足够的声望来发表评论!) - marcoresk
从文档中看来,似乎你需要创建自己的yaml.YAMLObject子类,并指定__repr__、__init__和yaml_tag。我认为它已经在某个地方可用了...但我找不到它。如果你只想序列化,你可以将矩阵转换为嵌套列表? - DA--
我也找不到例子。我想将我的矩阵保存为矩阵,以便在另一个脚本中加载它。我开始怀疑 YAML 是否是正确的选择... - marcoresk
就我个人而言,我只会使用YAML来提高可读性。否则,请使用JSON或Pickle。 - DA--

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接