使用h5py对hdf5进行增量写入
我有个问题,想知道用Python和h5py写hdf5文件的最佳方法。
我有一些数据,像这样:
-----------------------------------------
| timepoint | voltage1 | voltage2 | ...
-----------------------------------------
| 178 | 10 | 12 | ...
-----------------------------------------
| 179 | 12 | 11 | ...
-----------------------------------------
| 185 | 9 | 12 | ...
-----------------------------------------
| 187 | 15 | 12 | ...
...
大约有10^4列,和大约10^7行。(这大约是10^11(1000亿)个元素,或者说大约100GB,假设每个元素占用1个字节)。
对于这些数据,通常的使用方式是写一次,读很多次。典型的读取方式是抓取第一列和另一列(比如第254列),把这两列加载到内存中,然后进行一些复杂的统计分析。
我觉得一个好的hdf5结构应该是把上面表格中的每一列都作为一个hdf5组,这样就会有10^4个组。这样我们就不需要把所有数据都读入内存,对吧?不过hdf5的结构还没有确定,所以可以随意设计。
现在问题来了:我每次接收的数据大约是10^4行(而且每次接收的行数不完全相同),需要逐步写入到hdf5文件中。我该怎么写这个文件呢?
我在考虑使用Python和h5py,但如果有其他推荐的工具也可以。是不是应该用分块的方式,比如说:
dset = f.create_dataset("voltage284", (100000,), maxshape=(None,), dtype='i8', chunks=(10000,))
然后当另一块10^4行的数据到达时,替换掉数据集?
还是说把每块10^4行的数据存储为一个单独的数据集更好?或者我真的需要知道最终的行数吗?(这可能有点难,但也许可以做到)。
如果hdf5不是合适的工具,我也可以放弃它,不过我觉得一旦解决了写入的问题,它会非常好用。
2 个回答
正如@unutbu提到的,dset.resize
是一个很不错的选择。你可以看看pandas
以及它对HDF5的支持,这可能对你的工作流程有帮助。听起来HDF5是个合适的选择,但有可能你的问题用一个额外的层来表达会更好。
一个需要考虑的重要点是数据的方向。如果你主要关注的是读取数据,并且主要是按列来获取数据,那么你可能需要把数据转置一下,这样读取时就可以按行进行,因为HDF5是按行优先的方式存储数据的。
根据常见问题解答,你可以使用 dset.resize
来扩展数据集。比如说,
import os
import h5py
import numpy as np
path = '/tmp/out.h5'
os.remove(path)
with h5py.File(path, "a") as f:
dset = f.create_dataset('voltage284', (10**5,), maxshape=(None,),
dtype='i8', chunks=(10**4,))
dset[:] = np.random.random(dset.shape)
print(dset.shape)
# (100000,)
for i in range(3):
dset.resize(dset.shape[0]+10**4, axis=0)
dset[-10**4:] = np.random.random(10**4)
print(dset.shape)
# (110000,)
# (120000,)
# (130000,)