与 h5py 和 create_dataset 相关的问题

Posted

技术标签:

【中文标题】与 h5py 和 create_dataset 相关的问题【英文标题】:problem related to h5py and create_dataset 【发布时间】:2021-12-22 07:12:57 【问题描述】:

也许这个问题很愚蠢,但到目前为止我还没有找到解决方案。 我收到了来自其他人的代码,他可能正在使用与我不同的集合(例如 Python 2 而不是 3 等)。 所以我做了一些小改动以使事情正常进行,但我陷入了与 h5py 相关的一个可能简单的问题。

它崩溃的代码部分如下所示:

labels_ALL = ['ionic_str','psi0','psi1','psi2','psid','zeta','sig0','sig1','sig2','sigd','sig0_eq','sig1_eq','sig2_eq','sigd_eq','ch_bal_EDL','ch_bal_aq', 'sum_resid']
units_ALL = ['(mol/L)','(V)','(V)','(V)','(V)','(V)','(C/m**2)','(C/m**2)','(C/m**2)','(C/m**2)','(mol(eq))','(mol(eq))','(mol(eq))','(mol(eq))','(C/m**2)','(mol(eq)/L)',' ']
for i in range(len(Labels)):
    labels_ALL.append(Labels[i])
    units_ALL.append('(mol/L)')
base.create_dataset('Labels', data=labels_ALL)
base.create_dataset('Units', data=units_ALL)

问题似乎出在base.create_dataset:

Traceback (most recent call last):

  File "C:\Users\DaniJ\Documents\PostDoc_Jena\Trips, Conf, etc\Sinfonia Workshop\Exercise_1\exercise_1_SINFONIA_for_One\NR_chem_SINGLE_NoEu.py", line 252, in <module>
    base.create_dataset('Labels', data=labels_ALL)

  File "C:\Users\DaniJ\anaconda3\lib\site-packages\h5py\_hl\group.py", line 136, in create_dataset
    dsid = dataset.make_new_dset(self, shape, dtype, data, **kwds)

  File "C:\Users\DaniJ\anaconda3\lib\site-packages\h5py\_hl\dataset.py", line 118, in make_new_dset
    tid = h5t.py_create(dtype, logical=1)

  File "h5py\h5t.pyx", line 1634, in h5py.h5t.py_create

  File "h5py\h5t.pyx", line 1656, in h5py.h5t.py_create

  File "h5py\h5t.pyx", line 1717, in h5py.h5t.py_create

TypeError: No conversion path for dtype: dtype('<U10')

变量 base 似乎是一个 h5py._hl.files.File 变量。

有人可以解决这个问题吗?

谢谢

最好的问候, 丹妮

【问题讨论】:

错误信息 (No conversion path for dtype: dtype('&lt;U10')) 指的是 HDF5(和 h5py)不支持的 Unicode 字符。您必须在保存之前将 Unicode 转换为字节字符串。您的代码未显示 labels 值的分配,因此我无法重现该问题。如果我注释掉 for i in range(): 循环,代码就可以工作,并且只将 labels_ALLunits_ALL 的原始值保存到数据集中。 标签基本上是一个字符串列表,例如Labels = ['H+','Na+','Cl-','OH-','&gt;SOH_x','&gt;SO-_x','&gt;SONa_x','&gt;SOH2+_x','&gt;SOH2Cl_x','&gt;SOH_y','&gt;SO-_y','&gt;SONa_y'] 嗯...不是我对Labels 的期望。 :-( 如果 Labels 是 NumPy 字符串数组,您将收到 dtype('&lt;U10') 错误。当我添加该行(并包含 for 循环)时,您的代码按预期工作。如果我转换,我可以重现该错误List 到 NumPy 数组。 【参考方案1】:

你的问题解决了吗?我 99.9% 确定它与您的 Labels 数据有关——可能它位于 NumPy 数组而不是列表中。我写了 3 个简短的例子来说明区别。

    第一个代码段使用 List 并成功创建 文件SO_69900543_1.h5中的数据集。 第二个代码段重现了您的错误。它转换列表 到 NumPy 数组然后在尝试创建数据集时失败 在文件SO_69900543_2.h5。请注意,它给出了相同的错误 您遇到的消息:TypeError: No conversion path for dtype: dtype('&lt;U10')。 第三个代码段显示如何将numpy.str_ 元素修改为str(解决段#2 中的问题)。请注意,每个Labels 的值在添加到Labels_All 之前都会使用str() 进行转换。

也许这会帮助您找到(并解决)您的 Unicode 数据问题。

代码段 1(有效):

Labels = ['H+','Na+','Cl-','OH-','>SOH_x','>SO-_x','>SONa_x','>SOH2+_x','>SOH2Cl_x','>SOH_y','>SO-_y','>SONa_y']
labels_ALL = ['ionic_str','psi0','psi1','psi2','psid','zeta','sig0','sig1','sig2','sigd','sig0_eq','sig1_eq','sig2_eq','sigd_eq','ch_bal_EDL','ch_bal_aq', 'sum_resid']
units_ALL = ['(mol/L)','(V)','(V)','(V)','(V)','(V)','(C/m**2)','(C/m**2)','(C/m**2)','(C/m**2)','(mol(eq))','(mol(eq))','(mol(eq))','(mol(eq))','(C/m**2)','(mol(eq)/L)',' ']

for i in range(len(Labels)):
    labels_ALL.append(Labels[i])
    units_ALL.append('(mol/L)')
with h5py.File('SO_69900543_1.h5','w') as base:
    base.create_dataset('Labels', data=labels_ALL)
    base.create_dataset('Units', data=units_ALL)

代码段 2(返回 TypeError):

Labels = ['H+','Na+','Cl-','OH-','>SOH_x','>SO-_x','>SONa_x','>SOH2+_x','>SOH2Cl_x','>SOH_y','>SO-_y','>SONa_y']
# Convert Labels List to NumPy array 
# This will trigger the error when creating the dataset
Labels = np.array(Labels)
labels_ALL = ['ionic_str','psi0','psi1','psi2','psid','zeta','sig0','sig1','sig2','sigd','sig0_eq','sig1_eq','sig2_eq','sigd_eq','ch_bal_EDL','ch_bal_aq', 'sum_resid']
units_ALL = ['(mol/L)','(V)','(V)','(V)','(V)','(V)','(C/m**2)','(C/m**2)','(C/m**2)','(C/m**2)','(mol(eq))','(mol(eq))','(mol(eq))','(mol(eq))','(C/m**2)','(mol(eq)/L)',' ']

for i in range(len(Labels)):
    labels_ALL.append(Labels[i])
    units_ALL.append('(mol/L)')

for i in range(len(labels_ALL)):   
    print(i, type(labels_ALL[i]), type(units_ALL[i]))

with h5py.File('SO_69900543_2.h5','w') as base:
    base.create_dataset('Labels', data=labels_ALL)
    base.create_dataset('Units', data=units_ALL)  

代码段 3(有效):

Labels = ['H+','Na+','Cl-','OH-','>SOH_x','>SO-_x','>SONa_x','>SOH2+_x','>SOH2Cl_x','>SOH_y','>SO-_y','>SONa_y']
# Convert Labels List to NumPy array 
# This will trigger the error when creating the dataset if not modified
Labels = np.array(Labels)
labels_ALL = ['ionic_str','psi0','psi1','psi2','psid','zeta','sig0','sig1','sig2','sigd','sig0_eq','sig1_eq','sig2_eq','sigd_eq','ch_bal_EDL','ch_bal_aq', 'sum_resid']
units_ALL = ['(mol/L)','(V)','(V)','(V)','(V)','(V)','(C/m**2)','(C/m**2)','(C/m**2)','(C/m**2)','(mol(eq))','(mol(eq))','(mol(eq))','(mol(eq))','(C/m**2)','(mol(eq)/L)',' ']

for i in range(len(Labels)):
    # use str() to convert from 'numpy.str_' to 'str'
    labels_ALL.append(str(Labels[i])) 
    units_ALL.append('(mol/L)')

for i in range(len(labels_ALL)):   
    print(i, type(labels_ALL[i]), type(units_ALL[i]))
    
with h5py.File('SO_69900543_2.h5','w') as base:
    base.create_dataset('Labels', data=labels_ALL)
    base.create_dataset('Units', data=units_ALL)    

【讨论】:

谢谢,太完美了!! 你好丹尼尔。很高兴这有帮助。如果它解决了您的问题,请检查已接受的答案以表明它是解决方案。问候。

以上是关于与 h5py 和 create_dataset 相关的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 h5py(或其他方法)有效地保存和加载数据

使用 H5Py 在 HDF5 中存储日期时间

如何使用“h5py”调整 HDF5 数组的大小

通过 h5py (HDF5) 写入具有可变长度字符串的复合数据集

2.7 序列化(保存)tensor

将 scipy 稀疏矩阵存储为 HDF5