Python h5py - 为啥我会收到广播错误?
Posted
技术标签:
【中文标题】Python h5py - 为啥我会收到广播错误?【英文标题】:Python h5py - Why do I get a broadcast error?Python h5py - 为什么我会收到广播错误? 【发布时间】:2021-09-12 12:51:35 【问题描述】:我正在尝试读取一个 .h5 文件 data.h5
,它有 2 个数据集,“数据”和“元数据”。 'metaData' 包含一个 157x1 的字典,如下所示:
然后,我正在尝试编写一个新的 .h5 文件,其中包含 3 列:字典中每个变量的数字、名称(字典的第一列)和单位(字典的最后一列)。这是代码:
import numpy as np
import h5py as h5
hdf = h5.File('data.h5','r')
data1 = hdf.get('Data')
data2 = hdf.get('metaData')
dataset1 = np.array(data1)
dataset2 = np.array(data2)
#dictionary
hdfdic = dict(hdf['metaData'])
dic = hdfdic.get('dictionary')
dictionary = np.array(dic)
#write new h5 file
with h5.File('telemetry.h5', 'w') as var:
dt = np.dtype( [('n°', int), ('Variable name', 'S10'), ('Unit', 'S10')] )
dset = var.create_dataset( 'data', dtype=dt, shape = (len(dictionary),))
dset['n°'] = np.arange(len(dictionary))
dset['Variable name'] = [val[1] for val in dictionary[:][0][0]]
dset['Unit'] = [val[2] for val in dictionary[:][0][-1]]
data = dset[:]
print(data)
我得到错误:
Traceback (most recent call last):
File "c:/Users/user/Desktop/new/code.py", line 28, in <module>
dset['Variable name'] = [val[1] for val in dictionary[:][0][0]]
File "h5py\_objects.pyx", line 54, in h5py._objects.with_phil.wrapper
File "h5py\_objects.pyx", line 55, in h5py._objects.with_phil.wrapper
File "C:\Users\user\Anaconda3\envs\py38\lib\site-packages\h5py\_hl\dataset.py", line 707, in __setitem__
for fspace in selection.broadcast(mshape):
File "C:\Users\user\Anaconda3\envs\py38\lib\site-packages\h5py\_hl\selections.py", line 299, in broadcast
raise TypeError("Can't broadcast %s -> %s" % (target_shape, self.mshape))
TypeError: Can't broadcast (4,) -> (157,)
有什么问题?
【问题讨论】:
dictionary
是一个 numpy 数组。用[:]
对其进行索引没有任何作用。您可能想使用dictionary[:,0,0]
。但这只是猜测,因为我对此了解不多。
【参考方案1】:
正如@hpaulj 所说,h5py 将 HDF5 数据集作为 NumPy 数组返回。一开始可能会让人感到困惑——h5py 使用 Python 的字典语法来引用 HDF5 对象(组和数据集),但它们不是字典!你的尝试是在正确的轨道上。您需要修改它以将来自 hdf['metaData']
的数据作为 NumPy 数组而不是列表来处理。
下面的示例应该可以工作。由于我没有起始文件 (data.h5
),因此我创建了一个文件来复制图像中的值。创建该文件的代码在最后。
注意 1:如果没有使用 '°'
作为学位,这个例子会更简单。这增加了处理字符串数据的额外步骤。这就是我使用np.char.decode()
打印dset['Variable name']
和dset['Unit']
的原因。更多关于以下内容。
注意 2:使用硬编码字符串大小时要小心。 ('Variable name', 'S10')
来自较早问题的答案(字符串较短)。下面的代码从hdf['metaData']
数据集dtype 中获取大小,然后在telemetry.h5
中定义用于新数据集的dtype 时使用它。
with h5.File('data.h5','r') as hdf:
#read dataset as a numpy array metaData, it is not a dictionary
metaData = hdf['metaData'][:]
print('dtype is:',metaData.dtype)
#write new h5 file
with h5.File('telemetry.h5', 'w') as var:
dt = np.dtype( [('n°', int), ('Variable name', metaData.dtype), ('Unit', metaData.dtype)] )
dset = var.create_dataset( 'data', dtype=dt, shape=(len(metaData),))
dset['n°'] = np.arange(metaData.shape[0])
dset['Variable name'] = metaData[:,0] # use first column of metaData
dset['Unit'] = metaData[:,-1] # use last column of metaData
for row in dset:
print(row[0], np.char.decode(row[1]), np.char.decode(row[2]))
这是我为模仿data.h5
而编写的代码。当您打印原始数据(作为字节字符串)时,您会看到b'\xc2\xb0'
,您期望'°'
表示度数单位。使用 h5py 的那个字符有一些复杂性。在 Python 和 NumPy 中很好。但是,h5py(和 HDF5)不支持 NumPy 的 Unicode 数据类型;您需要使用 Numpy 字节数组('S' dtype)。这就是为什么我在使用 h5py 保存之前使用 np.char.encode()
将数组 arr
编码为 arr2
。这就是为什么在打印上面的dset['Variable name']
和dset['Unit']
时需要np.char.decode()
的原因——您必须将编码的字符串字节数据解码回Unicode。
arr = np.array( \
[['ADC_ALT_TC', 'ADC_ALT_TC', 'ADC.ALT:TC [ft]', 'ft'],
['ADC_AOA_TC', 'ADC_AOA_TC', 'ADC.AOA:TC [°]', '°'],
['ADC_AOS_TC', 'ADC_AOS_TC', 'ADC.AOS:TC [°]', '°'],
['ADC_CAS_TC', 'ADC_CAS_TC', 'ADC.CAS:TC [kts]', 'kts'],
['ADC_OAT_TC', 'ADC_OAT_TC', 'ADC.OAT:TC [°]'., '°'],
['ADC_SpeedWarning_TC', 'ADC_SpeedWarning_TC','ADC_SpeedWarning:TC', ''],
['ADC_Stall_TC', 'ADC_Stall_TC','ADC_Stall:TC', ''],
['ADC_TAS_TC', 'ADC_TAS_TC', 'ADC.TAS:TC [kts]', 'kts'],
['AHRS1_accX_TC', 'AHRS1_accX_TC', 'AHRS1.accX:TC [m/s^2]', 'm/s^2'],
['AHRS1_accY_TC', 'AHRS1_accY_TC', 'AHRS1.accX:TC [m/s^2]', 'm/s^2'],
['AHRS1_accZ_TC', 'AHRS1_accZ_TC', 'AHRS1.accX:TC [m/s^2]', 'm/s^2'] ]
print(arr)
arr2 = np.char.encode(arr)
print(arr2)
with h5.File('data.h5','w') as hdf:
hdf.create_dataset('metaData',data=arr2)
以下是一些参考资料,供需要有关底层 HDF5/h5py 要求或 Unicode 和字符串字节之间的编码/解码的更多详细信息的人参考:
Strings in HDF5 - Encodings Conversion from U3 dtype to ascii How to convert type from “str” to “numpy.string_” of each ndarray items?【讨论】:
以上是关于Python h5py - 为啥我会收到广播错误?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 h5py 在向数据集添加 3 个可变长度字符串时会抛出错误?