HDF5快速上手
2023-10-17
| 2023-10-17
0  |  阅读时长 0 分钟
type
status
password
date
slug
summary
category
URL
tags
icon

1. HDF5简介

Hierarchical Data Format(HDF)是一种针对大量数据进行组织和存储的文件格式。它包含了数据模型,库,和文件格式标准。现在HDF5还支持了大数据技术和NoSQL技术,并广泛用于科研,金融,以及其他科学和工程领域。当然批评者也认为HDF5格式具有以下缺点:
  1. 设计古老,定制化设置冗长
  1. 尽管有150多页的公开标准,但HDF5的非官方实现非常少
  1. HDF5没有强制使用UTF8编码,因此客户为了兼容型只好采用ASCII编码
  1. 存储的数据不能没有外部工具(如h5repack)的情况下自由的提取和复制。

2. HDF5文件结构

notion image

2.1 group

为了方便数据的组织,HDF5文件通过group的方式组织成树状结构。每个group相当于一个文件夹,其中可以包含一个或多个 dataset 及其它的 group
notion image

2.2 dataset

每一个dataset包含Metadata和Data两部分。其中Metadata包含Data相关的信息,而Data则包含数据本身。
notion image

2.2.1 Metadata

用于描述的元数据包括,Dataspaces、Datatypes、Properties和Attributes(可选).
  • Dataspaces:给出原始数据的 (Rank) 和维度 (dimension)
  • Datatypes:数据类型,分为预定义数据类型和衍生数据类型
    • 预定义数据类型:通过HDF5创建的数据,在所有支持的平台通用。
      • notion image
    • 衍生数据类型:由预定义数据类型衍生而来,例如字符串和嵌套的数据类型。
    • notion image
  • Properties:说明该 dataset 的分块储存以及压缩情况
    • notion image
  • Attributes:为该 dataset 的其他自定义属性

3. H5PY实战

💡
特别要注意的是,一定要在操作结束后关闭对象。因为之前的操作只是生成操作的流程,并不真正执行操作,只有关闭对象操作才会真正出发对对象进行的修改。

3.1 文件(Files)创建/打开/关闭

模式
操作
当文件不存在时
是否覆盖
r
只能读
报错
-
r+
可读可写
报错
-
w
只能写
创建
w+
可读可写
创建
a
可读可写
创建
否,追加写

3.2 群(Group)的建立

Python中将文件树表述成一个dict,keys值是groups成员的名字,values是成员对象(groups或者datasets)本身。文件对象本身作为root group。

3.3 数据集(Dataset)的创建

新的数据集可以通过group.create_dateset()或者group.require_dateset()记性创建。已经存在的数据已可以通过群的所以语法进行访问dset = group[“dset_name”]

3.4 数据集读取与子集索引(Subsetting)

3.4.1 Python部分

h5py库采用numpy的切片语法来读写文件中的数据集,因此熟悉numpy的索引规则用起HDF5的“hyperslab”选择是非常容易的,这也是快速读且HDF5文件中数据集的方法。
下面是四个能够被识别的用法
  • 索引
  • 切片(比如[:]或者[0:10])
  • 域名,在符合数据中使用
  • 最多一个省略(Ellipsis),即(…),对象
例如
花式索引(Fancy Indexing)
一部分numpy花式索引在HDF5中也支持,比如
单使用受到一些限制
  • 选择列表不能为空
  • 选择坐标必须要以升序方式给出
  • 重复项忽略
  • 长列表(>1k元素)将速度很慢
numpy的逻辑索引可以用来进行选择,比如
和numpy一样,*len()函数返回dataset中第一个轴的长度。但是如果在32位平台上第一个轴长度超过2^32时len(dataset)将失效,因此推荐使用dataset.len()*方法。

3.4.2 C/C++部分

在C语言中,访问原数据集子集的关键在于构造内存的dataspace,通过内存和文件中dataspace的配合实现访问选择子集的效果。在HDF5中,有两种选择,元素(element)选择和超块(hyperslab)选择,分别通过函数*H5Sselect_elements()H5Sselect_hyperslab()*两个函数实现。这两个函数都会修改传入dataspace_id对应的dataspace空间性质,以此实现选择的子集。
和MPI的子集选择方法相同,HDF5的子集选择定义子集四大件:
  • offset: 位置补偿
  • stride: 间隙
  • count: 块数
  • block: 块大小
例如想要从一个(8,10)的dataspace中选择一个如图(7,4)的dataspace,需要定义的四大件如下。
notion image
C/C++代码

3.5 添加注释——创建属性(Attribute)

属性是一种dataset的元数据(metadata),它描述了数据的相关信息,可以把属性理解成注释,所有的group和datasets都支持属性。
h5py采用dataset.attrs方法访问属性,比如
C/C++代码

3.6 数据压缩(Compression)

HDF5的数据集默认是连续空间存储的。单可以通过设置让HDF5把数据进行分块(chunked)存储,也就是说将数据分割为固定大小的小块分开存储,再通过B-Tree进行索引。
分块存储的方式是的数据集可以改变大小,也可以进行压缩过滤。
块的分割大小大概在10KiB到1MiB之间,数据集越大,则块也相应越多。分块以后数据读取将整块郑块的进行,如果对分块干到困惑,python中允许可以直接使用h5py的自动大小(chunks=True)
有了分块的数据集,就可以对数据集进行压缩了,通过无损的压缩过滤器可以将数据集进行无损失的压缩,利用函数group.create_dateset(compression=“filter”)
常见的无损压缩过滤器有
  • GZIP过滤器(“gzip”): 每个HDF5的标配,中等速度高压缩率,具有参数compression_opts取值从0到9控制压缩等级,默认值为4
  • LZF过滤器(“lzf”): 快速但压缩率中等的压缩器
  • SZIP过滤器(“szip”): NASA开发的专利保护压缩器

pandas方法

项目
创建
添加
创建索引
查询
存储
put(index=False,data_columns=True) append(data_columns=True)
19.41
230.92
75.29
81MB
put(index=False,data_columns=True) append(data_columns=True)
19.15
225.65
75.49
81MB
put(index=False) append(index=False,data_columns=False)
18.64
18.62
失败
7.57MB
put(index=False) append(index=False,data_columns=False) create_table_index(columns=True)
18.82
18.95
27.03
失败
40.3MB
put(index=False,data_columns=True) append(index=False,data_columns=False)
19.53
19.55
92.80
7.58MB
put(index=False,data_columns=True) append(index=False,data_columns=True)
19.23
19.41
94.39
7.58MB
put(index=False,data_columns=True) append(index=False,data_columns=True) create_table_index(columns=True)
19.34
19.59
207.38
282.67
81MB
💡
经过测试发现添加数据的时候;如果设置index=True,写入速度会变慢。

打开文件

  • path:字符型输入,用于指定h5文件的名称
  • mode:用于指定读写模式
    • 模式
      操作
      当文件不存在时
      是否覆盖
      r
      只能读
      报错
      -
      r+
      可读可写
      报错
      -
      w
      可读可写
      创建
      a
      可读可写
      创建
      否,追加写
  • complevel:int型,用于控制h5文件的压缩水平,取值范围在0-9之间,越大则文件的压缩程度越大,占用的空间越小,但相对应的在读取文件时需要付出更多解压缩的时间成本,默认为0,代表不压缩

写文件

put函数

往HDF中添加一张数据表, 以key作为索引。如果有数据表,那么进行覆盖
  • key:存储路径
  • index:将index作为列
  • append:是否可以添加数据,如果需要添加数据,那么format必须为table
  • append:是否可以添加数据,如果需要添加数据,那么format必须为table
  • data_columns:创建列名

append函数

  • key:存储路径
  • index:将index作为列
  • append:是否可以添加数据,如果需要添加数据,那么format必须为table
  • append:是否可以添加数据,如果需要添加数据,那么format必须为table
  • data_columns:创建列名

创建索引

项目
创建
添加
创建索引
查询
存储
put(index=False,data_columns=True) append(index=False,data_columns=True)
10.59
10.54
11.91
161MB
put(index=True,data_columns=True) append(index=True,data_columns=True)
152.21
190.63
12
892MB
put(index=False,data_columns=True) append(index=False,data_columns=True) create_table_index(columns=True)
10.69
10.67
257.03
12
928MB
put(index=True,data_columns=True) append(index=True,data_columns=True) 与上面所有测试不同。上述所有测试的index是数字,本项测试的index是datetime
96.65
112.67
6.54
671MB
💡
经过测试发现添加数据的时候;如果设置index=True,写入速度会变慢。

删除——remove函数

查询——select函数

要查询的列必须有索引
符号
描述
符号
描述
符号
=
==
>
<
!=
>=
<=
|
&
()
  • where:相当于sql里面的where
  • cloumns:相当于sql里面的select
  • chunksize:迭代器
 
  • 工具
  • 使用nps搭建内网穿透Linux挂载WebDAV为本地磁盘
    Loading...
    目录