Matplotlib嵌套for循环绘制时间序列(轨迹)子图问题咨询
问题根因与解决方案
1. 嵌套循环正确绘制全部5组时间序列的方法
根因
你当前代码的逻辑是:每遍历一组时间序列,就重复创建一次所有位置的子图,新创建的子图会直接覆盖同位置已有的旧子图,所以最后只会保留最后一组(第5组)的绘制结果。如果把plt.show()放在第二层循环外侧,会在第一组序列绘制完成后直接渲染弹窗,阻塞后续代码执行,所以只能看到第一组结果。
修正逻辑
- 提前计算所有状态对应的子图行列数,一次性创建全部子图,避免重复创建覆盖
- 第一层循环仅遍历5组序列数据,第二层循环直接在已创建好的对应子图上叠加绘制曲线
2. 同一y变量设置统一坐标轴范围的方法
有两种常用实现方案:
- 自动共享:创建子图时指定
sharey='row'或sharey='col',相同行/列的子图会自动同步y轴取值范围,适合同类状态排列在同一行/列的场景 - 手动统一:提前遍历所有序列的所有状态值,计算每类状态(关节角度/速度/肌肉激活度)的全局最大、最小值,绘制完成后统一给同类子图设置
ylim,适配自定义范围需求
修正后可运行代码
import numpy as np import matplotlib.pyplot as plt # ---------------------- 提前准备参数,一次性创建子图 ---------------------- # 假设所有轨迹的状态定义一致,取第一个轨迹的状态计算子图行列 stateNames = list(Traj_List[0].getStateNames()) numStates = len(stateNames) dim = np.sqrt(numStates) if dim == np.ceil(dim): numRows = int(dim) numCols = int(dim) else: numCols = int(np.min([numStates, 4])) numRows = int(np.floor(numStates / 4)) if not numStates % 4 == 0: numRows += 1 # 一次性创建所有子图,sharey='row'表示同行子图共享y轴,可按需调整为col或关闭 fig, axs = plt.subplots(numRows, numCols, figsize=(38, 55), sharey='row') axs = axs.flatten() # 把子图数组转为一维,方便按索引遍历 color = ['r', 'b', 'g', 'y', 'm'] lines = ["-", "--", "-.", ":", "-."] linewidth = [3, 2.5, 3.5, 2, 3] # ---------------------- 嵌套循环叠加绘制所有序列 ---------------------- for i in range(len(Traj_List)): for j in np.arange(numStates): # 直接在已创建的子图上绘制,不再重复创建 ax = axs[j] ax.plot(Traj_List[i].getTimeMat(), Traj_List[i].getStateMat(stateNames[j]), linestyle=lines[i], color=color[i], linewidth=linewidth[i], label=Label_List[i]) # ---------------------- 统一设置子图标签、范围 ---------------------- for j in np.arange(numStates): ax = axs[j] stateName = stateNames[j] ax.set_title(stateName) ax.set_xlabel('time (s)') ax.legend(loc='best') if 'value' in stateName: ax.set_ylabel('position (rad)') # 如需手动设置统一范围,可提前计算所有位置类数据的max/min,替换下面的数值 # ax.set_ylim(min_pos, max_pos) elif 'speed' in stateName: ax.set_ylabel('speed (rad/s)') # ax.set_ylim(min_speed, max_speed) elif 'activation' in stateName: ax.set_ylabel('activation (-)') ax.set_ylim(0, 1) fig.tight_layout() plt.show() plt.close()
内容的提问来源于stack exchange,提问作者Ali Nikoo
相关产品推荐
相关产品推荐

