2016-02-21 2 views
3

Преимущества и упрощенное отображение, которое h5py обеспечивает (через HDF5) для сохраняющихся наборов данных на диске, является исключительным. Я запускаю некоторый анализ набора файлов и сохраняю результат в наборе данных, по одному для каждого файла. В конце этого шага у меня есть набор объектов h5py.Dataset, которые содержат 2D-массивы. Все массивы имеют одинаковое количество столбцов, но различное количество строк, т. Е. (A, N), (B, N), (C, N) и т. Д.Целевые наборы данных из нескольких файлов/наборов данных HDF5

Теперь я хотел бы получить доступ к этим множественным 2D-массивы в виде массива 2D массива. То есть, я хотел бы читать их по запросу в виде массива формы (A + B + C, N).

С этой целью классы h5py.Link не помогают, поскольку они работают на уровне узлов HDF5.

Вот некоторый псевдокод:

import numpy as np 
import h5py 
a = h5py.Dataset('a',data=np.random.random((100, 50))) 
b = h5py.Dataset('b',data=np.random.random((300, 50))) 
c = h5py.Dataset('c',data=np.random.random((253, 50))) 

# I want to view these arrays as a single array 
combined = magic_array_linker([a,b,c], axis=1) 
assert combined.shape == (100+300+253, 50) 

Для моих целей, предложения от копирования массивов в новый файл не работает. Я также открыт для решения этого вопроса на уровне numpy, но я не нашел подходящих вариантов с numpy.view или numpy.concatenate, которые будут работать без копирования данных.

Кто-нибудь знает способ просмотра нескольких массивов в виде сложного набора массивов без копирования и от h5py.Dataset?

+1

Объясните больше того, что вы пытаетесь сделать с этими данными («читать по требованию»), и почему нечеткое сцепление (самое очевидное решение) неверно. – hpaulj

+0

Есть ли веская причина не хранить все ваши данные в одном 2D 'Dataset', а затем обращаться к отдельным подмассивам с помощью индексации срезов? –

+0

@ali_m, анализ индивидуальных наборов данных генерируется на основе инкрементного анализа, а иногда создаются новые наборы данных. Если бы мне пришлось конкатенировать и хранить все наборы данных, тогда я должен был бы делать это каждый раз, когда новый набор данных будет создан или изменен. И они могут часто меняться. Кроме того, чтение из отдельных файлов позволяет легко отфильтровать или выбрать наборы данных. Я был бы признателен за понимание того, как сгруппировать наборы данных. – achennu

ответ

0

Прежде всего, я не думаю, что есть способ сделать это, не копируя данные, чтобы вернуть один массив. Насколько я могу судить, невозможно объединить представления numpy в один массив - если, конечно, вы не создаете свою собственную оболочку.

Здесь я демонстрирую концепцию концепции, используя Object/Region references. Основная предпосылка заключается в том, что мы создаем новый набор данных в файле, который представляет собой массив ссылок на составные подмассивы. Сохраняя такие ссылки, подмассивы могут динамически изменять размер, и индексирование обертки всегда будет индексировать правильные подмассивы.

Поскольку это всего лишь доказательство концепции, я не реализовал правильную нарезку, просто очень простое индексирование. Также нет попытки проверить ошибки - это почти наверняка нарушит производство.

class MagicArray(object): 
    """Magically index an array of references 
    """ 
    def __init__(self, file, references, axis=0): 
     self.file = file 
     self.references = references 
     self.axis = axis 

    def __getitem__(self, items): 
     # We need to modify the indices, so make sure items is a list 
     items = list(items) 

     for item in items: 
      if hasattr(item, 'start'): 
       # items is a slice object 
       raise ValueError('Slices not implemented') 

     for ref in self.references: 
      size = self.file[ref].shape[self.axis] 

      # Check if the requested index is in this subarray 
      # If not, subtract the subarray size and move on 
      if items[self.axis] < size: 
       item_ref = ref 
       break 
      else: 
       items[self.axis] = items[self.axis] - size 

     return self.file[item_ref][tuple(items)] 

Вот как вы его используете:

with h5py.File("/tmp/so_hdf5/test.h5", 'w') as f: 
    a = f.create_dataset('a',data=np.random.random((100, 50))) 
    b = f.create_dataset('b',data=np.random.random((300, 50))) 
    c = f.create_dataset('c',data=np.random.random((253, 50))) 

    ref_dtype = h5py.special_dtype(ref=h5py.Reference) 
    ref_dataset = f.create_dataset("refs", (3,), dtype=ref_dtype) 

    for i, key in enumerate([a, b, c]): 
     ref_dataset[i] = key.ref 

with h5py.File("/tmp/so_hdf5/test.h5", 'r') as f: 
    foo = MagicArray(f, f['refs'], axis=0) 
    print(foo[104, 4]) 
    print(f['b'][4,4]) 

Это должно быть довольно тривиально распространить на голубевода индексации (т.е. быть в состоянии справиться с ломтиками), но я не могу видеть как это сделать без копирования данных.

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