如何为Matplotlib绘制的每条折线添加不同标记符号?
优化算法收敛曲线:自定义折线样式与标记
我写了一段基于Matplotlib、Pandas的Python代码,用来绘制优化算法的收敛曲线,目前生成了9条不同颜色的虚线,但想给每条折线设置不同的线型或者标记符号,方便区分。以下是我的代码和数据样本:
原始代码
import matplotlib.pyplot as plt import pandas as pd from pathlib import Path import numpy as np def run(results_directory, optimizer, objectivefunc, Iterations): plt.ioff() fileResultsData = pd.read_csv(results_directory + "/exp.csv") plt.figure(figsize=(10, 10)) for j in range(0, len(objectivefunc)): objective_name = objectivefunc[j] startIteration = 0 if "SSA" in optimizer: startIteration = 1 allGenerations = [x + 1 for x in range(startIteration, Iterations)] for i in range(len(optimizer)): optimizer_name = optimizer[i] row = fileResultsData[ (fileResultsData["Optimizer"] == optimizer_name) & (fileResultsData["objfname"] == objective_name) ] row = row.iloc[:, 3 + startIteration :] plt.plot(allGenerations, row.values.tolist()[0],linestyle = 'dashed',label=optimizer_name) plt.title("Curve") plt.xlabel("Iterations") plt.ylabel("Fitness") plt.yscale("log") plt.legend(loc="upper right", bbox_to_anchor=(1.2, 1.02)) plt.grid() fig_name = results_directory + "/convergence0-" + objective_name + ".png" plt.savefig(fig_name, bbox_inches="tight") plt.clf() p = Path(r"C:\Users\sa\Desktop\C2017") p.mkdir(parents=True, exist_ok=True) run(str(p), ["HybridSSALEO","MFO","CSO","SSA", "HHO","PSO","SCA","WOA","BAT"],["f1"], 2500)
数据样本
Optimizer objfname ExecutionTime Iter1 Iter2 Iter3 Iter4 Iter5 Iter6 Iter7 ... Iter2491 Iter2492 Iter2493 Iter2494 Iter2495 Iter2496 Iter2497 Iter2498 Iter2499 Iter2500 0 HybridSSALEO f1 7.43 2.580000e+12 2.290000e+12 2.170000e+12 2.050000e+12 1.820000e+12 1.700000e+12 1.650000e+12 ... 2104.890630 2104.880800 2104.874638 2104.868994 2104.863237 2104.857936 2104.853139 2104.849307 2104.843981 2104.829836 1 HybridSSALEO f2 9.46 5.955520e+10 2.445214e+08 6.004195e+06 5.798884e+06 2.734759e+06 2.633134e+06 1.713644e+06 ... 375.136389 375.017438 374.943893 374.869639 374.687064 374.602179 374.544733 374.447893 374.358422 374.317267 2 HybridSSALEO f3 14.09 1.516994e+09 2.770653e+05 2.728020e+05 2.684405e+05 2.169289e+05 2.123749e+05 2.080267e+05 ... 440.787196 440.777427 440.772892 440.748491 440.711001 440.698250 440.683562 440.677350 440.676047 440.668172 3 HybridSSALEO f4 12.08 2.826890e+03 2.549340e+03 2.452620e+03 1.579159e+03 1.558178e+03 1.477120e+03 1.458300e+03 ... 788.193094 788.193094 788.193094 788.193094 788.193094 788.193094 788.193094 788.193094 788.193094 788.193094 4 HybridSSALEO f5 21.16 8.074877e+02 8.014014e+02 7.957303e+02 7.931306e+02 7.913393e+02 7.872639e+02 7.811320e+02 ... 679.420922 679.420593 679.420393 679.420133 679.419760 679.419323 679.419027 679.418699 679.418348 679.417955 5 rows × 2503 columns
解决方案:自定义折线样式与标记
方法1:手动定义线型和标记列表
因为有9个优化器,我们可以预先定义9种不同的线型和标记符号,循环绘制时一一对应。考虑到迭代次数高达2500次,直接显示所有标记会导致重叠,所以用markevery参数控制标记显示间隔。
修改后的代码:
import matplotlib.pyplot as plt import pandas as pd from pathlib import Path import numpy as np def run(results_directory, optimizer, objectivefunc, Iterations): plt.ioff() # 预定义9种不同线型和标记,数量和optimizer一致 linestyles = ['-', '--', '-.', ':', '-', '--', '-.', ':', '-'] markers = ['o', 's', '^', 'D', 'p', '*', 'h', 'x', '+'] # 控制标记显示间隔,避免过于密集 mark_interval = 200 fileResultsData = pd.read_csv(results_directory + "/exp.csv") plt.figure(figsize=(10, 10)) for j in range(0, len(objectivefunc)): objective_name = objectivefunc[j] startIteration = 0 if "SSA" in optimizer: startIteration = 1 allGenerations = [x + 1 for x in range(startIteration, Iterations)] for i in range(len(optimizer)): optimizer_name = optimizer[i] row = fileResultsData[ (fileResultsData["Optimizer"] == optimizer_name) & (fileResultsData["objfname"] == objective_name) ] row = row.iloc[:, 3 + startIteration :] # 调用plot时指定当前优化器对应的线型、标记和间隔 plt.plot(allGenerations, row.values.tolist()[0], linestyle=linestyles[i], marker=markers[i], markevery=mark_interval, label=optimizer_name) plt.title("Convergence Curve") plt.xlabel("Iterations") plt.ylabel("Fitness") plt.yscale("log") plt.legend(loc="upper right", bbox_to_anchor=(1.2, 1.02)) plt.grid() fig_name = results_directory + "/convergence0-" + objective_name + ".png" plt.savefig(fig_name, bbox_inches="tight") plt.clf() p = Path(r"C:\Users\sa\Desktop\C2017") p.mkdir(parents=True, exist_ok=True) run(str(p), ["HybridSSALEO","MFO","CSO","SSA", "HHO","PSO","SCA","WOA","BAT"],["f1"], 2500)
方法2:利用Matplotlib自动循环样式
如果不想手动定义,可以通过设置rcParams让Matplotlib自动循环不同的线型和标记,代码更简洁:
修改后的代码:
import matplotlib.pyplot as plt import pandas as pd from pathlib import Path import numpy as np from matplotlib import cycler def run(results_directory, optimizer, objectivefunc, Iterations): plt.ioff() # 设置自动循环的样式组合:颜色+线型+标记 plt.rcParams['axes.prop_cycle'] = cycler('color', plt.cm.tab10(np.linspace(0,1,9))) + \ cycler('linestyle', ['-', '--', '-.', ':', '-', '--', '-.', ':', '-']) + \ cycler('marker', ['o', 's', '^', 'D', 'p', '*', 'h', 'x', '+']) mark_interval = 200 fileResultsData = pd.read_csv(results_directory + "/exp.csv") plt.figure(figsize=(10, 10)) for j in range(0, len(objectivefunc)): objective_name = objectivefunc[j] startIteration = 0 if "SSA" in optimizer: startIteration = 1 allGenerations = [x + 1 for x in range(startIteration, Iterations)] for i in range(len(optimizer)): optimizer_name = optimizer[i] row = fileResultsData[ (fileResultsData["Optimizer"] == optimizer_name) & (fileResultsData["objfname"] == objective_name) ] row = row.iloc[:, 3 + startIteration :] # 无需手动指定样式,自动循环 plt.plot(allGenerations, row.values.tolist()[0], markevery=mark_interval, label=optimizer_name) plt.title("Convergence Curve") plt.xlabel("Iterations") plt.ylabel("Fitness") plt.yscale("log") plt.legend(loc="upper right", bbox_to_anchor=(1.2, 1.02)) plt.grid() fig_name = results_directory + "/convergence0-" + objective_name + ".png" plt.savefig(fig_name, bbox_inches="tight") plt.clf() p = Path(r"C:\Users\sa\Desktop\C2017") p.mkdir(parents=True, exist_ok=True) run(str(p), ["HybridSSALEO","MFO","CSO","SSA", "HHO","PSO","SCA","WOA","BAT"],["f1"], 2500)
内容的提问来源于stack exchange,提问作者Mhd33
相关产品推荐
相关产品推荐

