2013-08-28 161 views
19

我有一些hdf5文件,每個文件都有一個數據集。數據集太大而無法保存在RAM中。我想將這些文件合併爲一個單獨的文件,其中包含所有數據集(即而不是,以將數據集連接成單個數據集)。合併hdf5文件

一種方法是創建一個hdf5文件,然後逐個複製數據集。這將是緩慢和複雜的,因爲它需要緩衝副本。

有沒有更簡單的方法來做到這一點?似乎應該有,因爲它本質上只是創建一個容器文件。

我正在使用python/h5py。

+1

看起來像這已被回答:http://stackoverflow.com/questions/5346589/concatenate-a-large-number-of-hdf5-files –

+2

@MattPavelle據我瞭解這是不同於我想要的。我不想將數據集連接成單個數據集,而是將它們作爲單獨的數據集保存在一個文件中。 – Bitwise

+1

明白了,謝謝澄清和編輯。並且原諒後續 - 這是我玩HDF5後的幾年 - 但我認爲h5merge並沒有做到這一點? –

回答

9

一種解決方案是使用h5py接口到低級別的HDF5 API的H5Ocopy​​,特別是h5py.h5o.copyfunction

In [1]: import h5py as h5 

In [2]: hf1 = h5.File("f1.h5") 

In [3]: hf2 = h5.File("f2.h5") 

In [4]: hf1.create_dataset("val", data=35) 
Out[4]: <HDF5 dataset "val": shape(), type "<i8"> 

In [5]: hf1.create_group("g1") 
Out[5]: <HDF5 group "/g1" (0 members)> 

In [6]: hf1.get("g1").create_dataset("val2", data="Thing") 
Out[6]: <HDF5 dataset "val2": shape(), type "|O8"> 

In [7]: hf1.flush() 

In [8]: h5.h5o.copy(hf1.id, "g1", hf2.id, "newg1") 

In [9]: h5.h5o.copy(hf1.id, "val", hf2.id, "newval") 

In [10]: hf2.values() 
Out[10]: [<HDF5 group "/newg1" (1 members)>, <HDF5 dataset "newval": shape(), type "<i8">] 

In [11]: hf2.get("newval").value 
Out[11]: 35 

In [12]: hf2.get("newg1").values() 
Out[12]: [<HDF5 dataset "val2": shape(), type "|O8">] 

In [13]: hf2.get("newg1").get("val2").value 
Out[13]: 'Thing' 

2.0.1-2+b1h5py版本和IPython的版本0.13.1-2+deb7u1生成的上述在Python版本2.7.3-4+deb7u1上,來自Debian Wheezy的或多或少的安裝。在執行上述操作之前,文件f1.h5f2.h5不存在。

命令[7]hf1.flush()是至關重要的,因爲低層次的接口顯然將始終從存儲在磁盤上的文件.h5,而不是在內存中緩存的版本借鑑。可以通過使用例如hf1.get("g1").id提供該組的ID來實現將數據集複製到不在File的根部的組中的數據集。

請注意,如果指定名稱的對象已存在於目標位置,則h5py.h5o.copy將失敗並出現異常(無clobber)。

+1

這看起來可能已經晚了兩年,但... 我一定會使用它,並希望如果沒有別的東西,它也會幫助其他人。 – hBy2Py

+1

謝謝!實際上這個問題每隔一段時間都會得票,所以我猜測它對許多人仍然有用。 – Bitwise

+0

很酷。 HDF5是一種非常好的數據格式,但它的高級API遠沒有......詳盡無遺。 – hBy2Py

9

我使用官方hdf5工具中的h5copy找到了非python解決方案。 h5copy可以將個別指定的數據集從hdf5文件複製到另一個現有的hdf5文件中。

如果有人發現一個基於python/h5py的解決方案,我很樂意聽到它。

26

這實際上是HDF5的用例之一。 如果您只是希望能夠訪問單個文件中的所有數據集,並且不關心它們是如何實際存儲在磁盤上的,則可以使用external links。從HDF5 website

外部鏈接允許一組包含在另一個HDF5文件對象,使圖書館,好像他們是在當前文件來訪問這些對象。以這種方式,一個組似乎可以直接包含數據集,名爲數據類型,甚至實際上在不同文件中的組。

Here's how to do it in h5py:此功能是通過一套用於創建和管理環節,界定和檢索路徑外部對象,解析鏈接名稱的功能實現

myfile = h5py.File('foo.hdf5','w') 
myfile['ext link'] = h5py.ExternalLink("otherfile.hdf5", "/path/to/resource") 

這將是非常快而不是將所有數據集複製到新文件中。我不知道訪問otherfile.hdf5的速度有多快,但對所有數據集的操作都是透明的 - 也就是說,h5py會將所有數據集看作位於foo.hdf5之內。

+0

謝謝,這是一個很好的訣竅。不過,就我而言,我更喜歡將它們真正包含在一個文件中。但是如果複製證明太慢,我可能會使用這種方法。 – Bitwise

+2

應該選擇這個作爲問題的答案。 – ivotron

+0

如果你打算這樣做,並且你有很多鏈接,當在h5py中創建/打開新文件時,一定要使用C或libver ='latest'中的H5Pset_libver_bounds()。這將使用最新的文件格式,這對於存儲大量鏈接來說效率更高。 –

1

我通常使用ipythonh5copy工具,這比純python解決方案要快得多。一旦安裝h5copy。

控制檯解決方案M.W.E.

#PLESE NOTE THIS IS IPYTHON CONSOLE CODE NOT PURE PYTHON 

import h5py 
#for every dataset Dn.h5 you want to merge to Output.h5 
f = h5py.File('D1.h5','r+') #file to be merged 
h5_keys = f.keys() #get the keys (You can remove the keys you don't use) 
f.close() #close the file 
for i in h5_keys: 
     !h5copy -i 'D1.h5' -o 'Output.h5' -s {i} -d {i} 

自動化控制檯解決方案

要完全使自動化過程假設你的文件夾中進行工作的文件,要合併存儲:

import os 
d_names = os.listdir(os.getcwd()) 
d_struct = {} #Here we will store the database structure 
for i in d_names: 
    f = h5py.File(i,'r+') 
    d_struct[i] = f.keys() 
    f.close() 

# A) empty all the groups in the new .h5 file 
for i in d_names: 
    for j in d_struct[i]: 
     !h5copy -i '{i}' -o 'output.h5' -s {j} -d {j} 

爲每.h5創建新組添加文件

如果要在output.h5中保留以前的數據集,請首先使用標記創建組:

# B) Create a new group in the output.h5 file for every input.h5 file 
for i in d_names: 
     dataset = d_struct[i][0] 
     newgroup = '%s/%s' %(i[:-3],dataset) 
     !h5copy -i '{i}' -o 'output.h5' -s {dataset} -d {newgroup} -p 
     for j in d_struct[i][1:]: 
      newgroup = '%s/%s' %(i[:-3],j) 
      !h5copy -i '{i}' -o 'output.h5' -s {j} -d {newgroup} 
1

要更新這一點,與HDF5版本1.10提供了一個新功能,可能是在這種情況下所謂的「虛擬數據集」非常有用。
在這裏你可以找到一個簡短的教程和一些解釋: Virtual Datasets
此處更詳細的功能說明和文檔:
Virtual Datasets extra doc
在這裏合併拉動請求在h5py包括虛擬datatsets API到h5py:
h5py Virtual Datasets PR但我不知道它是否已經在當前h5py版本或將來到。

+0

雖然創建一個虛擬數據集會(虛擬)連接數據集,但這不是原始海報想要做的。 –