来自多个HDF5文件/数据集的链数据集

时间:2016-02-21 09:12:10

标签: python arrays numpy dataset h5py

h5py(通过HDF5)为磁盘上的持久数据集提供的优势和简单映射非常出色。我对一组文件运行一些分析,并将结果存储到一个数据集中,每个文件一个。在这一步结束时,我有一组包含2D数组的h5py.Dataset个对象。这些数组都有相同数量的列,但行数不同,即(A,N),(B,N),(C,N)等。

我现在想要将这些多个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.viewnumpy.concatenate的任何合适的选项,这些选项可以在不复制数据的情况下工作。

是否有人知道如何将多个数组视为堆叠数组,而无需复制h5py.Dataset

1 个答案:

答案 0 :(得分: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继承并获得所有常用方法。