2013-10-11 46 views
12

我有MATLAB創建並存儲在7.3版格式墊文件一個結構數組:如何通過h5py讀取v7.3 mat文件?

struArray = struct('name', {'one', 'two', 'three'}, 
        'id', {1,2,3}, 
        'data', {[1:10], [3:9], [0]}) 
save('test.mat', 'struArray', '-v7.3') 

現在我想用h5py讀通過Python這個文件:

data = h5py.File('test.mat') 
struArray = data['/struArray'] 

我不知道如何從struArray一個的結構數據之一:

for index in range(<the size of struArray>): 
    elem = <the index th struct in struArray> 
    name = <the name of elem> 
    id = <the id of elem> 
    data = <the data of elem> 
+0

你找到這樣的一個實際的解決方案? – Pastafarian

+0

我有一個類似的問題,與部分解決:http://stackoverflow.com/questions/29852481/reading-all-variables-in-a-mat-file-with-python-h5py/29856030#29856030 – CodyF

回答

0

Matlab的7.3文件格式不極易與h5py工作。它依賴於HDF5參考,參見h5py documentation on references

>>> import h5py 
>>> f = h5py.File('test.mat') 
>>> list(f.keys()) 
['#refs#', 'struArray'] 
>>> struArray = f['struArray'] 
>>> struArray['name'][0, 0] # this is the HDF5 reference 
<HDF5 object reference> 
>>> f[struArray['name'][0, 0]].value # this is the actual data 
array([[111], 
     [110], 
     [101]], dtype=uint16) 

要閱讀struArray(i).id

>>> f[struArray['id'][0, 0]][0, 0] 
1.0 
>>> f[struArray['id'][1, 0]][0, 0] 
2.0 
>>> f[struArray['id'][2, 0]][0, 0] 
3.0 

注意,Matlab的存儲號碼作爲大小的陣列(1,1),因此最終[0, 0]得到的數量。

閱讀struArray(i).data

>>> f[struArray['data'][0, 0]].value 
array([[ 1.], 
     [ 2.], 
     [ 3.], 
     [ 4.], 
     [ 5.], 
     [ 6.], 
     [ 7.], 
     [ 8.], 
     [ 9.], 
     [ 10.]]) 

要閱讀struArray(i).name,有必要整數數組字符串轉換:

>>> f[struArray['name'][0, 0]].value.tobytes()[::2].decode() 
'one' 
>>> f[struArray['name'][1, 0]].value.tobytes()[::2].decode() 
'two' 
>>> f[struArray['name'][2, 0]].value.tobytes()[::2].decode() 
'three' 
0

我會被解僱瞭解釋,並在01運行help啓動。它應該給你足夠的信息,讓你開始。否則,您可以通過print轉儲任何Python對象的屬性__dict__屬性。

0

對不起,但我認爲從Matlab的外部獲取單元/結構的內容將是相當具有挑戰性的。如果您查看生成的文件(例如使用HDFView),您會看到有很多交叉引用,並且沒有明顯的方法可以繼續。

如果你堅持簡單的數值數組,它可以正常工作。如果你有包含數值數組的小單元格數組,你可以將它們轉換爲單獨的變量(即cellcontents1,cellcontents2等),它通常只有幾行,並允許它們直接保存和加載。因此,在你的例子,我會保存瓦爾name1, name2, name3, id1, id2, id3 ...

編輯一個文件:你在問題中指定h5py所以這就是我回答,但值得一提的是,與scipy.io.loadmat你應該能夠得到原始變量轉換爲NumPy的等價物(例如對象數組)。

+4

還是要謝謝你!幾天後我就與這個問題鬥爭了。我總是得到像這樣的東西,而不是真正的值。然而,'scipy.io.loadmat'不用於消文件的7.3版格式工作。 – Eastsun

-1

這真的是Matlab 7.3和h5py的問題。 我的竅門是將h5py._hl.dataset.Dataset類型轉換爲numpy數組。 例如,

np.array(data['data']) 

將解決你的問題與'data'領域。

+0

不起作用。只是在現有的圖層上添加另一個數組圖層。例如。 '陣列([[]],D型細胞=對象)的類型''的和現有的數據IS h5py._hl.dataset.Dataset' – Pastafarian

2

visitvisititems是看到h5py文件的整體結構的快速方法:

fs['struArray'].visititems(lambda n,o:print(n, o)) 

當我通過倍頻save -hdf5製作的文件運行此我得到:

type <HDF5 dataset "type": shape(), type "|S7"> 
value <HDF5 group "/struArray/value" (3 members)> 
value/data <HDF5 group "/struArray/value/data" (2 members)> 
value/data/type <HDF5 dataset "type": shape(), type "|S5"> 
value/data/value <HDF5 group "/struArray/value/data/value" (4 members)> 
value/data/value/_0 <HDF5 group "/struArray/value/data/value/_0" (2 members)> 
value/data/value/_0/type <HDF5 dataset "type": shape(), type "|S7"> 
value/data/value/_0/value <HDF5 dataset "value": shape (10, 1), type "<f8"> 
value/data/value/_1 <HDF5 group "/struArray/value/data/value/_1" (2 members)> 
... 
value/data/value/dims <HDF5 dataset "dims": shape (2,), type "<i4"> 
value/id <HDF5 group "/struArray/value/id" (2 members)> 
value/id/type <HDF5 dataset "type": shape(), type "|S5"> 
value/id/value <HDF5 group "/struArray/value/id/value" (4 members)> 
value/id/value/_0 <HDF5 group "/struArray/value/id/value/_0" (2 members)> 
... 
value/id/value/_2/value <HDF5 dataset "value": shape(), type "<f8"> 
value/id/value/dims <HDF5 dataset "dims": shape (2,), type "<i4"> 
value/name <HDF5 group "/struArray/value/name" (2 members)> 
... 
value/name/value/dims <HDF5 dataset "dims": shape (2,), type "<i4"> 

這可能與MATLAB 7.3產生的不一樣,但它提供了一個結構複雜性的概念。

更精細的回調可以顯示值,並且可能是重新創建Python對象(字典,列表等)的起點。

def callback(name, obj): 
    if name.endswith('type'): 
     print('type:', obj.value) 
    elif name.endswith('value'): 
     if type(obj).__name__=='Dataset': 
      print(obj.value.T) # http://stackoverflow.com/questions/21624653 
    elif name.endswith('dims'): 
     print('dims:', obj.value) 
    else: 
     print('name:', name) 

fs.visititems(callback) 

生產:

name: struArray 
type: b'struct' 
name: struArray/value/data 
type: b'cell' 
name: struArray/value/data/value/_0 
type: b'matrix' 
[[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]] 
name: struArray/value/data/value/_1 
type: b'matrix' 
[[ 3. 4. 5. 6. 7. 8. 9.]] 
name: struArray/value/data/value/_2 
type: b'scalar' 
0.0 
dims: [3 1] 
name: struArray/value/id 
type: b'cell' 
name: struArray/value/id/value/_0 
type: b'scalar' 
1.0 
... 
dims: [3 1] 
name: struArray/value/name 
type: b'cell' 
name: struArray/value/name/value/_0 
type: b'sq_string' 
[[111 110 101]] 
... 
dims: [3 1]