【问题标题】:How can I create a Matlab file from Python with multi-dimensional arrays in a Matlab data structure?如何从 Python 中创建具有 Matlab 数据结构中的多维数组的 Matlab 文件?
【发布时间】:2018-11-16 16:11:14
【问题描述】:

我正在尝试从 Python 创建一个 Matlab 文件 (*.mat),其中包含一个 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 中做到这一点?

谢谢

【问题讨论】:

    标签: python matlab numpy


    【解决方案1】:

    这是任务的尝试:

    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')])}
    

    因此,虽然创建了一个具有 intint(3) 等 dtype 的 numpy 结构化数组,但加载的数组具有所有字段的 object dtype。 loadmat 大量使用对象 dtype 数组来处理 MATLAB 单元和结构的一般性。 loadmat 有各种加载参数,我们可以玩弄。

    这只是基于之前加载 MATLAB 文件的经验的猜测。如果这不是您想要的,我建议在 MATLAB 中构建示例数据,保存它,然后加载以查看 loadmat 是如何构建它的。您可能需要来回多次才能解决错误。

    【讨论】:

      【解决方案2】:

      根据 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-11
        相关资源
        最近更新 更多