一、h5文件创建读取操作及参数介绍
train_h5 = h5py.File("dataset_with_coordinates.h5", 'w')
h5py.File
在创建或打开 HDF5 文件时,除了模式参数(如 'w'
、'r'
等)外,还支持其他参数。以下是常用的参数及其功能:
常用参数
-
name
- 描述:指定 HDF5 文件的路径(必填)。
- 示例:
h5py.File("data.h5", 'w')
-
mode
- 描述:文件打开模式。
- 可选值:
'r'
:只读模式。'r+'
:读写模式,文件必须已存在。'w'
:写模式,文件已存在时会覆盖。'w-'
/'x'
:写模式,若文件已存在则报错。'a'
:追加模式,文件不存在时会创建,存在时保留内容。
- 示例:
h5py.File("data.h5", 'r')
-
driver
- 描述:HDF5 文件的驱动类型,控制底层存储方式。
- 示例:
'core'
:将文件加载到内存中操作,退出时可选择是否保存到磁盘。'sec2'
(默认):标准 POSIX 文件系统接口。
- 示例:
h5py.File("data.h5", 'w', driver='core')
-
libver(可有可无)
- 描述:指定 HDF5 文件的版本兼容性。
- 可选值:
('earliest', 'latest')
:支持的最早和最新 HDF5 库版本。
- 示例:
h5py.File("data.h5", 'w', libver=('earliest', 'latest'))
-
track_order
- 描述:是否记录创建的组和数据集的顺序。
- 可选值:
True
:记录顺序。False
(默认):不记录顺序。
- 示例:
h5py.File("data.h5", 'w', track_order=True)
-
userblock_size
- 描述:为文件设置用户块的大小,用户块是文件开头的一块额外空间,供用户存储自定义元数据。
- 示例:
h5py.File("data.h5", 'w', userblock_size=512)
-
swmr
- 描述:是否启用单写多读模式(SWMR),允许一个进程写入文件,同时多个进程读取文件。
- 可选值:
True
:启用 SWMR 模式。False
(默认):不启用。
- 示例:
h5py.File("data.h5", 'r', swmr=True)
-
rdcc_nbytes
- 描述:设置读取缓存的总大小(以字节为单位)。
- 示例:
h5py.File("data.h5", 'w', rdcc_nbytes=1024*1024)
-
rdcc_w0
- 描述:设置读取缓存的写入策略(取值范围 0 到 1,默认 0.75)。
- 示例:
h5py.File("data.h5", 'w', rdcc_w0=0.5)
综合示例
import h5py
# 创建一个 HDF5 文件,启用顺序记录,用户块大小 512 字节
with h5py.File("example.h5", "w", track_order=True, userblock_size=512) as f:
print("File created successfully!")
h5py.File
的参数功能非常灵活,除了控制文件打开方式(mode
),还支持配置文件存储模式(driver
)、兼容性(libver
)、缓存等。- 根据具体需求可以选择不同的参数组合。
——————————————————————————————————————————
二、实现h5文件中的子数据集合并为一个新的子数据集然后重新存储到h5文件中:
import h5py
import numpy as np
# 打开 HDF5 文件,
with h5py.File('results.h5', 'r') as f:
print("Keys in the file:", list(f.keys()))
xcoor = f['xcoor'][:]
ycoor = f['ycoor'][:]
zcoor = f['zcoor'][:]
print(xcoor)
print(ycoor)
print(zcoor)
1、我的results.h5文件中有两个坐标子集xcoor、ycoor,内容分别为[0. 0.00613592 0.01227185]、[0. 0.00613592 0.01227185]我想将这两个坐标子集合并为[[x,y][x,y]]结构的坐标集pointcoor,请用代码实现这个过程
用到了numpy库里面的column_stack方法
- 将两个一维数组按列合并为一个二维数组。
- 每一行的第一个元素来自
xcoor
,第二个元素来自ycoor
。
import h5py
import numpy as np
# 打开 HDF5 文件并读取数据
with h5py.File('results.h5', 'r') as f:
# 提取 x 和 y 坐标
xcoor = f['xcoor'][:]
ycoor = f['ycoor'][:]
# 打印原始数据
print("xcoor:", xcoor)
print("ycoor:", ycoor)
# 合并为 [[x, y], [x, y], [x, y]] 结构
pointcoor = np.column_stack((xcoor, ycoor))
# 打印结果
print("pointcoor:", pointcoor)
也可以将三个一维数组按列合并为一个三维数组。
import h5py
import numpy as np
# 打开 HDF5 文件并读取数据
with h5py.File('results.h5', 'r') as f:
# 提取 x, y, z 坐标
xcoor = f['xcoor'][:]
ycoor = f['ycoor'][:]
zcoor = f['zcoor'][:]
# 打印原始数据
print("xcoor:", xcoor)
print("ycoor:", ycoor)
print("zcoor:", zcoor)
# 合并为 [[x, y, z], [x, y, z], ...] 的结构
pointcoor = np.column_stack((xcoor, ycoor, zcoor))
# 打印结果
print("pointcoor:", pointcoor)
在使用 np.column_stack
时,输入的一维数组的长度必须一致。如果 xcoor
、ycoor
、zcoor
的长度不同,就会出现错误。
我们需要先检查这三个数组的长度是否一致。如果长度不一致,可以通过截取或填充(如补零)的方法使它们的长度一致。
import h5py
import numpy as np
# 打开 HDF5 文件并读取数据
with h5py.File('results.h5', 'r') as f:
# 提取 x, y, z 坐标
xcoor = f['xcoor'][:]
ycoor = f['ycoor'][:]
zcoor = f['zcoor'][:]
# 检查每个数组的长度
print(f"Lengths: xcoor={len(xcoor)}, ycoor={len(ycoor)}, zcoor={len(zcoor)}")
# 找出最短的长度
min_length = min(len(xcoor), len(ycoor), len(zcoor))
# 截取每个数组到最短长度
xcoor = xcoor[:min_length]
ycoor = ycoor[:min_length]
zcoor = zcoor[:min_length]
# 合并为 [[x, y, z], [x, y, z], ...] 的结构
pointcoor = np.column_stack((xcoor, ycoor, zcoor))
# 打印结果
print("pointcoor:", pointcoor)
修改说明
-
min_length
截取:- 我们找到
xcoor
、ycoor
和zcoor
的最短长度。 - 然后截取所有数组到这个最短长度,避免因数组长度不一致引发错误。
- 我们找到
-
截取方式:
- 如果你不希望截取数据,而是希望填充短的数组以对齐长度,可以改用
np.pad
进行填充。示例如下。
- 如果你不希望截取数据,而是希望填充短的数组以对齐长度,可以改用
# 找出最长的长度
max_length = max(len(xcoor), len(ycoor), len(zcoor))
# 使用 np.pad 填充每个数组到最长长度
xcoor = np.pad(xcoor, (0, max_length - len(xcoor)), constant_values=0)
ycoor = np.pad(ycoor, (0, max_length - len(ycoor)), constant_values=0)
zcoor = np.pad(zcoor, (0, max_length - len(zcoor)), constant_values=0)
# 合并数组
pointcoor = np.column_stack((xcoor, ycoor, zcoor))
print("Padded pointcoor:", pointcoor)
创建数据集:使用 create_dataset
方法创建新的子数据集,将 pointcoor
保存进去。
# 打开 HDF5 文件并保存新的子数据集
with h5py.File('results.h5', 'a') as f: # 使用 'a' 模式打开文件,表示如果文件存在则修改
# 创建新的数据集 'pointcoor'
f.create_dataset('pointcoor', data=pointcoor)
print("pointcoor 数据集已保存到 'results.h5'")
2、我有x轴坐标集xcoor,y轴坐标集ycoor,z轴坐标集zcoor,我想在results.h5 文件中创建一个pointdataset子集,pointdataset的数据结构应该如何设计才能保证坐标数据是和压力场数据一一对应的关系,因为后期在进行数据分析时,我需要同时调用压力场的数据以及压力场数据对应的坐标点信息
方法1:
为了保证坐标数据与压力场数据一一对应,pointdataset
的数据结构应该设计成一个多维数组,能够同时存储每个压力点的坐标和对应的压力值。一个合理的设计方案是将 pointdataset
结构定义为 (N, 4)
的二维数组,其中:
N
是压力场中的点总数,等于 3×3×3=27- 每行有 4 列:
- 前 3 列:存储每个点的 x, y, z 坐标值。
- 第 4 列:存储对应的压力值。
结构的优势:
- 行是压力场中点的编号,每行的数据完整描述了一个点的空间位置和其对应的标量值。
- 后期分析时,可以直接按行索引,方便提取特定点的坐标和压力值。
实现代码
import h5py
import numpy as np
# 定义坐标轴和压力场数据
xcoor = np.array([0.0, 0.00613592, 0.01227185])
ycoor = np.array([0.0, 0.00613592, 0.01227185])
zcoor = np.array([0.0, 0.00613592, 0.01227185])
pressure_data = np.array(
[[[[0.30191338], [0.2950729], [0.28597635]],
[[0.30330813], [0.29460722], [0.2836517]],
[[0.2975547], [0.28577524], [0.27363893]]],
[[[0.29940894], [0.29601768], [0.29162994]],
[[0.3002585], [0.29563743], [0.289917]],
[[0.29535323], [0.2889055], [0.28194022]]],
[[[0.3018312], [0.30014834], [0.29751754]],
[[0.30059883], [0.2987659], [0.29534575]],
[[0.29670358], [0.2942623], [0.28991356]]]]
)
# 获取所有组合的坐标点
X, Y, Z = np.meshgrid(xcoor, ycoor, zcoor, indexing='ij')
coordinates = np.stack([X.flatten(), Y.flatten(), Z.flatten()], axis=-1) # (27, 3)
# 压力值展开为一维
pressure_values = pressure_data.flatten() # (27,)
# 构造 pointdataset 数据
pointdataset = np.hstack([coordinates, pressure_values.reshape(-1, 1)]) # (27, 4)
# 将 pointdataset 保存到 HDF5 文件中
with h5py.File("results.h5", "a") as f:
if "pointdataset" in f:
del f["pointdataset"] # 如果已存在,先删除
f.create_dataset("pointdataset", data=pointdataset)
print("pointdataset successfully created and stored in results.h5!")
pointdataset
的内容结构
运行以上代码后,pointdataset
的内容将类似于以下结构:
x-coord | y-coord | z-coord | pressure |
---|---|---|---|
0.00000000 | 0.00000000 | 0.00000000 | 0.30191338 |
0.00613592 | 0.00000000 | 0.00000000 | 0.29507290 |
0.01227185 | 0.00000000 | 0.00000000 | 0.28597635 |
0.00000000 | 0.00613592 | 0.00000000 | 0.30330813 |
... | ... | ... | ... |
每行包含一个点的 x,y,z坐标和压力值。
数据读取与分析
以后进行数据分析时,可以通过以下代码读取并处理 pointdataset
:
import h5py
import numpy as np
with h5py.File("results.h5", "r") as f:
pointdataset = f["pointdataset"][:]
print("Pointdataset shape:", pointdataset.shape)
print("Example row (x, y, z, pressure):", pointdataset[0])
---------------------------------------------------------------------------------------------------------------------------------
方法分析
np.meshgrid
:这是一个用于生成坐标网格的函数,常用于从一维坐标向量生成网格化的二维或三维坐标矩阵。它接受多个一维数组作为输入,生成一个网格化的坐标矩阵。
参数解释:
-
xcoor
,ycoor
,zcoor
:这三个是分别表示 x、y、z 轴坐标的一维数组。每个坐标数组都有三个元素,例如:xcoor = np.array([0.0, 0.00613592, 0.01227185]) ycoor = np.array([0.0, 0.00613592, 0.01227185]) zcoor = np.array([0.0, 0.00613592, 0.01227185])
它们分别表示 x、y、z 方向上 3 个离散坐标值。
-
indexing='ij'
:np.meshgrid
的默认行为是使用xy
索引方式,即生成的网格依次按照x
和y
方向生成坐标点。通过设置indexing='ij'
,生成网格时会使用ij
索引方式,即i
对应第一个维度(例如,y 轴),j
对应第二个维度(例如,x 轴),k
对应第三个维度(z 轴)。这种方式更适合处理数学和物理计算中的坐标系。
生成网格:
这行代码的作用是通过 np.meshgrid
创建三个三维网格 X
, Y
, Z
,每个网格的维度分别对应于 xcoor
, ycoor
, zcoor
的组合。这意味着你会得到一个大小为 3×3×3的三维坐标网格,网格中的每一个元素表示对应坐标轴的坐标值。
X, Y, Z = np.meshgrid(xcoor, ycoor, zcoor, indexing='ij')
X
是一个形状为(3, 3, 3)
的数组,表示每个位置对应的 x 坐标值。Y
是一个形状为(3, 3, 3)
的数组,表示每个位置对应的 y 坐标值。Z
是一个形状为(3, 3, 3)
的数组,表示每个位置对应的 z 坐标值。
下面:表示在每个 y, z
的组合下,x
坐标的值被复制扩展
X = [[[0.0, 0.00613592, 0.01227185], [0.0, 0.00613592, 0.01227185], [0.0, 0.00613592, 0.01227185]],
[[0.0, 0.00613592, 0.01227185], [0.0, 0.00613592, 0.01227185], [0.0, 0.00613592, 0.01227185]],
[[0.0, 0.00613592, 0.01227185], [0.0, 0.00613592, 0.01227185], [0.0, 0.00613592, 0.01227185]]]
-
X.flatten()
:这是一个将X
数组展平为一维数组的操作。X
的形状是(3, 3, 3)
,通过.flatten()
方法会把这个三维数组展开为一个一维数组,包含所有的 x 坐标值。 -
Y.flatten()
和Z.flatten()
同理,将Y
和Z
展平为一维数组。 -
np.stack([X.flatten(), Y.flatten(), Z.flatten()], axis=-1)
:np.stack
将这三个一维数组沿着最后一个轴(axis=-1
)堆叠起来,形成一个二维数组。也就是说,这行代码将X.flatten()
,Y.flatten()
,Z.flatten()
合并成一个形状为(27, 3)
的二维数组,每行包含一个坐标点的 x,y,z 值。 X.flatten()
会展平成一个大小为 27 的一维数组。Y.flatten()
和Z.flatten()
也同理展平成大小为 27 的一维数组。- 然后通过
np.stack
将它们按列组合起来,得到一个大小为(27, 3)
的二维数组,其中每行表示一个三维坐标点的 x,y,z值。
总结:
np.meshgrid
:生成三个坐标轴的网格,适用于多维坐标的计算和分析。.flatten()
:将三维数组展平为一维数组,方便后续操作。np.stack
:将多个一维数组堆叠成二维数组,按行表示多个坐标点。
方法2:
为了保持压力场数据的结构((3, 3, 3, 1)
),同时为每个压力场数据点生成相应的坐标信息,可以将坐标数据存储为与压力场数据相同形状的数组。在这种情况下,point2dataset
的数据结构可以是 (3, 3, 3, 3)
,其中最后一个维度是 3,代表每个坐标点的 (x, y, z)
三个坐标分量。
思路:
- 保持压力场数据结构:即
(3, 3, 3, 1)
。 - 坐标数据集的形状:与压力场数据一样,
point2dataset
也应当是(3, 3, 3, 3)
,其中每个点包含(x, y, z)
坐标信息。 - 将坐标数据(
xcoor
,ycoor
,zcoor
)进行网格化:用np.meshgrid
创建三维网格,得到每个点的(x, y, z)
坐标。 - 将坐标数据保存到 HDF5 文件:将处理后的坐标数据与压力场数据一同保存到
results.h5
中。
实现步骤:
- 创建三维坐标网格。
- 将坐标网格堆叠成一个
point2dataset
数组,形状为(3, 3, 3, 3)
。 - 将
point2dataset
和Pressure_data
(假设为形状(3, 3, 3, 1)
)保存到results.h5
中。
[Group] results.h5 [Dataset] point2dataset [Dataset] Pressure
import h5py
import numpy as np
# 假设已经有了以下坐标数据
xcoor = np.array([0.0, 0.00613592, 0.01227185])
ycoor = np.array([0.0, 0.00613592, 0.01227185])
zcoor = np.array([0.0, 0.00613592, 0.01227185])
# 生成坐标网格,使用 np.meshgrid 来生成每个坐标轴的网格
X, Y, Z = np.meshgrid(xcoor, ycoor, zcoor, indexing='ij')
# 将坐标数据堆叠成 (3, 3, 3, 3) 结构
# X, Y, Z 都是 (3, 3, 3) 形状,flatten 后堆叠成 (3, 3, 3, 3)
coordinates = np.stack([X, Y, Z], axis=-1) # 形状为 (3, 3, 3, 3)
# 假设你的压力数据是以下的 (3, 3, 3, 1) 形状
Pressure_data = np.random.random((3, 3, 3, 1)) # 示例的压力场数据
# 保存数据到 HDF5 文件
with h5py.File('results.h5', 'w') as f:
# 保存坐标数据
f.create_dataset('point2dataset', data=coordinates)
# 保存压力数据
f.create_dataset('Pressure_data', data=Pressure_data)
print("Data has been saved successfully to results.h5")
代码解释:
np.meshgrid
:根据xcoor
,ycoor
,zcoor
创建了一个 3D 网格,生成的X
,Y
,Z
分别是形状为(3, 3, 3)
的数组,表示每个网格点的x
,y
,z
坐标。np.stack([X, Y, Z], axis=-1)
:通过np.stack
将X
,Y
,Z
沿最后一个维度(即axis=-1
)堆叠,得到形状为(3, 3, 3, 3)
的数组。每个网格点的最后一个维度包含对应的(x, y, z)
坐标。f.create_dataset('point2dataset', data=coordinates)
:将生成的坐标数据保存为 HDF5 文件中的point2dataset
数据集。f.create_dataset('Pressure_data', data=Pressure_data)
:将压力数据保存为Pressure_data
数据集。
数据结构:
point2dataset
数据集:形状为(3, 3, 3, 3)
,表示每个网格点的(x, y, z)
坐标。Pressure_data
数据集:形状为(3, 3, 3, 1)
,表示每个网格点的压力值。
结果:
在 results.h5
文件中,你将有以下结构:
[Group] results.h5
[Dataset] point2dataset (3, 3, 3, 3)
[Dataset] Pressure_data (3, 3, 3, 1)
后续使用:
- 你可以通过以下方式访问坐标和压力数据:
with h5py.File('results.h5', 'r') as f: point2dataset = f['point2dataset'][:] Pressure_data = f['Pressure_data'][:] print(point2dataset.shape) # (3, 3, 3, 3) print(Pressure_data.shape) # (3, 3, 3, 1)