matplotlib绘制Pareto最优前沿时如何合并两个图例?
合并matplotlib双图例的实现方法
你遇到的双图例拆分问题,本质是循环绘制蓝色候选点时,每次调用ax.plot()都会生成一个独立的隐式图例条目,最终和红色帕累托点的图例分裂显示。只要给两类点分别指定唯一标签,matplotlib就会自动合并同类型元素的图例项,生成单个统一图例。
另外原代码存在几处会直接导致运行报错的问题,一并修复:
- 修复
dominates、pareto_front函数内部的缩进语法错误 - 修正坐标轴、标题的错误赋值写法(直接给
ax.xlabel、plt.title属性赋值是无效操作,需要调用官方提供的set_*方法) - 修正帕累托前沿的标签拼写错误(原代码写为
Pareto Font,应为Pareto Front) - 循环绘制蓝色点时仅在第一次传入标签参数,避免重复生成上千条无效图例项
修正后可直接运行的代码
import matplotlib.pyplot as plt import random def dominates(bestRouteTime, num_buses): dominating = False for i in range(len(bestRouteTime)): if bestRouteTime[i] > num_buses[i]: return False if bestRouteTime[i] < num_buses[i]: dominating = True return dominating def is_dominated(bestRouteTime, front): for num_buses in front: if dominates(num_buses, bestRouteTime): return True return False def pareto_front(cand): front = set([]) for i in cand: add_i = True for j in list(front): if dominates(i, j): front.remove(j) if dominates(j, i): add_i = False if add_i: front.add(i) front = list(front) front.sort() return front if __name__ == "__main__": # random.seed(1) cand = [(random.random()**.25, random.random()**.25) for i in range(1000)] fig, ax = plt.subplots(figsize=(10, 8)) # 绘制普通候选解,仅首次绘制传入标签避免重复图例 for idx, (bestRouteTime, num_buses) in enumerate(cand): x, y = (bestRouteTime * 360, num_buses * 10) if idx == 0: ax.plot(x, y, "bo", label="Candidate Solutions") else: ax.plot(x, y, "bo") # 绘制帕累托前沿点 front = pareto_front(cand) ax.plot( [x for (x, y) in front], [y for (x, y) in front], "ro", label="Pareto Front" ) # 设置坐标轴与标题 ax.set_ylabel('Number of Walking Buses') ax.set_xlabel('Travel Time (seconds)') ax.set_title("Pareto Optimal Fronts (TSPTW)") # 生成统一图例 ax.legend(loc='best', shadow=True, fontsize='large') plt.show()
运行代码后会生成单个合并后的图例,仅包含「候选解」「帕累托前沿」两个条目,不会再出现分裂的双图例问题。
内容的提问来源于stack exchange,提问作者agyengo44
相关产品推荐
相关产品推荐

