Matplotlib绘制三子图折线时如何为每条折线设置差异化颜色
问题背景
你持有名为plot_data的DataFrame,共约998行、23列,原代码逐行遍历数据,按Level字段值拆分绘制3个纵向排列的子图,同一子图内所有折线使用统一配色,需要调整代码实现同子图内折线具备足够区分度,线条重叠时也可直观分辨差异。
原实现代码如下:
fig=plt.figure() for i in range(0,plot_data.shape[0]): if (plot_data["Level"].iloc[i] == "Low"): plt.subplot(311) plt.plot(plot_data.drop(columns =["Level"]).iloc[i],"green",linewidth=0.6) plt.xticks([]) elif (plot_data["Level"].iloc[i] == "Medium"): plt.subplot(312) plt.plot(plot_data.drop(columns =["Level"]).iloc[i],"yellow",linewidth=0.6) plt.xticks([]) else : plt.subplot(313) plt.plot(plot_data.drop(columns =["Level"]).iloc[i],"red",linewidth=0.6) plt.xticks([]) plt.show()
实现方案
原代码逐行循环重复调用plt.subplot效率较低,建议先按Level字段分组筛选数据,再搭配高区分度配色、透明度设置解决重叠辨识度问题,提供两种可直接复用的实现:
方案1:高区分度多色板(无固定色彩语义)
适合不需要保留原绿/黄/红分类色彩逻辑的场景,使用matplotlib内置的高区分度离散色板循环取色,搭配透明度设置让重叠区域通过颜色叠加自然显示密度差异:
import matplotlib.pyplot as plt # 提前初始化3个子图,避免循环中重复创建子图对象 fig, (ax_low, ax_medium, ax_high) = plt.subplots(3, 1, figsize=(10, 8)) axes_map = {"Low": ax_low, "Medium": ax_medium, "High": ax_high} # 加载20种专门校准过的高区分度色值,循环使用 color_palette = plt.cm.tab20.colors color_cursor = 0 for level, ax in axes_map.items(): # 一次性筛选当前分类的所有数据,无需逐行判断 group_data = plot_data[plot_data["Level"] == level].drop(columns=["Level"]) for _, row in group_data.iterrows(): line_color = color_palette[color_cursor % len(color_palette)] ax.plot(row.values, color=line_color, linewidth=0.6, alpha=0.7) color_cursor += 1 ax.set_xticks([]) ax.set_ylabel(level) plt.tight_layout() plt.show()
方案2:同色系渐变(保留原分类色彩语义)
如果需要保留Low=绿色、Medium=黄色、High=红色的原有视觉逻辑,可以为每个分类单独生成同色系渐变颜色,同一子图内线条通过明暗、饱和度差异区分,既保留分类辨识度,又能分辨单条折线:
import matplotlib.pyplot as plt from matplotlib.colors import to_rgba fig, (ax_low, ax_medium, ax_high) = plt.subplots(3, 1, figsize=(10,8)) level_config = { "Low": {"ax": ax_low, "base_color": "#2ca02c"}, "Medium": {"ax": ax_medium, "base_color": "#ffcc00"}, "High": {"ax": ax_high, "base_color": "#d62728"} } for level, config in level_config.items(): ax = config["ax"] base_rgb = to_rgba(config["base_color"])[:3] group_data = plot_data[plot_data["Level"] == level].drop(columns=["Level"]) line_total = len(group_data) for row_idx, (_, row) in enumerate(group_data.iterrows()): # 生成从浅到深的同色系色值 light_factor = 0.3 + 0.7 * (row_idx / max(line_total-1, 1)) line_color = tuple([channel * light_factor for channel in base_rgb] + [0.6]) ax.plot(row.values, color=line_color, linewidth=0.6) ax.set_xticks([]) ax.set_ylabel(level) plt.tight_layout() plt.show()
优化提示:如果单组折线数量超过30条,仅靠颜色区分会存在压力,可以额外给线条搭配不同线型(实线、虚线、点线交替)、或者加极微小的纵向随机偏移,进一步提升重叠场景下的辨识度。
内容的提问来源于stack exchange,提问作者notRelevant
相关产品推荐
相关产品推荐

