Matplotlib绘制斜率图如何不修改yticks避免文本重叠并加百分比标注
解决方案
问题1:解决左右文本标注重叠(不修改yticks)
按如下调整即可解决重叠问题:
- 修正原有代码
ylim设置错误,将范围匹配为yticks对应的3000~46000,避免高值数据标签被压缩重叠 - 扩大x轴范围至
(-0.2,4.2),给左右两侧标注预留更多展示空间 - 适当降低标注字号从14调整为12,减少单标签占用面积
若仍有轻微重叠,可对相邻的y值接近的标签手动添加1000~2000的y轴偏移量错开位置。
问题2:添加摆动百分比标注到线段上方
将df2转为字典做映射匹配对应政党,在绘制每根线段时,取线段中点坐标添加百分比标注即可,可搭配白色半透明背景框提升可读性,颜色和线段涨跌色保持一致。
完整可运行修改后代码
import matplotlib.pyplot as plt import matplotlib.lines as mlines import numpy as np import pandas as pd # 原始数据 df={'continent': {0: 'BJP', 1: 'INC', 2: 'BSP'}, '1952': {0: 10650, 1: 30047, 2: 36828}, '1957': {0: 42369, 1: 4482, 2: 4069}} df = pd.DataFrame(df) # 摆动数据 df2={'continent': {0: 'BJP', 1: 'INC', 2: 'BSP'}, 'Swing': {0: 31.9, 1: 9.9, 2: -42.5}} df2 = pd.DataFrame(df2) swing_map = df2.set_index('continent')['Swing'].to_dict() klass = ['red' if (y1-y2) < 0 else 'green' for y1, y2 in zip(df['1952'], df['1957'])] def newline(p1, p2, color='black'): ax = plt.gca() l = mlines.Line2D([p1[0],p2[0]], [p1[1],p2[1]], color='red' if p1[1]-p2[1] > 0 else 'green', marker='o', markersize=6) ax.add_line(l) return l fig, ax = plt.subplots(1,1,figsize=(7,7), dpi= 80) # Vertical Lines ax.vlines(x=1, ymin=3500, ymax=45000, color='black', alpha=0.7, linewidth=1, linestyles='dotted') ax.vlines(x=3, ymin=3500, ymax=45000, color='black', alpha=0.7, linewidth=1, linestyles='dotted') # Points ax.scatter(y=df['1952'], x=np.repeat(1, df.shape[0]), s=10, color='black', alpha=0.7) ax.scatter(y=df['1957'], x=np.repeat(3, df.shape[0]), s=10, color='black', alpha=0.7) # Line Segments and Annotation for p1, p2, c in zip(df['1952'], df['1957'], df['continent']): newline([1,p1], [3,p2]) # 左右标注调整字号 ax.text(1-0.05, p1, c + ', ' + str(round(p1)), horizontalalignment='right', verticalalignment='center', fontdict={'size':12}) ax.text(3+0.05, p2, c + ', ' + str(round(p2)), horizontalalignment='left', verticalalignment='center', fontdict={'size':12}) # 添加摆动百分比标注 swing_val = swing_map[c] mid_x = 2 mid_y = (p1 + p2) / 2 text_color = 'green' if swing_val > 0 else 'red' ax.text(mid_x, mid_y + 1500, f'{swing_val}%', ha='center', va='center', color=text_color, fontsize=13, weight='bold', bbox=dict(facecolor='white', alpha=0.8, edgecolor='none', pad=2)) # 'Before' and 'After' Annotations ax.text(1-0.05, 23000, 'BEFORE', horizontalalignment='right', verticalalignment='center', fontdict={'size':18, 'weight':700}) ax.text(3+0.05, 23000, 'AFTER', horizontalalignment='left', verticalalignment='center', fontdict={'size':18, 'weight':700}) # Decoration ax.set_title("Vote Swing", fontdict={'size':22}) # 调整xlim和ylim ax.set(xlim=(-0.2,4.2), ylim=(3000, 46000), ylabel='Votes') ax.set_xticks([1,3]) ax.set_xticklabels(["2012", "2017"]) plt.yticks(np.arange(3500, 45000, 2000), fontsize=12) # Lighten borders plt.gca().spines["top"].set_alpha(.0) plt.gca().spines["bottom"].set_alpha(.0) plt.gca().spines["right"].set_alpha(.0) plt.gca().spines["left"].set_alpha(.0) plt.show()
内容的提问来源于stack exchange,提问作者DSR
相关产品推荐
相关产品推荐

