【问题标题】:Numpy array from YAML来自 YAML 的 Numpy 数组
【发布时间】:2019-06-13 00:07:06
【问题描述】:

我在 YAML 中有一个配置文件,其中包含字符串、浮点数、整数和列表。我想,当 YAML 被加载时返回列表一个 numpy 数组。因此,例如,如果 YAML 如下:

name: 'John Doe'
age: 20
score:
  -- 19
   - 45
  -- 21
   - 12
  -- 32
   - 13

我读了这篇文章

import yaml

def read(CONFIG_FILE):
    with open(CONFIG_FILE) as c:
        return yaml.load(c)

config = read('path\to\yml')

然后我希望将config['score'] 而非列表键入为numpy.array。当然,这可以在 YAML 之外通过 numpy.array(config['score']) 之类的方式轻松完成,但我想避免这种情况。

我已尝试按照文档 (https://pyyaml.org/wiki/PyYAMLDocumentation) 中的说明设置标签,但无法使其正常工作。因此,例如,以下失败:

score:!!python/object:numpy.array
  -- 19
   - 45
  -- 21
   - 12
  -- 32
   - 13

将标签更改为!!python/module:numpy.array!!python/name:numpy.array 也不起作用。

我怎样才能做到这一点?我正在使用 Python v.3

【问题讨论】:

  • 没有列表(即 YAML 中的序列),因为在开始 score 的值的破折号后没有空格,这不是序列条目指示符,其余的是一个普通的多行标量。

标签: python arrays python-3.x yaml


【解决方案1】:

用你得到的数据转储一个 numpy 数组,你会得到一个 YAML 文件比通过添加一个 标签。因此,我建议您只定义一个自己的标签 导致数据加载,然后转换为 numpy on 苍蝇。这样您就不必遍历生成的加载结构来查找 score 或其值。

config.yaml:

name: 'John Doe'
age: 20
score: !2darray
  -- 19
   - 45
  -- 21
   - 12
  -- 32
   - 13

您还必须意识到该文件中score 的值是一个普通的多行 标量,它将被加载为字符串'-- 19 - 45 -- 21 - 12 -- 32 - 13'

import sys
import ruamel.yaml
from pathlib import Path
import numpy

config_file = Path('config.yaml')

yaml = ruamel.yaml.YAML(typ='safe')

@yaml.register_class
class Array:
    yaml_tag = '!2darray'

    @classmethod
    def from_yaml(cls, constructor, node):
        array = []
        for x in node.value.split():
            if x == '--':
                sub_array = []
                array.append(sub_array)
                continue
            if x == '-':
                continue
            sub_array.append(int(x))
        return numpy.array(array)

data = yaml.load(config_file)
print(type(data['score']))
print(data)

给出:

<class 'numpy.ndarray'>
{'name': 'John Doe', 'age': 20, 'score': array([[19, 45],
       [21, 12],
       [32, 13]])}

如果在您的输入中score 的值将是序列序列, 在- 之后需要一个空格,然后才会被解释为 一个序列入口指示器:

name: 'John Doe'
age: 20
score: !2darray
  - - 19
    - 45
  - - 21
    - 12
  - - 32
    - 13

如果这是输入,那么您需要调整from_yaml 方法:

@yaml.register_class
class Array:
    yaml_tag = '!2darray'

    @classmethod
    def from_yaml(cls, constructor, node):
        array = constructor.construct_sequence(node, deep=True)
        return numpy.array(array)

这给出了与以前完全相同的输出。

【讨论】:

  • 以上还有一个额外的好处,就是你不必使用 PyYAML。它的 yaml.load() 被记录为可能不安全,您需要它来尝试使用 !!python/object:module.type 形式的标签
猜你喜欢
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多