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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 01:59:53