如何为2D折线图正确添加行内标签与对数颜色刻度并修复多标签问题
问题解决:折线图行内标签重复及对数颜色条实现
问题描述
需要绘制带有行内标签(inline label)和对数颜色条刻度的2D折线图,目前已实现行内标签,但每条折线显示多个标签;同时需要添加对数颜色条。当前效果如下:

原代码
import numpy as np import pandas as pd import matplotlib.pyplot as plt from labellines import labelLines num=np.linspace(2, 10, 15) en=[0.000001,0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000] dis=[] for i in en: for j in num: dist=0.48*j -0.33*np.log10(i) -1.4 r=10**dist dis.append(r) dd=np.array(dis) AA=dd.reshape(10, 15) D=pd.DataFrame(AA) D=np.transpose(D) m=pd.DataFrame(num) fig, ax = plt.subplots(figsize=(12,8)) ax.plot(m[0], D[0], label='$0.000001{J/m^3}$',color='b', lw=2.5, linestyle='solid') labelLines(plt.gca().get_lines(), zorder=2, align=True, fontsize=14) ax.plot(m[0], D[1], label='$0.00001$',color='b', lw=2.5, linestyle='solid', alpha=0.8) labelLines(plt.gca().get_lines(), zorder=2, align=True, fontsize=14) ax.plot(m[0], D[2],label='$0.0001$',color='b', lw=2.5, linestyle='solid', alpha=0.6) labelLines(plt.gca().get_lines(), zorder=2, align=True, fontsize=14) ax.plot(m[0], D[3],label='$0.001$',color='b', lw=2.5, linestyle='solid', alpha=0.4) labelLines(plt.gca().get_lines(), zorder=2, align=True, fontsize=14) ax.plot(m[0], D[4],label='$0.01$',color='b', lw=2.5, linestyle='solid', alpha=0.4) ax.plot(m[0], D[5],label='$0.1$',color='r', lw=2.5, linestyle='solid', alpha=0.2) ax.plot(m[0], D[6], label='$1$',color='r', lw=2.5, linestyle='solid', alpha=0.4) ax.plot(m[0], D[7], label='$10$',color='r', lw=2.5, linestyle='solid', alpha=0.6) ax.plot(m[0], D[8], label='$100$',color='r', lw=2.5, linestyle='solid', alpha=0.8) ax.plot(m[0], D[9], label='$01000$',color='r', lw=2.5, linestyle='solid') #ax.legend(inline=True, fontsize=10) ax.set_yscale('log') ax.set_xlim(2, 10) ax.set_ylim(1, 20000) ax.xaxis.set_tick_params(labelsize=14) ax.yaxis.set_tick_params(labelsize=14) for axis in ['top', 'bottom', 'left', 'right']: ax.spines[axis].set_linewidth(2) plt.show()
解决方案
1. 解决行内标签重复问题
原代码每次绘制一条线后就调用labelLines,该函数会给当前所有已绘制的线条添加标签,导致重复标注。只需在所有线条绘制完成后,调用一次labelLines即可。
2. 实现对数颜色条
使用对数归一化的颜色映射,将en数组的值映射到colormap上,同时创建颜色条展示刻度对应关系。
修改后的完整代码
import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.colors import LogNorm from matplotlib.cm import ScalarMappable from labellines import labelLines # 生成数据 num = np.linspace(2, 10, 15) en = [0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000] dis = [] for i in en: for j in num: dist = 0.48 * j - 0.33 * np.log10(i) - 1.4 r = 10 ** dist dis.append(r) dd = np.array(dis) AA = dd.reshape(10, 15) D = pd.DataFrame(AA).T m = pd.DataFrame(num) # 创建绘图对象 fig, ax = plt.subplots(figsize=(12, 8)) # 配置对数颜色映射 norm = LogNorm(vmin=np.min(en), vmax=np.max(en)) cmap = plt.get_cmap('coolwarm') sm = ScalarMappable(norm=norm, cmap=cmap) sm.set_array([]) # 循环绘制所有折线,简化冗余代码 for idx, e in enumerate(en): color = cmap(norm(e)) alpha = 0.2 + idx * 0.08 if idx < 5 else 0.2 + (9 - idx) * 0.08 line, = ax.plot(m[0], D[idx], label=f'${e} J/m^3$', color=color, lw=2.5, linestyle='solid', alpha=alpha) # 仅调用一次labelLines添加行内标签 labelLines(ax.get_lines(), zorder=2, align=True, fontsize=14) # 添加对数颜色条 cbar = fig.colorbar(sm, ax=ax, orientation='vertical') cbar.set_label('Energy ($J/m^3$)', fontsize=14) cbar.ax.tick_params(labelsize=14) # 设置坐标轴样式 ax.set_yscale('log') ax.set_xlim(2, 10) ax.set_ylim(1, 20000) ax.set_xlabel('num', fontsize=14) ax.set_ylabel('Distance', fontsize=14) ax.xaxis.set_tick_params(labelsize=14) ax.yaxis.set_tick_params(labelsize=14) for axis in ['top', 'bottom', 'left', 'right']: ax.spines[axis].set_linewidth(2) plt.tight_layout() plt.show()
说明
- 循环绘制折线减少了代码冗余,通过对数归一化colormap实现颜色与
en值的对应。 - 颜色条使用对数刻度,匹配数据的对数特性,直观展示能量值变化。
- 仅调用一次
labelLines,确保每条折线只显示一个行内标签。
内容的提问来源于stack exchange,提问作者Adnan
相关产品推荐
相关产品推荐

