【问题标题】:How to read data from hdf5(h5py) saved as recarray with different types?如何从保存为不同类型的recarray的hdf5(h5py)读取数据?
【发布时间】:2019-12-19 00:01:27
【问题描述】:

我正在尝试从 hdf5 文件中读取数据 - 我之前使用 recarray 保存到它。 一行数据的类型如下:2x u2(flags) 后跟 2x u4(timestamps) 和 32x u2(data)。

self.flags = np.empty((self.size, 2), dtype="u2")
self.t0 = np.empty(self.size, dtype="u4")
self.t1 = np.empty(self.size, dtype="u4")
self.data = np.empty((self.size, 32), dtype="u2")
...
labels = ['lost events','overwritten events', 't0', 't1'] + ["data_{0}".format(i) for i in range(32)]
result_arr = np.rec.fromarrays(tuple(self.flags.T)+(self.t0, self.t1) + tuple(self.data.T), names=labels)
file.create_dataset('dataset_name', data=result_arr)

现在我想逐行迭代这个文件的一部分(数据部分 - 最后 32 列),并能够像通常的 numpy.array 一样处理它。

data = self.dataset[row_n]
def parseDataToFlags(data):
    return np.array(list(data)[4:36], dtype="u2")

这是有效的,但非常缓慢。我正在寻找一种正确的方法来执行此操作,因为我将处理大数据文件。 我也试图弄乱这个:(self.dataset 是从文件加载的 h5py 数据集)

    def get(self, index):
        if not (0 <= index < self.n_of_rows):
            raise IndexError
        return type(self.dataset['t0', 't1'][index])

但是当我尝试将 [data_{0}".format(i) for i in range(32)] 代替 't0','t1' 时它失败了。

我多次尝试将数据解析为结构化数组,但到目前为止都没有成功。

我应该如何正确地尝试阅读过程?我应该更改访问顺序(行前的列)还是有办法在读取行后将这些数据解析为正确的类型?

更新 我得到了一些帮助,结果如下: 我的代码中如此缓慢的不是为每一行创建列表并解析为 numpy 数组。访问 h5py 文件中的数据是。所以最好一次访问它并一次解析它们。

self.flags = np.vstack((self.dataset['lost events'], self.dataset['overwritten events'])).T
self.time = np.vstack((self.dataset['t0'], self.dataset['t1'])).T
self.output = np.vstack([self.dataset['data_'+str(i)] for i in range(32)]).T

一旦我使用了该代码,它的速度几乎提高了 1000 倍。

【问题讨论】:

  • Earwin,请澄清一下,“_self.dataset 是一个 h5py 数据集_”。您从h5pyFile() 获得一个文件对象/句柄(如上面代码中的self)。使用h5py,可以使用 h5file 对象和数据集名称访问数据集:self['dset_name']。从那里,您可以使用 numpy 切片符号来获取感兴趣的行和列,如下所示:self['dset_name'][4:36,'col_i_name','col_j_name','col_k_name']
  • 考虑修改主题标签以添加 [hdf5] 和 [h5py] 以提高问题的可见性。
  • @kcw78 self.dataset 通过 self.dataset = h5pyfile['dataset'] 初始化。我不熟悉这种切片 [4:36,'col_i_name','col_j_name','col_k_name']。 col_*_name 代表什么?他们会给我在 4:36 得到的列命名还是我弄错了?
  • 我指的是您使用labels = [ ] 创建的不同文件名,例如:'t0', 'data_0', 'data_1' 等。请查看下面的答案以获取 hpaulj 示例的扩展版本。它添加更多字段和数据,然后显示如何按行号或字段名称切片

标签: python numpy hdf5 h5py structured-array


【解决方案1】:

这个答案扩展了 hpaulj 的例子。它添加更多字段和数据,创建 HDF5 文件,然后打开以按行号和/或字段名称读取和切片。我使用h5fwh5fr 来显示我正在写入和读取不同的文件句柄/对象。通常我不会这样做。

注意print (arr#.dtype) 是如何特定于切片数据的(arr1.dtypearr2.dtype 不同)。

import numpy as np
import h5py

# create HDF5 file and add a dataset:
with h5py.File('SO_57460643.h5','w') as h5fw:

    labels = ['lost events','overwritten events', 't0', 't1'] + ["data_{0}".format(i) for i in range(4)]
    dt = np.dtype({'names': labels,
                   'formats': ['u2']*2 + ['u4']*2 + ['u4']*4 })
    nrows=5
    ncols=8                                               
    d = np.zeros(nrows, dt)
    for row in range(nrows) :
        arr_tup = tuple(range(row*ncols,(row+1)*ncols))
        d[row] = arr_tup
    #print (d)
    h5fw.create_dataset('ds_name', data=d)

# open HDF5 for reading only:
with h5py.File('SO_57460643.h5','r') as h5fr:

#  get last row
    arr1 = h5fr['ds_name'][-1]
    print (arr1.dtype)
    print (arr1)

 #  get rows 1-3, fields t0, data_0, data_1, data_2, data_3
    arr2 = h5fr['ds_name'][1:4,'t0', 'data_0', 'data_1', 'data_2', 'data_3']
    print (arr2.dtype)
    print (arr2)

【讨论】:

  • 感谢您的回答。有什么方法可以避免显式地写入 'data_0', ... ,'data_3' 而是生成名称?因为这是我面临的问题之一
  • 澄清一下,您想获取我在arr2 = h5fr['ds_name']=[1:4, 't0'...] 中使用的字段名称,对吗?简短的回答,是的,您可以像获取 numpy recarray 的字段名称一样获取它们。试试上面的文件:print (h5fr['ds_name'].dtype.names)。如果您想要组名称,请使用 keys() 属性:print (h5fr.keys()) 将返回 &lt;KeysViewHDF5 ['ds_name']&gt;
【解决方案2】:

我认为使用具有复合 dtype 的结构化数组,您的任务会更简单,例如:

In [86]: dt = [('events','u2'),('t0','u4'),('t1','u4'),('data','u2',32)]                                     
In [87]: d = np.zeros(3, dt)                                                                                 
In [88]: d                                                                                                   
Out[88]: 
array([(0, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
       (0, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
       (0, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])],
      dtype=[('events', '<u2'), ('t0', '<u4'), ('t1', '<u4'), ('data', '<u2', (32,))])

data 可以作为一个二维数组访问:

In [89]: d['data']                                                                                           
Out[89]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint16)

【讨论】:

  • 我要仔细检查一下,但我想我是这样尝试的,但得到了错误:“结构必须具有相同的大小”。
猜你喜欢
  • 2016-06-05
  • 2020-04-16
  • 2021-05-14
  • 2015-04-09
  • 2016-03-29
  • 1970-01-01
  • 2015-04-17
  • 2018-03-06
  • 2019-08-02
相关资源
最近更新 更多