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

Matplotlib多Figure列表绘图异常:系列图混入组图问题排查

问题原因分析

核心问题出在Matplotlib的figure编号复用机制上:你在初始化组和系列的figure时,都用了plt.figure(j)且j的取值范围完全相同(都是0和1)。Matplotlib中plt.figure(num)的逻辑是:如果指定的num已经对应一个存在的figure,就会直接返回这个已存在的对象,而不是创建新的。这就导致系列的figure其实和组的figure是同一个对象,后续的绘图操作自然会串到一起。

优雅的解决方法

我们可以完全避免手动指定figure编号,让Matplotlib自动分配唯一ID,同时完善绘图流程的完整性。下面是具体修改方案:

1. 修改figure初始化逻辑

把initGrpPlt和initSeriesPlt中的plt.figure(j)改为不带参数的plt.figure(),这样每次调用都会创建全新的独立figure:

def initGrpPlt():
    for group in Groups._GroupRegistry:
        for _ in range(maxNrVdrain):
            fig = plt.figure()  # 自动生成唯一编号的新figure
            group.figlist.append(fig)
            group.axlist.append(fig.add_subplot(111))
    return

def initSeriesPlt():
    for series in Series._SeriesRegistry:
        for _ in range(maxNrVdrain):
            fig = plt.figure()
            series.figlist.append(fig)
            series.axlist.append(fig.add_subplot(111))
    return

2. 完善系列图的显示流程

原来的代码只处理了组图的设置,漏掉了系列图的最终配置。在MainPlt中补充系列图的处理逻辑:

def MainPlt():
    initGrpPlt()
    initSeriesPlt()
    # 遍历晶体管填充所有绘图数据
    for trans in Transistor._TransRegistry:
        for j in range(maxNrVdrain):
            toGPlt(trans,j)
            toSPlt(trans,j)
    # 完成组图的标题等设置
    for j in range(maxNrVdrain):
        for group in Groups._GroupRegistry:
            PltGrp(group,j)
    # 完成系列图的图例、标题设置
    for j in range(maxNrVdrain):
        for series in Series._SeriesRegistry:
            PltSeries(series,j)
    plt.show()  # 一次性显示所有创建的figure
    return

完整修改后的代码

# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

maxNrVdrain = 2
X = np.linspace(-np.pi, np.pi, 256,endpoint=True)
A = [[1*np.cos(X),2*np.cos(X),3*np.cos(X),4*np.cos(X)],[1*np.tan(X),2*np.tan(X),3*np.tan(X),4*np.tan(X)]]
B = [[2* np.sin(X),4* np.sin(X),6* np.sin(X),8* np.sin(X)],[2*np.cos(X),4*np.cos(X),6*np.cos(X),8*np.cos(X)]]

class Transistor(object):
    _TransRegistry = []
    def __init__(self,y1,y2):
        self._TransRegistry.append(self)
        self.X = X
        self.Y = [y1,y2]
        self.group = ''

class Groups():
    _GroupRegistry = []
    def __init__(self,trans):
        self._GroupRegistry.append(self)
        self.transistors = [trans]
        self.figlist = []
        self.axlist = []

class Series():
    _SeriesRegistry = []
    def __init__(self,group):
        self._SeriesRegistry.append(self)
        self.groups = [group]
        self.figlist = []
        self.axlist = []

def initGrpPlt():
    for group in Groups._GroupRegistry:
        for _ in range(maxNrVdrain):
            fig = plt.figure()
            group.figlist.append(fig)
            group.axlist.append(fig.add_subplot(111))
    return

def initSeriesPlt():
    for series in Series._SeriesRegistry:
        for _ in range(maxNrVdrain):
            fig = plt.figure()
            series.figlist.append(fig)
            series.axlist.append(fig.add_subplot(111))
    return

def toGPlt(trans,j):
    colour = cm.rainbow(np.linspace(0, 1, 4))
    group = trans.group
    group.axlist[j].plot(trans.X,trans.Y[j], color=colour[group.transistors.index(trans)], linewidth=1.5, linestyle="-")
    return

def toSPlt(trans,j):
    colour = cm.rainbow(np.linspace(0, 1, 2))
    series = Series._SeriesRegistry[0]
    group = trans.group
    if group.transistors.index(trans) == 0:
        series.axlist[j].plot(trans.X,trans.Y[j],color=colour[series.groups.index(group)], linewidth=1.5, linestyle="-", label = 'T = nan, RH = nan' )
    else:
        series.axlist[j].plot(trans.X,trans.Y[j],color=colour[series.groups.index(group)], linewidth=1.5, linestyle="-")
    return

def PltGrp(group,j):
    ax = group.axlist[j]
    ax.set_title('Test Grp')
    return

def PltSeries(series,j):
    ax = series.axlist[j]
    ax.legend(loc='upper right', frameon=False)
    ax.set_title('Test Series')
    return

def MainPlt():
    initGrpPlt()
    initSeriesPlt()
    for trans in Transistor._TransRegistry:
        for j in range(maxNrVdrain):
            toGPlt(trans,j)
            toSPlt(trans,j)
    # 处理组图配置
    for j in range(maxNrVdrain):
        for group in Groups._GroupRegistry:
            PltGrp(group,j)
    # 处理系列图配置
    for j in range(maxNrVdrain):
        for series in Series._SeriesRegistry:
            PltSeries(series,j)
    plt.show()
    return

def Init():
    for j in range(4):
        trans = Transistor(A[0][j],A[1][j])
        if j == 0:
            Groups(trans)
        else:
            Groups._GroupRegistry[0].transistors.append(trans)
        trans.group = Groups._GroupRegistry[0]
    Series(Groups._GroupRegistry[0])

    for j in range(4):
        trans = Transistor(B[0][j],B[1][j])
        if j == 0:
            Groups(trans)
        else:
            Groups._GroupRegistry[1].transistors.append(trans)
        trans.group = Groups._GroupRegistry[1]
    Series._SeriesRegistry[0].groups.append(Groups._GroupRegistry[1])
    return

def main():
    Init()
    MainPlt()
    return

main()
额外优化建议
  • 尽量避免使用全局静态注册表(比如_TransRegistry),可以在Init函数中直接管理实例对象,代码会更清晰可控。
  • 提前计算绘图颜色映射,避免每次调用group.transistors.index(trans)的索引查找(当晶体管数量较多时会有性能损耗)。
  • 给每个figure添加更具辨识度的标题,比如包含组ID或系列名称,方便后续区分不同图表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:00:30