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

Python matplotlib多序列绘图线型区分选择方法(水文场景)

降水扰动情景水文对比图线型优化方案

当前图件4类水文要素共20组序列挤在双轴坐标系内,仅靠同色系下不同marker区分,视觉编码维度单一,线条、符号堆叠后辨识度极低,可按以下方向优化:

一、视觉编码分层(核心提升区分度)

  • 给不同要素大类绑定固定的、不重复的视觉属性,不要混同:
    • 降水(P):蓝色系、实线、圆形类marker,线宽1.2
    • 蒸散发(ET):红/橙红色系、虚线、方形类marker,线宽1.2
    • 径流(Q):绿色系、点划线、菱形类marker,线宽1.2
    • 雪水当量(SWE):青/蓝紫色系、点线、五边形类marker,线宽1.5(SWE在左轴,稍粗的线宽可以和右轴要素直接拉开差异)
    • 基准情景(100%降水)统一用纯黑色,线宽2,marker比其他情景大2号,作为参考线突出显示,不用和其他扰动情景共用同色系
  • 同要素下的不同降水扰动梯度,用同色系的透明度/饱和度区分:离基准100%降水越远,透明度越高(比如70%、110%情景透明度设0.6,80%、90%设0.8),不用全用0.5的统一透明度,读者可以直接通过颜色深浅判断扰动幅度
  • 不要全用实线!现在所有序列都是实线,是辨识度低的核心原因之一。把4类要素的线型(-实线/--虚线/-.点划线/:点线)拆开,哪怕颜色接近,线型差异也能快速区分,尤其打印成黑白版本时,线型的辨识度远高于颜色和marker
  • marker不要全数据点铺满!现在每个月的数据点都打marker,线密的时候符号直接糊成块,改成markevery=2隔点显示,或者只在1、4、7、10月季度节点打marker,保留标识作用的同时图面干净很多

二、图面信息减负

  • 20条线硬塞在一个双轴图里信息密度严重过载,优先考虑拆成2行2列的子图,每个子图单独放一类水文要素的5组扰动序列,5条线不需要复杂样式也不会混淆,还能给每个子图单独配坐标轴标注,读数值比双轴方便很多
  • 如果必须保留单图双轴形式,把网格线透明度降到0.1以下,直接关掉次要网格和次刻度——现在主次网格全开,和细线叠在一起进一步加剧杂乱感
  • 图例不要拆成左右两个飘在图外,合并成一个放在图右侧,开启labelcolor='linecolor'让图例文字颜色和对应线条颜色一致,找序列的时候不用来回对照色块

三、代码优化参考

原脚本逐行写20个plot语句重复度极高,还容易出笔误(比如原代码里SWE的字段名前多打了空格,容易读不到数据),可以用循环批量绘图,统一管控样式:

import matplotlib.pyplot as plt

# 预定义要素样式:要素名 -> (颜色, 线型, marker, 挂载坐标轴)
style_config = {
    'P': {'color': '#1f77b4', 'ls': '-', 'marker': 'o', 'ax': 'ax2'},
    'ET': {'color': '#d62728', 'ls': '--', 'marker': 's', 'ax': 'ax2'},
    'Q': {'color': '#2ca02c', 'ls': '-.', 'marker': 'D', 'ax': 'ax2'},
    'SWE': {'color': '#17becf', 'ls': ':', 'marker': 'p', 'ax': 'ax1', 'lw': 1.5}
}
# 预定义扰动情景:情景名, 对应数据集, 透明度
scenario_config = [
    ('70%', bbprec070_vicoutput_monthly, 0.6),
    ('80%', bbprec080_vicoutput_monthly, 0.8),
    ('90%', bbprec090_vicoutput_monthly, 0.8),
    ('100%', bbb_vicoutput_monthly, 1.0),
    ('110%', bbprec110_vicoutput_monthly, 0.6)
]

marksize = 6
fig, ax1 = plt.subplots(figsize=(10, 6), dpi=100)
ax2 = ax1.twinx()
ax_map = {'ax1': ax1, 'ax2': ax2}

lines = []
labels = []
for var in style_config:
    sty = style_config[var]
    target_ax = ax_map[sty['ax']]
    for scen_name, data, alpha in scenario_config:
        # 基准情景单独用黑色加粗突出
        if scen_name == '100%':
            line_color = 'black'
            line_width = 2
            marker_size = 10
        else:
            line_color = sty['color']
            line_width = sty.get('lw', 1.2)
            marker_size = marksize
        # 计算变量值,修正原代码字段名前多余空格的问题
        if var == 'Q':
            y_val = data['OUT_BASEFLOW']['mean'] + data['OUT_RUNOFF']['mean']
        else:
            y_val = data[f'OUT_{var}']['mean']
        line, = target_ax.plot(months, y_val, color=line_color, linestyle=sty['ls'],
                              marker=sty['marker'], alpha=alpha, lw=line_width,
                              markersize=marker_size, markevery=2)
        lines.append(line)
        labels.append(f'{var}({scen_name})')

# 标注设置
ax1.set_ylabel('Hydrologic States (mm)', fontsize=10)
ax2.set_ylabel('Hydrologic Fluxes (mm/day)', fontsize=10)
plt.title("Precipitation Perturbation", fontsize=12, pad=15)
# 仅保留低透明度主网格,关闭次网格减少干扰
ax1.grid(which='major', color='#666666', linestyle='-', alpha=0.1)
ax1.minorticks_off()
# 合并单图例,文字颜色和线条一致
ax1.legend(lines, labels, loc='center left', bbox_to_anchor=(1.12, 0.5),
           fontsize=9, labelcolor='linecolor')
plt.tight_layout()
plt.show()

原脚本输出的效果如下,核心问题为线型单一、marker过密、视觉属性无分层:
原脚本输出的线条杂乱样图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:54:25