Как хранить словарь в наборе данных HDF5

У меня есть словарь, где ключ - это объект datetime, а значение - набор целых чисел:

>>> d.items()[0]
(datetime.datetime(2012, 4, 5, 23, 30), (14, 1014, 6, 3, 0))

Я хочу сохранить его в наборе данных HDF5, но если я попытаюсь просто сбросить словарь, h5py вызывает ошибку:

TypeError: объект dtype dtype ('object') не имеет собственного эквивалента HDF5

Что было бы "лучшим" способом преобразования этого словаря, чтобы я мог хранить его в наборе данных HDF5?

В частности, я не хочу просто дублировать словарь в массиве numpy, так как это усложнит поиск данных на основе запроса datetime.

Ответ 1

Я нашел два способа:

I) преобразовать объект datetime в строку и использовать его в качестве имени набора данных

h = h5py.File('myfile.hdf5')
for k, v in d.items():
    h.create_dataset(k.strftime('%Y-%m-%dT%H:%M:%SZ'), data=np.array(v, dtype=np.int8))

к которым можно получить доступ к данным путем ввода ключевых строк (имя набора данных). Например:

for ds in h.keys():
    if '2012-04' in ds:
        print(h[ds].value)

II) преобразовать объект datetime в подгруппы данных

h = h5py.File('myfile.hdf5')
for k, v in d.items():
    h.create_dataset(k.strftime('%Y/%m/%d/%H:%M'), data=np.array(v, dtype=np.int8))

обратите внимание на косые черты в строке strftime, которая создаст соответствующие подгруппы в файле HDF. Доступ к данным можно получить напрямую, как h['2012']['04']['05']['23:30'].value, или путем итерации с предоставленными итераторами h5py или даже с помощью пользовательских функций через visititems()

Для простоты я выбираю первый вариант.

Ответ 2

Я бы сериализовал объект в JSON или YAML и сохранил полученную строку как атрибут в соответствующем объекте (группа HDF5 или набор данных).

Я не уверен, почему вы используете дату-время как имя набора данных, однако, если вам абсолютно не нужно искать ваш набор данных напрямую с помощью datetime.

p.s. Для чего это стоит, PyTables намного проще в использовании, чем низкоуровневый h5py.

Ответ 3

В настоящее время у нас есть глубокий (www.deepdish.io):

import deepdish as dd
dd.io.save(filename, {'dict1': dict1, 'dict2': dict2}, compression=('blosc', 9))

Ответ 4

Этот вопрос относится к более общему вопросу о возможности хранения любого типа словаря в формате HDF5. Сначала преобразуйте словарь в строку. Затем, чтобы восстановить словарь, используйте библиотеку ast, используя команду import ast. В следующем примере приведен пример.

>>> d = {1:"a",2:"b"}
>>> s = str(d)
>>> s
"{1: 'a', 2: 'b'}"
>>> ast.literal_eval(s)
{1: 'a', 2: 'b'}
>>> type(ast.literal_eval(s))
<type 'dict'>