如何在不制作任何中间副本的情况下将多维h5py数据集复制到平面1D Python列表?

时间:2015-06-23 03:03:53

标签: python numpy protocol-buffers hdf5 h5py

问题

如何将N x N x N x... h5py数据集中的数据复制到1D标准Python列表而不制作数据的中间副本?

我可以想到使用中间副本执行此操作的几种不同方法。例如:

import h5py
import numpy as np

# initialize list, put some initial data in it
myList = ['foo']

# open up an h5py dataset from a file on disk
myFile = h5py.File('/path-to-my-data', 'r')
myData = myFile['bar']
myData.shape        # returns, for example, (5,15,7)

# copy dataset over to a numpy array
arr = np.zeros(myData.shape)
myData.read_direct(arr)

# finally, add data from copied dataset to myList
myList.extend(arr.flatten())

这可以在没有中间副本到numpy数组的情况下完成吗?

一些背景

(除非你很好奇,否则你绝对不必阅读此内容)

我正在尝试通过他们的Python API将数据从HDF5文件复制到Protocol Buffers文件。这些都是用于编写自己的复杂可序列化数据结构的库/框架。就他们的Python API而言,HDF5假装其阵列是numpy数组,而Protocol Buffers假装其数组是标准的1D Python列表(遗憾的是,对于简单的多维数组,协议缓冲区没有本机支持)。因此我需要从h5py数据集转换为Python列表。

修改

有人要求澄清我的意思

  

HDF5假装其数组是numpy数组,而Protocol Buffers假装其数组是标准的1D Python列表

我的意思是h5py数据集向用户公开类似于numpy数组公开的接口的接口,并且Python Protobuf重复的数字字段公开了一个类似于标准Python列表的接口。但是,它们都没有实现其原型的完整行为,甚至是完整的接口。例如,h5py数据集没有.flatten()方法,如果您尝试将其他列表指定为元素,则Pybuf重复字段会抱怨(例如myBuf.repIntField[2] = [1,2,3]将始终引发错误)。

以下是Pybuf documentation

中的相关行
  

重复字段表示为一个像Python序列一样的对象。

来自h5py documentation的相关行(强调添加):

  

数据集与NumPy数组非常相似。它们是数据元素的同源集合,具有不可变数据类型和(超)矩形形状。 与NumPy数组不同,它们支持各种透明存储功能,如压缩,错误检测和分块I / O.

1 个答案:

答案 0 :(得分:1)

对于numpy数组,我建议使用ndarray.flat,但h5py数据集没有flat / flatten属性。

你可以创建一个生成器,它将块作为numpy数组带入内存,然后从展平值中产生值。然后可以将其转换为列表。例如,只是沿外部维度块:

def yield_chunks(x):
    for chunk in iter(x):
        yield chunk.flat

myGenerator = itertools.chain(yield_chunk(arr))

myGenerator将从arr生成单个值。您将其转换为list(myGenerator)的列表。