web-dev-qa-db-ja.com

h5pyを介してv7.3マットファイルを読み取る方法は?

Matlabによって作成され、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')

今、私はこのファイルをpython using h5py:

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

struArrayから構造体データを1つずつ取得する方法がわかりません。

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>
15
Eastsun

Matlab 7.3ファイル形式は、h5pyでの作業が非常に簡単ではありません。これは、HDF5リファレンスに依存しています。 参照に関するh5pyドキュメント

_>>> 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'
_
6
nbedou

visitまたはvisititemsは、h5pyファイルの全体的な構造をすばやく確認する方法です。

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

Octave 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">

これはMATLAB7.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]
3
hpaulj

まず、インタープリターを起動し、helpstruarrayを実行します。それはあなたが始めるのに十分な情報をあなたに与えるはずです。それができない場合は、__dict__属性をprintすることで、任意のPythonオブジェクトの属性をダンプできます。

0

申し訳ありませんが、Matlabの外部からセル/構造のコンテンツを取得することは非常に難しいと思います。生成されたファイルを(たとえばHDFViewで)表示すると、相互参照がたくさんあり、続行する明確な方法がないことがわかります。

単純な数値配列に固執する場合、それはうまく機能します。数値配列を含むスモールセル配列がある場合は、それらを個別の変数(つまり、cellcontents1、cellcontents2など)に変換できます。これは通常、数行であり、直接保存およびロードできます。したがって、あなたの例では、vars name1, name2, name3, id1, id2, id3 ...などでファイルを保存します。

編集:あなたは質問でh5pyを指定したので、私は答えましたが、scipy.io.loadmatを使用すると、元の変数を同等のnumpy(オブジェクト配列など)に変換できるはずです。

0
robince