Matplotlib绘图中图例与线条/符号匹配错误问题求助
Matplotlib图例与绘图元素不匹配的解决方法
问题说明
使用Matplotlib绘制包含线条、菱形/三角形标记的双图时,图例出现以下异常:
- 最先绘制的线条和标记未在图例中显示
- 图例末尾存在重复符号
- 图例样式与实际绘图元素无法正确对应
原代码问题分析
原代码仅给最后一个plot调用添加了label参数,其余绘图元素均未指定label。当直接向plt.legend()传入labels列表时,Matplotlib只会收集带有label的绘图元素,导致标签列表和实际元素数量不匹配,最终出现图例混乱。
解决方案
方法1:为每个图例条目添加对应label
修改所有需要在图例中显示的plot调用,添加匹配的label参数,让Matplotlib自动关联元素与标签:
import numpy as np from scipy.integrate import odeint from scipy.io import loadmat import matplotlib.pyplot as plt fig = plt.figure(figsize=(17, 7)) fig.subplots_adjust(wspace=.35) ax1 = fig.add_subplot(1, 2, 1) # 为模型线条和数据标记添加对应label ax1.plot(t, np.sum(x[:, [5, 6, 7, 14, 16, 18]], axis=1), 'k', linewidth=line_wdth, label='Replicated viral DNA - Model') # Total viral DNA ax1.plot(np.concatenate([dataTotalDNA[:, 0], dataTotalDNA[:, 0], dataTotalDNA[:, 0]]), np.concatenate([dataTotalDNA[:, 1], dataTotalDNA[:, 2], dataTotalDNA[:, 3]]), 'k^', linewidth=line_wdth, markersize=10, markerfacecolor='none', markeredgewidth=2, markeredgecolor='black', label='Replicated viral DNA - Data') plt.xlabel(r'Time (hpt)', fontsize=ftsz) if mode == 'manuscript': ax1.set_ylabel('AAV DNA copies/mL', fontsize=ftsz) if mode == 'presentation': ax1.set_title('AAV DNA copies/mL', fontsize=ftsz) ax1.set_xticks(range(0, 61, 12)) ax1.tick_params(labelsize=ftsz) # 封装DNA的模型线条和数据标记添加label ax1.plot(t, np.sum(x[:, [16, 18]], axis=1), 'r', linewidth=line_wdth, label='Full virion - Model') # Encapsidated DNA ax1.plot(np.concatenate([dataFullCap[:, 0], dataFullCap[:, 0], dataFullCap[:, 0]]), np.concatenate([dataFullCap[:, 1], dataFullCap[:, 2], dataFullCap[:, 3]]), 'rs', linewidth=line_wdth, markersize=10, markerfacecolor='none', markeredgewidth=2, markeredgecolor='red', label='Full virion - Data') ax1.plot([6, 6], [0, 7e9], 'k--', linewidth=1.2) # Media exchange(无需图例) ax1.set_ylim([0, 7e9]) ylim1 = ax1.get_ylim() xlim1 = ax1.get_xlim() if mode == 'manuscript': plt.text(-0.15 * xlim1[1], 1.01 * ylim1[1], r'A', fontsize=26, fontweight='bold') # Total capsid vs full capsid ax2 = fig.add_subplot(1, 2, 2) # 总衣壳的模型线条和数据标记添加label ax2.plot(t, np.sum(x[:, [15, 16, 17, 18]], axis=1), 'b', linewidth=line_wdth, label='Total capsid - Model') # Total capsid ax2.plot(dataCap[:, 0], dataCap[:, 1], 'bd', markersize=10, linewidth=line_wdth, markerfacecolor='none', markeredgewidth=2, markeredgecolor='blue', label='Total capsid - Data') # 重复的Full capsid绘图无需再次添加label ax2.plot(t, np.sum(x[:, [16, 18]], axis=1), 'r', linewidth=line_wdth) # Full capsid ax2.plot([dataFullCap[:, 0], dataFullCap[:, 0], dataFullCap[:, 0]], [dataFullCap[:, 1], dataFullCap[:, 2], dataFullCap[:, 3]], 'rs', linewidth=line_wdth, markersize=10, markerfacecolor='none', markeredgewidth=2, markeredgecolor='red') ax2.plot([6, 6], [0, 6e9], 'k--', linewidth=1.2) # Media exchange(无需图例) ax2.set_yscale('log') ax2.set_ylim([1e8, 1e11]) ax2.set_xlim([0, 60]) ax2.set_xticks(range(0, 61, 12)) ax2.tick_params(labelsize=ftsz) ax2.set_xlabel('Time (hpt)', fontsize=ftsz) if mode == 'manuscript': ax2.set_ylabel('Capsids/mL (All Compartments)', fontsize=ftsz) elif mode == 'presentation': ax2.set_title('Capsids/mL (All Compartments)', fontsize=ftsz) ylim2 = ax2.get_ylim() xlim2 = ax2.get_xlim() if mode == 'manuscript': ax2.text(-0.22 * xlim2[1], 1.05 * ylim2[1], r'B', fontsize=26, fontweight='bold') # 直接调用legend,无需手动传入labels列表 leg2 = plt.legend(loc='upper left', bbox_to_anchor=(-0.93, 1.127), ncol=3, fontsize=13) plt.show()
方法2:手动构建自定义图例元素
如果不想修改原有绘图代码,可以通过Line2D手动创建图例条目,确保样式与绘图元素完全一致:
import numpy as np from scipy.integrate import odeint from scipy.io import loadmat import matplotlib.pyplot as plt from matplotlib.lines import Line2D # 原绘图代码保持不变,仅替换图例部分 # ...(此处省略原绘图代码) # 手动定义每个图例条目对应的样式 custom_legend = [ Line2D([0], [0], marker='^', color='k', linestyle='', markerfacecolor='none', markeredgewidth=2, markersize=10), Line2D([0], [0], color='k', linewidth=line_wdth), Line2D([0], [0], marker='s', color='r', linestyle='', markerfacecolor='none', markeredgewidth=2, markersize=10), Line2D([0], [0], color='r', linewidth=line_wdth), Line2D([0], [0], marker='d', color='b', linestyle='', markerfacecolor='none', markeredgewidth=2, markersize=10), Line2D([0], [0], color='b', linewidth=line_wdth), ] labels = ['Replicated viral DNA - Data', 'Replicated viral DNA - Model', 'Full virion - Data', 'Full virion - Model', 'Total capsid - Data', 'Total capsid - Model'] # 传入自定义图例元素和标签 leg2 = plt.legend(handles=custom_legend, labels=labels, loc='upper left', bbox_to_anchor=(-0.93, 1.127), ncol=3, fontsize=13) plt.show()
内容的提问来源于stack exchange,提问作者Aparna Roy
相关产品推荐
相关产品推荐

