Python 如何使用h5py将数据写入复合数据?

Python 如何使用h5py将数据写入复合数据?,python,numpy,h5py,Python,Numpy,H5py,我知道在c中,我们可以使用struct类型轻松地构造一个复合数据集,并逐块分配数据。我目前正在用h5py在Python中实现类似的结构 import h5py import numpy as np # we create a h5 file f = h5py.File("test.h5") # default is mode "a" # We define a compound datatype using np.dtype dt_type = np.dtype({"names":["

我知道在
c
中,我们可以使用
struct
类型轻松地构造一个复合数据集,并逐块分配数据。我目前正在用
h5py
Python
中实现类似的结构

import h5py
import numpy as np 

# we create a h5 file 
f = h5py.File("test.h5") # default is mode "a"


# We define a compound datatype using np.dtype
dt_type = np.dtype({"names":["image","feature"],
                   "formats":[('<f4',(4,4)),('<f4',(10,))]})

# we define our dataset with 5 instances
a = f.create_dataset("test", shape=(5,), dtype=dt_type)

输出为

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.]], dtype=float32)

# Write 1s to data field "feature"
a["feature"] = np.ones((5,10))

array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float32)

问题是当我将2D数组“image”写入文件时

a["image"] = np.ones((5,4,4))

ValueError: When changing to a larger dtype, its size must be a divisor of the total size in bytes of the last axis of the array.
我阅读了文档并做了研究。不幸的是,我没有找到一个好的解决办法。我知道我们使用
group/dataset
来模拟这个复合数据,但我真的想保留这个结构。有什么好办法吗

任何帮助都将不胜感激。谢谢。

您可以使用PyTables(也称为tables)用所需的数组填充HDF5文件。您应该将每一行视为一个独立的条目(由数据类型定义)。因此,“映像”数组存储为5(4x4)个ndarray,而不是单个(5x4x4)个ndarray。“功能”数组也是如此

此示例将每个“功能”和“图像”数组一次添加一行。或者,您可以创建一个numpy记录数组,其中两个数组都包含多行数据,然后使用Table.append()函数进行添加

请参阅下面的代码以创建文件,然后打开只读以检查数据

import tables as tb
import numpy as np 

# open h5 file for writing
with tb.File('test1_tb.h5','w') as h5f:

# define a compound datatype using np.dtype
    dt_type = np.dtype({"names":["feature","image"],
                        "formats":[('<f4',(10,)) , ('<f4',(4,4)) ] })

# create empty table (dataset)
    a = h5f.create_table('/', "test1", description=dt_type)

# create dataset row interator
    a_row = a.row
# create array data and append to dataset
    for i in range(5):
        a_row['feature'] = i*np.ones(10)
        a_row['image'] = np.random.random(4*4).reshape(4,4)
        a_row.append()

    a.flush()

# open h5 file read only and print contents
with tb.File('test1_tb.h5','r') as h5fr:
    a = h5fr.get_node('/','test1')
    print (a.coldtypes)
    print ('# of rows:',a.nrows)

    for row in a:
        print (row['feature'])
        print (row['image'])
将表作为tb导入
将numpy作为np导入
#打开h5文件进行写入
将tb.File('test1_tb.h5','w')作为h5f:
#使用np.dtype定义复合数据类型
dt_type=np.dtype({“名称”:[“特征”,“图像”],

“格式”:[('这篇博客文章帮助我解决了这个问题:

用于编写复合数据集的关键代码:

import numpy as np
import h5py

# Load your dataset into numpy
audio = np.load(path.join(root_dir, 'X_dev.npy')).astype(np.float32)
text = np.load(path.join(root_dir, 'T_dev.npy')).astype(np.float32)
gesture = np.load(path.join(root_dir, 'Y_dev.npy')).astype(np.float32)

# open a hdf5 file
hf = h5py.File(root_dir+"/dev.hdf5", 'a') 

# create group
g1 = hf.create_group('dev') 

# put dataset in subgroups
g1.create_dataset('audio', data=audio)
g1.create_dataset('text', data=text)
g1.create_dataset('gesture', data=gesture)

# close the hdf5 file
hf.close()  

当我用那个形状和数据类型创建一个数组时,你的
ones
赋值有效。a['image']=np.ones((5,4,4),'f4')
work?
np。默认情况下,
可能会生成
float64
,而
h5py
无法将其转换为
float32
。也许稍后我会尝试使用
h5py
@hpaulj。谢谢您的回复。它不起作用。
dtype
遵循我们在开始时定义的格式。在我们的例子中是这样的
float32
并且分配的值的类型将被强制为float32。我可以用该数据类型和形状创建一个numpy数组,用那些
np.ones
设置其“image”字段,并且
a[:]=arr
工作。另外
a['image'][:]=np.ones((5,4,4))
有效。我的理解是
h5py
使用
cython
代码与
HDF5
C++
API接口。由于numpy数组可以设置字段值,我怀疑我们在这里看到的限制来自HDF5本身,而不是
h5py
开发人员的一些懒惰例如,我们可能需要更多地注意错误消息和位置。
\uuu setitem\uuu
代码是Python。问题可能局限于2d字段。此外,
numpy
在处理多字段索引方面做了一些更改。
import numpy as np
import h5py

# Load your dataset into numpy
audio = np.load(path.join(root_dir, 'X_dev.npy')).astype(np.float32)
text = np.load(path.join(root_dir, 'T_dev.npy')).astype(np.float32)
gesture = np.load(path.join(root_dir, 'Y_dev.npy')).astype(np.float32)

# open a hdf5 file
hf = h5py.File(root_dir+"/dev.hdf5", 'a') 

# create group
g1 = hf.create_group('dev') 

# put dataset in subgroups
g1.create_dataset('audio', data=audio)
g1.create_dataset('text', data=text)
g1.create_dataset('gesture', data=gesture)

# close the hdf5 file
hf.close()