Как динамически назначать столбцы классу PyTables IsDescription? - PullRequest
0 голосов
/ 07 октября 2019

Допустим, у меня есть класс описания PyTables:

In [1]: import tables as tb
        class DataDescr(tb.IsDescription):
            timestamp = tb.Time64Col(pos=0)
            value_b = tb.Float32Col(pos=2)

Теперь я назначаю value_a динамически. Мне нужно сделать это, потому что форма этого столбца зависит от некоторых пользовательских данных.

In [2]: DataDescr.value_a = tb.Float32Col(pos=1, shape=given_shape)

Но при просмотре таблицы, созданной с этим описанием, я не вижу новый столбец.

In [3]: h5file = tb.open_file('goodstuff.h5', mode='w')
        table = h5file.create_table('/', 'data', DataDescr)
        table
Out[3]: /data (Table(0,)) ''
          description := {
          "timestamp": Time64Col(shape=(), dflt=0.0, pos=0),
          "value_b": Float32Col(shape=(), dflt=0.0, pos=1)}
          byteorder := 'little'
          chunkshape := (5461,)

Как я могу это исправить?

1 Ответ

0 голосов
/ 07 октября 2019

Есть несколько вариантов для этого (см. File.create_table()).

Опция 1: Добавить атрибут класса с IsDescription.columns

IsDescription объекты имеютcolumns атрибут, который хранит информацию столбца в словаре, который может использоваться для динамического назначения. Как и в вопросе, начните с наиболее полного класса ...

class DataDescr(tb.IsDescription):
    timestamp = tb.Time64Col(pos=0)
    value_b = tb.Float32Col(pos=2)

..., затем добавьте отсутствующий атрибут.

DataDescr.columns['value_a'] = tb.Float32Col(pos=1, shape=(3, 2))

Вариант 2: Используйте словарьdescription

Вместо описания класса начните с описания словаря ...

data_descr = dict(
    timestamp=tb.Float64Col(pos=1),
    value_b=tb.Float32Col(pos=2),
)

... затем добавьте запись в словарь.

data_descr['value_a'] = tb.Float32Col(pos=1, shape=(3, 2))

Вариант 3: Создать описание типа dum NumPy одновременно

Поскольку типы типов NumPy не поддерживают назначение элементов, этот метод требует одновременного создания описания. Если это проблема, доступны варианты 1 и 2.

data_descr = np.dtype([
    ('timestamp', np.float64),
    ('value_a', (np.float32, (3, 2))),
    ('value_b', np.float32),
])

[Возможно, опасно] Вариант 4. Изменение формы записи в диктовке

Я упомяну последний вариант, что не обязательно поддерживается. Поэтому может быть лучше держаться подальше от этой опции.

После запуска с полным словарем без указания размеров ...

data_descr = dict(
    timestamp=tb.Float64Col(pos=1),
    value_a=tb.Float32Col(pos=1),
    value_b=tb.Float32Col(pos=2),
)

... изменить форму 'value_a' запись.

data_descr['value_a'].shape = (3, 2)

ПРИМЕЧАНИЕ. Это не работает с описаниями классов по незаметным для меня причинам.

class DataDescr(tb.IsDescription):
    timestamp = tb.Time64Col(pos=0)
    value_a = tb.Float32Col(pos=1)
    value_b = tb.Float32Col(pos=2)

DataDescr.columns['value_a'].shape = (3, 2)

h5file = tb.open_file('goodstuff.h5', mode='w')
table = h5file.create_table('/', 'data', DataDescr)

row = table.row
row['value_a'] = np.ones((3, 2)) * 5
row.append()

Результат:

TypeError: invalid type (<class 'numpy.ndarray'>) for column ``value_a``
...