Когда вы используете PyYAML load
, вы указываете, что все в загружаемом вами документе YAML является безопасным.Вот почему вам нужно использовать yaml.safe_load
.
В вашем случае это приводит к ошибке, потому что safe_load
не знает, как сконструировать внутренние элементы панд, которые имеют теги в документе YAML, такие как:
!!python/name:pandas.core.indexes.base.Index
и
!!python/tuple
и т. Д.
Вам потребуется предоставить конструкторы для всех объектов, добавить их в SafeLoader
и затем выполнить a_series = yaml.load(f)
.Для этого может потребоваться много работы, особенно если учесть, что небольшое изменение в данных, используемых в вашей серии, может потребовать добавления конструкторов.
Вы можете вывести DICT-представление вашего Series
и загрузитьчто обратно.Конечно, некоторая информация теряется в этом процессе, я не уверен, что это приемлемо:
import sys
import yaml
from pandas import Series
def series_representer(dumper, data):
return dumper.represent_mapping(u'!pandas.series', data.to_dict())
yaml.add_representer(Series, series_representer, Dumper=yaml.SafeDumper)
def series_constructor(loader, node):
d = loader.construct_mapping(node)
return Series(data)
yaml.add_constructor(u'!pandas.series', series_constructor, Loader=yaml.SafeLoader)
data = Series([1,2,3,4,5], index=['a', 'b', 'c', 'd', 'e'])
with open('ex.yaml', 'w') as f:
yaml.safe_dump(data, f)
with open('ex.yaml') as f:
s = yaml.safe_load(f)
print(s)
print(type(s))
, что дает:
a 1
b 2
c 3
d 4
e 5
dtype: int64
<class 'pandas.core.series.Series'>
И файл ex.yaml
содержит:
!pandas.series {a: 1, b: 2, c: 3, d: 4, e: 5}
Следует отметить несколько вещей:
Документы YAML обычно записываются в файлы с расширением .yaml
.Использование .py
обязательно приведет вас в замешательство, или вам придется перезаписать некоторые исходные файлы программы в какой-то момент.
yaml.load()
и yaml.safe_load()
принимают поток в качестве первого используемого параметраони как:
data = yaml.safe_load(stream)
и не как:
yaml.safe_load(data, stream)
Было бы лучше иметь двухступенчатый конструктор , который позволяетвам построить самоссылочные структуры данных.Однако Series.append()
, похоже, не работает для этого:
def series_constructor(loader, node):
d = Series()
yield d
d.append(Series(loader.construct_mapping(node)))
Если сброс Series
через словарь не достаточно хорош (потому что это упрощает серию'data), и если вас не волнует читаемость сгенерированного YAML, вы можете вместо .to_dict()
использовать для to_pickle()
, но вам придется работать с временными файлами, так как этот метод недостаточно гибок для обработкиfile like объекты и ожидает строку имени файла в качестве аргумента.