You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重构从Simulink .mat文件读取的嵌套Numpy结构化数组?

问题描述

我用Python的scipy.io.loadmat()读取了Simulink导出的.mat数据结构,想在Python中程序化重建这个结构,但始终无法正确实现多层嵌套。读取后的mat['rtp']['internal']结构如下:

>>> mat['rtp']['internal']
array( [[
    array( [[ (
        array( [[
            array( [[
                (array(['Br'], dtype='<U2'), array([[1]], dtype=uint8), array([[2]], dtype=uint8), array([[0]], dtype=uint8)),
                (array(['Ari'], dtype='<U3'), array([[1]], dtype=uint8), array([[3]], dtype=uint8), array([[0]], dtype=uint8))
            ]],
            dtype=[('name', 'O'), ('transitionIdx', 'O'), ('mapIdx', 'O'), ('isStruct', 'O')] )
        ]],
        dtype=object), )
    ]],
    dtype=[('tunedParameters', 'O')] )
]],
dtype=object )

我已经写出了创建内部参数部分的代码(变量a):

import numpy as np

dt = np.dtype([('name','O'),('transitionIdx','O'),('mapIdx','O'),('isStruct','O')])

all_entries = np.empty( 0, dtype=dt)

# Br PARAMETERS:
paramName = 'Br'
transitionIdx = 1
paramIdx = 2
isStruct = 0

new_entry = np.empty( 1, dtype=dt)
new_entry['name'] = [np.array( np.array([paramName]))]
new_entry['transitionIdx'] = [np.array([np.array([transitionIdx])],dtype=np.uint8)]
new_entry['mapIdx'] = [np.array([np.array([paramIdx])],dtype=np.uint8)]
new_entry['isStruct'] = [np.array([np.array([isStruct])],dtype=np.uint8)]

all_entries = np.append(all_entries, new_entry)

# Ari PARAMETERS:
paramName = 'Ari'
transitionIdx = 1
paramIdx = 3
isStruct = 0

new_entry = np.empty( 1, dtype=dt)
new_entry['name'] = [np.array( np.array([paramName]))]
new_entry['transitionIdx'] = [np.array([np.array([transitionIdx])],dtype=np.uint8)]
new_entry['mapIdx'] = [np.array([np.array([paramIdx])],dtype=np.uint8)]
new_entry['isStruct'] = [np.array([np.array([isStruct])],dtype=np.uint8)]

all_entries = np.append(all_entries, new_entry)

print( f"all_entries = {all_entries}" )
print( f"all_entries.dtype = {all_entries.dtype}" )

a = np.array([all_entries,])
print( f"a = {a}" )
print( f"a.dtype = {a.dtype}" )

这段代码的输出是:

a = [[(array(['Br'], dtype='<U2'), array([[1]], dtype=uint8), array([[2]], dtype=uint8), array([[0]], dtype=uint8))
  (array(['Ari'], dtype='<U3'), array([[1]], dtype=uint8), array([[3]], dtype=uint8), array([[0]], dtype=uint8))]]
a.dtype = [('name', 'O'), ('transitionIdx', 'O'), ('mapIdx', 'O'), ('isStruct', 'O')]

但我没法实现类似array( [[ array( [[ array( [[的多层嵌套结构,不知道怎么完整重构这个数据结构。

编辑补充
根据建议,我写了一个遍历结构并打印数组类型和形状的脚本:

import numpy as np
import scipy

mat = scipy.io.loadmat( "simulink_model_input.mat", mat_dtype=True )

def traverse( mat_str ):
    mat = eval( mat_str )
    if type( mat ) not in [str,np.str_]:
        print( f"{mat_str} type: {type(mat)} shape: {np.shape(mat)}, dtype: {mat.dtype}" )
        traverse( mat_str + "[0]" )

traverse( "mat['rtp']['internal']" )

输出结果:

mat['rtp']['internal'] type: <class 'numpy.ndarray'> shape: (1, 1), dtype: object
mat['rtp']['internal'][0] type: <class 'numpy.ndarray'> shape: (1,), dtype: object
mat['rtp']['internal'][0][0] type: <class 'numpy.ndarray'> shape: (1, 1), dtype: [('tunedParameters', 'O')]
mat['rtp']['internal'][0][0][0] type: <class 'numpy.ndarray'> shape: (1,), dtype: [('tunedParameters', 'O')]
mat['rtp']['internal'][0][0][0][0] type: <class 'numpy.void'> shape: (), dtype: [('tunedParameters', 'O')]
mat['rtp']['internal'][0][0][0][0][0] type: <class 'numpy.ndarray'> shape: (1, 1), dtype: object
mat['rtp']['internal'][0][0][0][0][0][0] type: <class 'numpy.ndarray'> shape: (1,), dtype: object
mat['rtp']['internal'][0][0][0][0][0][0][0] type: <class 'numpy.ndarray'> shape: (1, 2), dtype: [('name', 'O'), ('transitionIdx', 'O'), ('mapIdx', 'O'), ('isStruct', 'O')]
mat['rtp']['internal'][0][0][0][0][0][0][0][0] type: <class 'numpy.ndarray'> shape: (2,), dtype: [('name', 'O'), ('transitionIdx', 'O'), ('mapIdx', 'O'), ('isStruct', 'O')]
mat['rtp']['internal'][0][0][0][0][0][0][0][0][0] type: <class 'numpy.void'> shape: (), dtype: [('name', 'O'), ('transitionIdx', 'O'), ('mapIdx', 'O'), ('isStruct', 'O')]
mat['rtp']['internal'][0][0][0][0][0][0][0][0][0][0] type: <class 'numpy.ndarray'> shape: (1,), dtype: <U2

我还是不清楚怎么推进,只要能搞懂一层嵌套的实现方式,应该就能完成剩下的部分。

解决方案

核心思路是从内到外逐层嵌套,每一层都严格匹配遍历结果中的shape和dtype:

import numpy as np

# --- 保留你已有的参数生成代码 ---
dt = np.dtype([('name','O'),('transitionIdx','O'),('mapIdx','O'),('isStruct','O')])
all_entries = np.empty(0, dtype=dt)

# Br参数
paramName = 'Br'
transitionIdx = 1
paramIdx = 2
isStruct = 0
new_entry = np.empty(1, dtype=dt)
new_entry['name'] = [np.array([paramName])]
new_entry['transitionIdx'] = [np.array([[transitionIdx]], dtype=np.uint8)]
new_entry['mapIdx'] = [np.array([[paramIdx]], dtype=np.uint8)]
new_entry['isStruct'] = [np.array([[isStruct]], dtype=np.uint8)]
all_entries = np.append(all_entries, new_entry)

# Ari参数
paramName = 'Ari'
transitionIdx = 1
paramIdx = 3
isStruct = 0
new_entry = np.empty(1, dtype=dt)
new_entry['name'] = [np.array([paramName])]
new_entry['transitionIdx'] = [np.array([[transitionIdx]], dtype=np.uint8)]
new_entry['mapIdx'] = [np.array([[paramIdx]], dtype=np.uint8)]
new_entry['isStruct'] = [np.array([[isStruct]], dtype=np.uint8)]
all_entries = np.append(all_entries, new_entry)
# --- 已有代码结束 ---

# 逐层构建嵌套结构
# 1. 包成(1,2)的结构化数组(对应遍历中的最内层参数数组上层)
level7 = np.array([all_entries], dtype=dt)

# 2. 包成(1,)的object数组
level6 = np.array([level7], dtype=object)

# 3. 包成(1,1)的object数组
level5 = np.array([level6], dtype=object)

# 4. 创建tunedParameters结构化类型,生成(1,1)的该类型数组并赋值
dt_tuned = np.dtype([('tunedParameters', 'O')])
level4 = np.empty((1,1), dtype=dt_tuned)
level4['tunedParameters'] = level5

# 5. 包成(1,)的tunedParameters类型数组
level3 = np.array([level4[0][0]], dtype=dt_tuned)

# 6. 包成(1,1)的object数组
level2 = np.array([level3], dtype=object)

# 7. 包成(1,)的object数组
level1 = np.array([level2], dtype=object)

# 8. 最外层:(1,1)的object数组,即目标结构
final_internal = np.array([level1], dtype=object)

# 验证结构(用你之前的遍历逻辑)
def traverse(obj, path="final_internal"):
    if not isinstance(obj, (str, np.str_)):
        print(f"{path} type: {type(obj)} shape: {np.shape(obj)}, dtype: {obj.dtype}")
        if hasattr(obj, '__getitem__') and np.shape(obj) != ():
            traverse(obj[0], path + "[0]")

traverse(final_internal)

关键说明

  • 每一层嵌套都用np.array()包裹上一层数组,同时指定对应的dtype:要么是结构化类型(如dt、dt_tuned),要么是object类型(用于存放任意数组)
  • 结构化数组的赋值必须通过字段名(如level4['tunedParameters'] = level5),确保嵌套数组被放到正确的字段中
  • 严格匹配遍历结果中的shape,比如最外层是(1,1)的object数组,每一层的形状都要和遍历输出对应

内容的提问来源于stack exchange,提问作者nwhite43

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 06:35:28