python---之table寫hdf5檔案

zxyhhjs2017發表於2018-06-03

Python Tables 學習筆記

實在是太煩了,雖然以前也用過python tables來儲存大資料,但是還是有些功能不太懂。我只用了最簡單的create array直接把所有的資料一次性寫入hdf5檔案。但是現在的電腦記憶體比較小,處理的資料太大,一次性寫入,記憶體會不足。另一方面,一邊處理資料,一邊寫入資料,是一種更好的策略。於是自己又重寫學了python tables,也花了不少時間。在此總結下,也為自己做好總結立個標杆。要總結好,不然很快就會忘記了。
  • 1
  • 2

本文將從tables的讀,寫,以及一些簡單的操作進行簡要描述。使得tables這個tool能夠為我們所用。
首先,我們先介紹下HDF5(Hierarchical Data Format).HDF 是用於儲存和分發科學資料的一種自我描述、多物件檔案格式。HDF 是由美國國家超級計算應用中心(NCSA)建立的,以滿足不同群體的科學家在不同工程專案領域之需要。HDF 可以表示出科學資料儲存和分佈的許多必要條件。其有以下一些特徵:
- 自述性
- 通用性
- 靈活性
- 擴充套件性
- 跨平臺


HDF檔案是安裝樹狀結構組織起來的。其頂部是根節點(),根節點下可以接很多分組(group),每個分組下有可以有很多節點,包括表(table),陣列(array),壓縮陣列(compression array,Earray),可擴充套件壓縮陣列(enlargeable array,Earray),變長陣列(variable length array,VLarray)。每個節點下還有葉子節點,即最終儲存的資料。

簡單知道HDF5檔案的特徵,我們接著介紹下,在python下如何使用tables(其實還有H5Py這個包也是可以用)這個package來實現對HDF5檔案的操作。
假設大家已經把tables及其依賴的庫如numpy等包安裝好在python的環境下。

1 寫資料到表

這裡簡單以pytable裡面的例子進行說明。對於table,我們首先要定義表格中每個元素(field)的資料型別,長度等資訊。如下圖,我們定義了一個particle類,其名稱,資料型別,及長度。比如說name這個field是字串型別,最大長度是16個位元組。

from tables import *
class particle(IsDescription):
    '''definition '''
    name = StringCol(16) #16-character string
    _id = Int64Col()  #signed 64-bit interger
    energy = Float64Col() #double-precision
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

新建一個hdf5檔案,檔名是tutorial.h5, 寫的模式,描述為test file。

f = open_file('tutorial.h5',mode='w',title='test file')
  • 1

為了更好地組織資料,我們在根節點下新建一個分組叫detector,描述為Detector information。

group = f.create_group('/','detector','Detector information')
  • 1

“/”可以由f.root代替。
接著,我們在detector這個分組下建立一個新的表(table)叫做‘readout’,並初始化為particle形式。

table=f.create_table(group,'readout',particle,'Readout_example')
  • 1

接著,我們往表裡新增資料。其中append這個函式用於把資料寫入到I/O buffer中。

for i in range(10):
    particle['name']='particle: %6d' %(i)
    particle['_id'] = i *(2 **34)
    particle['energy'] = float(i *i)
    particle.append()
table.flush()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

最後還需要呼叫flush函式把資料寫入到硬碟中,並且會釋放被佔用的記憶體,這樣我們就可以處理海量的資料,而不用擔心記憶體不足。

2 從表中讀資料

我們把資料存到硬碟裡面,接下的步驟要從硬碟把資料讀出來。我們首先定位到表。接著我們還可以查詢我們感興趣的資料。我們的查詢是通過 Table.iterrows() 這個迭代器,它把表中的每行提取出來。

table = f.root.detector.readout
energy = []
for x in table.iterrows():
    energy.append(x)
  • 1
  • 2
  • 3
  • 4

3 建立陣列物件(Array object)

把資料放在table是資料組織很好的方式,但是當我們的資料並沒有那麼複雜,並沒有包含很多屬性,我們可以簡單地使用陣列來組織資料。比如我們想儲存矩陣資料,

features = np.random.rand(100,100000)
f = tables.openFile('feat.h5','w')
f.createArray(f.root,'feature',features)
f.close()
  • 1
  • 2
  • 3
  • 4

4 壓縮陣列(Compression Array)

HDF檔案還可以進行壓縮儲存,壓縮方式有blosc, zlib, 和 lzo。Zlib和lzo壓縮方式需要另外的包,blosc在tables是自帶的。我們需要定義一個filter來說明壓縮方式及壓縮深度。另外,我們使用creatCArray來建立壓縮矩陣。

f = tables.open_file('feat.h5', mode='w')
features = np.random.rand(100,100000)
filters=Filters(complevel=5,complib='blosc')
data_storage = f.createCArray(f.root,'feature',
                                    Atom.from_dtype(features.dtype),
                                    shape=features.shape,filters=filters)
data_storage[:]= features
f.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

5 壓縮可擴充套件陣列(Compression & Enlargeable Array)

壓縮陣列,初始化之後就不能改變大小,但現實很多時候,我們只知道維度,並不知道我們資料的長度。這個時候,我們需要這個陣列是可以擴充套件的。HDF檔案也提供這樣的介面,我們能夠擴充套件其一個維度。同CArray一樣,我們也先要定filter來宣告壓縮型別及深度。最重要的是,我們把可以擴充套件這個維度的shape設定為0。擴充套件資料的時候就使用append,這個資料shape必須為(1,data.shape[1])

f = tables.open_file('feat.h5', mode='w')
features = np.random.rand(100,100000)
filters=Filters(complevel=5,complib='blosc')

data_storage = f.createEArray(f.root,'feature',
                                    Atom.from_dtype(features.dtype),
                                    shape=(0,features.shape[1]),filters=filters)

for x in range(features.shape[0]):
    data_storage.append(features[:,x])
f.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

上述我們儲存的資料是浮點型,當我們要儲存字串型別的,我們同樣定義:

image_name  = '123fjo.jpg'
imageName_storage = f.createEArray(f.root,'filename',tables.StringAtom(itemsize=32),shape=(0,))
image_name = np.array([image_name],dtype=np.object)

imageName_storage.append(image_name)
  • 1
  • 2
  • 3
  • 4
  • 5

如果我們不知道字串的位元組數,我們在初始化的時候就不需要填。接著,我們需要把python string型別轉換為numpy object型別。這樣在新增資料就沒有問題了。

當然,HDF遠遠不止這些內容,但是目前只用到這麼多。如果以後有需要,我們再來深入學習。

參考網站:
[1]: http://www.pytables.org/ 官方網站,很齊全但是內容太多了。

[2]: https://kastnerkyle.github.io/posts/using-pytables-for-larger-than-ram-data-processing/ 很好的例子,如果不想看太多,就看這個例子,基本就夠用了。


轉載:https://blog.csdn.net/lengyuexiang123/article/details/53558779

相關文章