1. 基本结构理解
2.python代码实现
一般的操作一个HDF5对象的步骤是
打开这个对象;
对这个对象进行操作;
关闭这个对象。
特别要注意的是,一定要在操作结束后关闭对象。因为之前的操作只是生成操作的流程,并不真正执行操作,只有关闭对象操作才会真正出发对对象进行的修改。
2.1 文件(files)创建/打开/关闭
import h5py
# r 只读,文件必须已存在
# r+ 读写,文件必须已存在
# w 新建文件,若存在覆盖
# w- 或x,新建文件,若存在报错
# a 如存在则读写,不存在则创建(默认)
# 以写入方式打开文件 这只是创建的hdf5,是/这个目录 其他创建的要放在这个目录之下
file = h5py.File('file.h5', 'w')
file.close()
# 打开文件
file_open = h5py.File('file.h5', 'r+')
file_open.close()
2.2 Group(群)的建立
#好像也可以理解为创建文件目录的过程
#!!!!重点记得要close
import h5py
f = h5py.File('foo.hdf5','w')
f.name # output = '/'
[k for k in f.keys()] # output = []
# 创建一个group
# 1. 相对地址方法
grp = f.create_group("bar")
grp.name # output = '/bar'
subgrp = grp.create_group("baz")
subgrp.name # output = '/bar/baz'
# 2. 绝对地址创建多个group
grp2 = f.create_group("/some/long/path")
grp2.name # output = '/some/long/path'
grp3 = f['/some/long']
grp3.name # output = '/some/long'
# 3. 删除一个group
del f['bar']
# 最终一定要记得关闭文件才能保存
f.close()
2.3 数据集(Dataset)的创建
H5py中的dataset很类似与Numpy中的array,但支持一些列透明(针对连续存储的选择操作对分块存储同样有效)的存储特性,还支持分块,压缩,和错误校验。
新的数据集可以通过group.create_dateset()或者group.require_dateset()记性创建。已经存在的数据已可以通过群的所以语法进行访问dset = group[“dset_name”]。
import h5py
import numpy as np
f = h5py.File('file.h5','w')
#创建数据集
# dataset = group.create_dateset(name,
# shape=None,
# dtype=None,
# data=None)
dset = f.create_dateset("default", (100,))
dset = f.create_dateset("ints", (100,), dtype='i8')
dset = f.create_dateset("init", data=np.arange(100))
# 读取数据集可以采用索引操作
read_dset = f["default"]
# 数据集的删除,注意这样做只是删除链接,但文件中所申请的空间无法收回
f.__delitem__("ints") # version 1
del f['init'] # version 2
f.close()
2.4 数据集读取与子集索引(Subsetting)
h5py库采用numpy的切片语法来读写文件中的数据集,因此熟悉numpy的索引规则用起HDF5的“hyperslab”选择是非常容易的,这也是快速读且HDF5文件中数据集的方法。
下面是四个能够被识别的用法
- 索引
- 切片(比如[:]或者[0:10])
- 域名,在符合数据中使用
- 最多一个省略(Ellipsis),即(…),对象
>>> dset = f.create_dataset("MyDataset", (10,10,10), 'f')
>>> dset[0,0,0]
>>> dset[0,2:10,1:9:3]
>>> dset[:,::2,5]
>>> dset[0]
>>> dset[1,5]
>>> dset[0,...]
>>> dset[...,6]
>>> # 对于符合数据
>>> dset["FieldA"]
>>> dset[0,:,4:5, "FieldA", "FieldB"]
>>> dset[0, ..., "FieldC"]
>>> # 广播在索引中依然被支持
>>> dset[0,:,:] = np.arange(10) # 广播到(10,10)
>>> # 对于标量数据集,采用和numpy相同的语法结果,利用空tuple做索引,即
>>> scalar_result = dset[()]
>>> dset.shape
(10, 10)
>>> result = dset[0, [1,3,8]]
>>> result.shape
(3,)
>>> result = dset[1:6, [5,8,9]]
>>> result.shape
(5, 3)
单使用受到一些限制
选择列表不能为空
选择坐标必须要以升序方式给出
重复项忽略
长列表(>1k元素)将速度很慢
numpy的逻辑索引可以用来进行选择,比如
>>> arr = numpy.arange(100).reshape((10,10))
>>> dset = f.create_dataset("MyDataset", data=arr)
>>> result = dset[arr > 50]
>>> result.shape
(49,)
和numpy一样,len()函数返回dataset中第一个轴的长度。但是如果在32位平台上第一个轴长度超过2^32时len(dataset)将失效,因此推荐使用dataset.len()方法。
2.5 数据压缩
HDF5的数据集默认是连续空间存储的。单可以通过设置让HDF5吧数据进行分块(chunked)存储,也就是说将数据分割为固定大小的小块分开存储,再通过B-Tree进行索引。
分块存储的方式是的数据集可以改变大小,也可以进行压缩过滤。
块的分割大小大概在10KiB到1MiB之间,数据集越大,则块也相应越多。分块以后数据读取将整块郑块的进行,如果对分块干到困惑,python中允许可以直接使用h5py的自动大小(chunks=True)
import h5py
f = h5py.File('file.h5','w')
#创建分块数据集
dset_chunk = f.create_dateset("chunked", (1000,1000), chunks=(100,100))
dset_auto = f.create_dateset("chunked_auto", (1000,1000), chunks=True)
f.close()
有了分块的数据集,就可以对数据集进行压缩了,通过无损的压缩过滤器可以将数据集进行无损失的压缩,利用函数group.create_dateset(compression=”filter”)。
import h5py
f = h5py.File('file.h5','w')
#创建采用gzip压缩过滤器的无损压缩数据集
dset_compress = f.create_dateset("chunked", (1000,1000), compression="gzip")
dset_compressmax = f.create_dateset("chunked_auto", (1000,1000), compression="gzip", compression_opts=9)
f.close()
常见的无损压缩过滤器有
- GZIP过滤器(“gzip”): 每个HDF5的标配,中等速度高压缩率,具有参数compression_opts取值从0到9控制压缩等级,默认值为4
- LZF过滤器(“lzf”): 快速但压缩率中等的压缩器
- SZIP过滤器(“szip”): NASA开发的专利保护压缩器