使用h5py从生成器向H5文件追加结构化数组失败求助
使用h5py追加结构化数组数据失败排查
我尝试用h5py向数据集追加数据,但一直没成功,想找出问题所在。numpy_arr是一个生成器,用来产出结构化numpy数组,相关代码如下:
import h5py import numpy as np dt_vlstr = h5py.string_dtype(encoding='utf-8') dt_vlstr_arr = h5py.vlen_dtype(dt_vlstr) dt_int = np.dtype('i4') constructor = { 'names':['ark','dates','events','iso639','views','dublincore','catch_word','colors', 'bw'], 'formats': [ dt_vlstr, #ark dt_vlstr_arr, #dates dt_vlstr_arr, #events dt_vlstr_arr, #iso639 dt_int, #lecture dt_vlstr, #dublincore dt_vlstr_arr, #catch_word dt_int, #colors dt_int, #bw ]} compound = np.dtype(constructor) def mapping2numpy(generators): for i in (generators): numpy_arr = np.array([( i['ark'], i['dates'].astype(dt_vlstr), i['events'].astype(dt_vlstr), i['iso639'].astype(dt_vlstr), i['views'], i['dublincore'], i['catch_word'].astype(dt_vlstr), i['colors'], i["bw"])],dtype=compound) yield numpy_arr numpy_arr = mapping2numpy(data) with h5py.File('file.h5', 'w') as h5f: group = h5f.create_group('metadata') dataset = group.create_dataset('records', (1,1), maxshape=(None,1), compression="lzf", dtype=compound, fletcher32=True, chunks=(1,1)) with h5py.File('file.h5', 'a') as h5f: dset = h5f['metadata/records'] for data in numpy_arr: dset.resize( (dset.shape[0]+1, 1) ) dset[-1,:] = data
问题排查与修正
核心问题点
- 维度不匹配:创建数据集时用了二维形状
(1,1),但生成器产出的是(1,)的一维数组,赋值dset[-1,:] = data时形状不兼容。 - 冗余数组嵌套:生成器每次产出
(1,)的数组,没必要多套一层,直接产出单个结构化元素更合理。 - 初始数据占位冗余:初始创建的
(1,1)数据集会留下一行空数据,后续追加会导致数据错位。
修正后的代码
import h5py import numpy as np dt_vlstr = h5py.string_dtype(encoding='utf-8') dt_vlstr_arr = h5py.vlen_dtype(dt_vlstr) dt_int = np.dtype('i4') constructor = { 'names':['ark','dates','events','iso639','views','dublincore','catch_word','colors', 'bw'], 'formats': [ dt_vlstr, # ark dt_vlstr_arr, # dates dt_vlstr_arr, # events dt_vlstr_arr, # iso639 dt_int, # views(原注释写错为lecture) dt_vlstr, # dublincore dt_vlstr_arr, # catch_word dt_int, # colors dt_int # bw ]} compound = np.dtype(constructor) def mapping2numpy(generators): for i in generators: # 直接产出单个结构化元素,避免冗余数组嵌套 yield ( i['ark'], i['dates'].astype(dt_vlstr), i['events'].astype(dt_vlstr), i['iso639'].astype(dt_vlstr), i['views'], i['dublincore'], i['catch_word'].astype(dt_vlstr), i['colors'], i["bw"] ) numpy_arr = mapping2numpy(data) # 创建空的一维可扩展数据集 with h5py.File('file.h5', 'w') as h5f: group = h5f.create_group('metadata') dataset = group.create_dataset('records', shape=(0,), maxshape=(None,), compression="lzf", dtype=compound, fletcher32=True, chunks=(1,)) # 追加数据 with h5py.File('file.h5', 'a') as h5f: dset = h5f['metadata/records'] for data in numpy_arr: dset.resize(dset.shape[0] + 1, axis=0) dset[-1] = data # 直接赋值最后一行,形状完全匹配
修正说明
- 调整数据集为一维:结构化数组用一维存储更符合逻辑,避免二维维度带来的形状匹配问题。
- 简化生成器输出:去掉不必要的数组嵌套,直接生成单个结构化元素,赋值更直观。
- 初始创建空数据集:从0行开始追加,避免初始空数据占位导致的冗余。
- 修正注释错误:将原代码中
views的错误注释lecture修正。
内容的提问来源于stack exchange,提问作者Gustave Turrell
相关产品推荐
相关产品推荐

