使用 Python 在 HDF5 文件中查找特定值的所有路径的最有效方法是什么?
What is the most efficient way to find all paths to particular values in HDF5 file with Python?
我正在具有以下体系结构的 .hdf5 文件中查找负值:
- Incidence_0
- Wavelength_0
- (Table of size m * n)
- Wavelength_1
- (Table of size m * n)
...
- Incidence_1
...
...
我的objective是找出每一个负值,并取回它在文件中的确切位置(即入射数,波长数,以及它在关联table).
很抱歉,我无法提供最小的可重现示例,因为我无法提供我正在使用的文件,但这是我的想法。
import h5py
file = h5py.File('testFile.hdf5', 'r')
result = []
for incidence in range(nbIncidence):
for wavelength in range(nbWavelength):
for theta in range(nbTheta):
for phi in range(nbPhi):
value = file['Incidence_' + str(incidence)]['Wavelength_' + str(wavelength)][theta, phi]
if (value < 0):
result.append([value, incidence, wavelength, theta, phi])
这是完美的工作,但使用四个循环很耗时,尤其是如果我必须处理大文件,这可能会发生...我对 h5py 库了解不够,但我很确定它存在一种比那更快的方法。
首先,坏消息是:h5py
没有按照您描述的方式查询数据的功能。好消息:您可以通过将每个 Incident/Wavelength 数据集提取到一个 NumPy 数组,然后结合 2 个 NumPy 方法对提取的数组进行操作来完成您的任务。 [注意:这假设您有足够的内存来加载每个数据集。]
关于处理这些数据的一些观察(以帮助您效仿我的示例)。
- HDF5 文件架构是 self-describing。所以你不需要遍历整数计数器。相反,您可以使用
.keys()
方法获取组和数据集名称。 (或者,您可以使用 .items()
方法获得 (name, object)
个元组。)
- 我强烈建议您使用 Python 的文件上下文管理器,以确保您不会
退出时保持文件打开。
- 使用标准的 numpy 切片符号将数据集中的数据读入 numpy 数组。空元组检索所有数据。在您的架构中使用以下内容:
arr = file['Incidence_#']['Wavelength_#'][()]
- 根据您指定的条件创建一个新的布尔数组。使用
arr < 0
将 return True
用于所有负值(和 False
用于其他值)。
- 使用
np.argwhere
查找数组元素索引 non-zero。在布尔数组上使用它(记住 True 是 non-zero,False 是零)。
- 从那里,您可以遍历索引以提取所需的数据。 :-)
我创建了一个模仿您的架构的简单示例来演示该过程。为了完整起见,该代码在最后。这是一个小文件,不会让您埋没在输出中。
下面的代码读取数据、查找负值并将数据添加到列表中。它有几个打印语句,因此您可以看到每个步骤是如何工作的。一旦您对程序有信心,就不需要它们了。
with h5py.File('testFile.hdf5', 'r') as h5fr:
result = []
for i_grp in h5fr.keys():
for wave_ds in h5fr[i_grp].keys():
wave_arr = h5fr[i_grp][wave_ds][()]
neg_idx = np.argwhere(wave_arr < 0.0)
wave_res = []
for n in neg_idx:
i, j = n[0], n[1]
result.append([wave_arr[i,j], i_grp, wave_ds, i, j])
wave_res.append([wave_arr[i,j], i_grp, wave_ds, i, j])
print(f'\nResults for {i_grp}; {wave_ds}:')
print(wave_res)
创建上面使用的示例文件的代码:
nbIncidence = 4
nbWavelength = 6
m, n = 10, 10 # m,n same as nbTheta, nbPhi??
with h5py.File('testFile.hdf5', 'w') as h5fw:
for i_cnt in range(nbIncidence):
grp = h5fw.create_group('Incidence_' + str(i_cnt))
for w_cnt in range(nbWavelength):
arr = np.random.uniform(low=-1.0, high=10.0, size=(m,n)) #.reshape(m,n)
grp.create_dataset('Wavelength_' + str(w_cnt), data=arr)
我正在具有以下体系结构的 .hdf5 文件中查找负值:
- Incidence_0
- Wavelength_0
- (Table of size m * n)
- Wavelength_1
- (Table of size m * n)
...
- Incidence_1
...
...
我的objective是找出每一个负值,并取回它在文件中的确切位置(即入射数,波长数,以及它在关联table).
很抱歉,我无法提供最小的可重现示例,因为我无法提供我正在使用的文件,但这是我的想法。
import h5py
file = h5py.File('testFile.hdf5', 'r')
result = []
for incidence in range(nbIncidence):
for wavelength in range(nbWavelength):
for theta in range(nbTheta):
for phi in range(nbPhi):
value = file['Incidence_' + str(incidence)]['Wavelength_' + str(wavelength)][theta, phi]
if (value < 0):
result.append([value, incidence, wavelength, theta, phi])
这是完美的工作,但使用四个循环很耗时,尤其是如果我必须处理大文件,这可能会发生...我对 h5py 库了解不够,但我很确定它存在一种比那更快的方法。
首先,坏消息是:h5py
没有按照您描述的方式查询数据的功能。好消息:您可以通过将每个 Incident/Wavelength 数据集提取到一个 NumPy 数组,然后结合 2 个 NumPy 方法对提取的数组进行操作来完成您的任务。 [注意:这假设您有足够的内存来加载每个数据集。]
关于处理这些数据的一些观察(以帮助您效仿我的示例)。
- HDF5 文件架构是 self-describing。所以你不需要遍历整数计数器。相反,您可以使用
.keys()
方法获取组和数据集名称。 (或者,您可以使用.items()
方法获得(name, object)
个元组。) - 我强烈建议您使用 Python 的文件上下文管理器,以确保您不会 退出时保持文件打开。
- 使用标准的 numpy 切片符号将数据集中的数据读入 numpy 数组。空元组检索所有数据。在您的架构中使用以下内容:
arr = file['Incidence_#']['Wavelength_#'][()]
- 根据您指定的条件创建一个新的布尔数组。使用
arr < 0
将 returnTrue
用于所有负值(和False
用于其他值)。 - 使用
np.argwhere
查找数组元素索引 non-zero。在布尔数组上使用它(记住 True 是 non-zero,False 是零)。 - 从那里,您可以遍历索引以提取所需的数据。 :-)
我创建了一个模仿您的架构的简单示例来演示该过程。为了完整起见,该代码在最后。这是一个小文件,不会让您埋没在输出中。
下面的代码读取数据、查找负值并将数据添加到列表中。它有几个打印语句,因此您可以看到每个步骤是如何工作的。一旦您对程序有信心,就不需要它们了。
with h5py.File('testFile.hdf5', 'r') as h5fr:
result = []
for i_grp in h5fr.keys():
for wave_ds in h5fr[i_grp].keys():
wave_arr = h5fr[i_grp][wave_ds][()]
neg_idx = np.argwhere(wave_arr < 0.0)
wave_res = []
for n in neg_idx:
i, j = n[0], n[1]
result.append([wave_arr[i,j], i_grp, wave_ds, i, j])
wave_res.append([wave_arr[i,j], i_grp, wave_ds, i, j])
print(f'\nResults for {i_grp}; {wave_ds}:')
print(wave_res)
创建上面使用的示例文件的代码:
nbIncidence = 4
nbWavelength = 6
m, n = 10, 10 # m,n same as nbTheta, nbPhi??
with h5py.File('testFile.hdf5', 'w') as h5fw:
for i_cnt in range(nbIncidence):
grp = h5fw.create_group('Incidence_' + str(i_cnt))
for w_cnt in range(nbWavelength):
arr = np.random.uniform(low=-1.0, high=10.0, size=(m,n)) #.reshape(m,n)
grp.create_dataset('Wavelength_' + str(w_cnt), data=arr)