Как я могу создать файл Matlab из Python с многомерными массивами в структуре данных Matlab? - PullRequest
0 голосов
/ 06 июня 2018

Я пытаюсь создать файл Matlab (* .mat) из Python, который содержит структуру данных Matlab, которая будет выглядеть следующим образом:

s.key1 where key1 is an array of values
s.key2 where key2 is an array of 1D arrays 
s.key3 where key3 is an array of 2D arrays 

Если я использую savemat и словарь, вывод Matlab будетмассив ячеек, а не структура данных Matlab.

Я пытался использовать

np.core.records.fromarrays(data_list, names=q_keys)

, но, похоже, это не работает для ключей с двумерными массивами.У меня есть как 2D, так и 3D массивы, которые должны быть в структуре Matlab для совместимости с существующим форматом файла.Есть ли способ сделать это в Python?

Спасибо

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Учитывая направление, предоставленное hpaulj, я разработал следующую функцию, которая создала структуру из списка объектов.

    def listobj2struct(list_in):
    """Converts a list of objects to a structured array.

    Parameters
    ----------
    list_in: list
        List of objects

    Returns
    -------
    struct: np.array
        Structured array
    """

    # Create data type for each variable in object
    keys = list(vars(list_in[0]).keys())
    data_type = []
    for key in keys:
        data_type.append((key, list))

    # Create structured array based on data type and length of list
    dt = np.dtype(data_type)
    struct = np.zeros((len(list_in),), dt)

    # Populate the structure with data from the objects
    for n, item in enumerate(list_in):
        new_dict = vars(item)
        for key in new_dict:
            struct[key][n] = new_dict[key]

    return struct

Чтобы завершить то, что мне нужно было сделать, чтобы создать файл Matlab из сложного вложенияИз объектов я также написал следующие функции.Возможно, это поможет другим, сталкивающимся с подобными задачами.Возможно, есть и лучшие способы, но у меня это сработало.

    def obj2dict(obj):
    """Converts object variables to dictionaries. Works recursively to all levels of objects.

    Parameters
    ----------
    obj: object
        Object of some class

    Returns
    -------
    obj_dict: dict
        Dictionary of all object variables
    """

    obj_dict = vars(obj)
    for key in obj_dict:
        # Clean out NoneTypes
        if obj_dict[key] is None:
            obj_dict[key] = []
        # If variable is another object convert to dictionary recursively
        elif str(type(obj_dict[key]))[8:13] == 'Class':
            obj_dict[key]=obj2dict(obj_dict[key])

    return obj_dict


def listobj2dict(list_in):
    """Converts list of objects to list of dictionaries. Works recursively to all levels of objects.

    Parameters
    ----------
    obj: object
        Object of some class

    Returns
    -------
    new_list: list
        List of dictionaries
    """
    new_list = []
    for obj in list_in:
        new_list.append(obj2dict(obj))
    return new_list


def listdict2struct(list_in):
    """Converts a list of dictionaries to a structured array.

    Parameters
    ----------
    list_in: list
        List of dictionaries

    Returns
    -------
    struct: np.array
        Structured array
    """

    # Create data type for each variable in object
    keys = list(list_in[0].keys())
    data_type = []
    for key in keys:
        data_type.append((key, list))

    # Create structured array based on data type and length of list
    dt = np.dtype(data_type)
    struct = np.zeros((len(list_in),), dt)

    # Populate the structure with data from the objects
    for n, item in enumerate(list_in):
        new_dict = item
        for key in new_dict:
            struct[key][n] = new_dict[key]

    return struct
0 голосов
/ 07 июня 2018

Вот удар по задаче:

In [292]: dt = np.dtype([('key1',int),('key2',int, (3,)),('key3',object)])
In [293]: arr = np.zeros((5,), dt)
In [294]: arr
Out[294]: 
array([(0, [0, 0, 0], 0), (0, [0, 0, 0], 0), (0, [0, 0, 0], 0),
       (0, [0, 0, 0], 0), (0, [0, 0, 0], 0)],
      dtype=[('key1', '<i8'), ('key2', '<i8', (3,)), ('key3', 'O')])
In [295]: arr['key1']=np.arange(5)
In [296]: arr['key2']=np.arange(15).reshape(5,3)
In [302]: arr['key3']=[1,np.arange(5),np.ones((2,3),int),'astring',[['a','b']]]
In [303]: io.savemat('test.mat', {'astruct':arr})

В октаве:

>> load test.mat
>> format compact
>> astruct
astruct =

  1x5 struct array containing the fields:

    key1
    key2
    key3
>> astruc.key1
error: 'astruc' undefined near line 1 column 1
>> astruct.key1
ans = 0
ans = 1
ans = 2
ans = 3
ans = 4
>> astruct.key2
ans =
  0  1  2
ans =
  3  4  5
ans =
  6  7  8
ans =
   9  10  11
ans =
  12  13  14
>> astruct.key3
ans = 1
ans =
  0  1  2  3  4
ans =
  1  1  1
  1  1  1
ans = astring
ans = ab

Назад в ipython:

In [304]: d = io.loadmat('test.mat')
In [305]: d
Out[305]: 
{'__header__': b'MATLAB 5.0 MAT-file Platform: posix, Created on: Wed Jun  6 15:36:23 2018',
 '__version__': '1.0',
 '__globals__': [],
 'astruct': array([[(array([[0]]), array([[0, 1, 2]]), array([[1]])),
         (array([[1]]), array([[3, 4, 5]]), array([[0, 1, 2, 3, 4]])),
         (array([[2]]), array([[6, 7, 8]]), array([[1, 1, 1],
        [1, 1, 1]])),
         (array([[3]]), array([[ 9, 10, 11]]), array(['astring'], dtype='<U7')),
         (array([[4]]), array([[12, 13, 14]]), array([['a', 'b']], dtype='<U1'))]],
       dtype=[('key1', 'O'), ('key2', 'O'), ('key3', 'O')])}

Итак, пока созданnumpy структурированный массив с dtypes, как int и int(3), загруженный массив имеет объект dtype для всех полей.loadmat интенсивно использует массивы dtype объектов для обработки общности ячеек MATLAB и структуры.loadmat имеет различные параметры загрузки, с которыми мы можем играть.

Это было лишь предположение, основанное на предыдущем опыте загрузки файлов MATLAB.Если это не то, что вам нужно, я бы предложил создать пример данных в MATLAB, сохранить его, а затем загрузить, чтобы посмотреть, как его создает loadmat.Возможно, вам придется несколько раз возвращаться и исправлять ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...