2017-07-18 1 views
1

Ich versuche, eine .mat-Datei in Python zu laden. Die Datei wurde wie folgt erstellt:laden verschachtelt defaultdict mit scipy.loadmat

import collections 
import scipy.io 

out_o = collections.defaultdict(list) 
out_t = collections.defaultdict(list) 
out_o['o1'] = {'x':[1,2,3], 'y':[4,5,6]} 
out_o['o2'] = {'x':[7,8,9], 'y':[10,11,12]} 
out_t['t'] = out_o 
scipy.io.savemat('test.mat', out_t) 

Wie kann ich out_t aus der Datei rekonstruieren test.mat ohne harte Codierung der Schlüssel out_o?

ich es geschafft, die Schlüssel zu bekommen mit:

input = scipy.io.loadmat('test.mat', squeeze_me=True, struct_as_record=True) 
print(list(input['t'].dtype.names)) 

[ 'o2', 'o1']

Aber wie greife ich auf die Daten?

print(input['t']) 

Drucke:

((Array ([7, 8, 9]), array ([10, 11, 12])), (Array ([1, 2, 3]), array ([4, 5, 6])))

Das ist so nah wie ich

zu x und y ... erhalten verwalten

edit:

Dank hpauljs Antwort gelang es mir, mein Problem zu lösen.

Ich konnte nicht hart codieren die oi s, so habe ich dtype.fields.keys():

input = scipy.io.loadmat('test.mat') 
objs = list(input['t'].dtype.fields.keys()) 
in_o = collections.defaultdict(list) 
in_t = collections.defaultdict(list) 
for i in objs: 
    in_o[i]={'x': list(input['t'][i][0,0]['x'][0,0][0]),'y': list(input['t'][i][0,0]['y'][0,0][0])} 
in_t['t'] = in_o 

print(in_t == out_t) 
+0

Was erhalten Sie ohne den Parameter 'struct_as_record'? 'savemat' komprimiert die Daten in Matlab-kompatible Strukturen. Es ist nicht dazu gedacht, Python-Pickel zu "pürieren". – hpaulj

Antwort

1

Sie sparen

In [409]: out_t 
Out[409]: 
defaultdict(list, 
      {'t': defaultdict(list, 
         {'o1': {'x': [1, 2, 3], 'y': [4, 5, 6]}, 
          'o2': {'x': [7, 8, 9], 'y': [10, 11, 12]}})}) 

und zurück

In [410]: R = io.loadmat('test.mat') 
In [411]: R 
Out[411]: 
{'__globals__': [], 
'__header__': b'MATLAB 5.0 MAT-file Platform: posix, Created on: Tue Jul 18 09:32:39 2017', 
'__version__': '1.0', 
't': array([[ (array([[(array([[1, 2, 3]]), array([[4, 5, 6]]))]], 
     dtype=[('x', 'O'), ('y', 'O')]), array([[(array([[7, 8, 9]]), array([[10, 11, 12]]))]], 
     dtype=[('x', 'O'), ('y', 'O')]))]], 
     dtype=[('o1', 'O'), ('o2', 'O')])} 

R['t'] ist ein (1,1) Array mit 2 Feldern, dtype([('o1', 'O'), ('o2', 'O')]).

Dies ist (1,1) Objekt-Array; das Element ist ein (1,1) Array mit 2 Feldern

In [424]: R['t']['o1'][0,0]['x'][0,0] 
Out[424]: array([[1, 2, 3]]) 

Matlab kompatibel zu sein, sind alle Arrays 2d. Wörterbücher werden als strukturierte Arrays mit einem Feld pro Schlüssel gespeichert.

Mit squeeze_me Indizierung ist etwas anders. Die (1,1) Objekt-Arrays wurden durch () (0d) Objekt-Arrays ersetzt.

Wie ich kommentiert. savemat speichert eine Matlab-kompatible Struktur. Verwenden Sie pickle, wenn Sie Python-Objekte speichern und erneut laden möchten.

Laden diese Datei in Octave gibt eine Struktur, t:

>> t 
t = 
    scalar structure containing the fields: 
    o1 = 
     scalar structure containing the fields: 
     x = 
      1 2 3 
     y = 
      4 5 6 
    o2 = 
     scalar structure containing the fields: 
     x = 
      7 8 9 
     y = 
      10 11 12 

np.save speichert Python mit ihren Beize-Objekte, nachdem sie zuerst in einem Objekt dtype Array Verpackung:

In [467]: np.save('test.npy', out_t) 
In [468]: np.load('test.npy') 
Out[468]: array(defaultdict(<class 'list'>, {'t': defaultdict(<class 'list'>, {'o1': {'x': [1, 2, 3], 'y': [4, 5, 6]}, 'o2': {'x': [7, 8, 9], 'y': [10, 11, 12]}})}), dtype=object) 
In [469]: _.item() 
Out[469]: 
defaultdict(list, 
      {'t': defaultdict(list, 
         {'o1': {'x': [1, 2, 3], 'y': [4, 5, 6]}, 
          'o2': {'x': [7, 8, 9], 'y': [10, 11, 12]}})}) 
+0

Vielen Dank für die ausführliche Antwort, mit Ihrer Hilfe konnte ich mein Problem lösen (siehe Frage bearbeiten) – Jonas