Python Matplotlib饼图标签重叠如何解决?需保留扇区引线且不使用图例
解决方案
目前Python生态下有两种成熟方案可以实现类似Excel的标签最佳适配效果,完全解决饼图扇区标签重叠问题,无需使用图例:
方案1:使用adjustText自动调整标签(推荐,等效Excel best fit功能)
这个方案依赖专门处理matplotlib文本重叠的第三方库adjustText,可以自动偏移重叠的标签位置,同时保留指向对应扇区的连线,不需要手动计算布局。
- 先安装依赖:
pip install adjustText - 调整后的代码如下:
import matplotlib.pyplot as plt import numpy as np from adjustText import adjust_text bbox_props = dict(boxstyle='square,pad=0.3', fc='w', ec='k', lw=0.72) kw = dict( xycoords='data', textcoords='data', arrowprops=dict(arrowstyle='-', shrinkA=5, shrinkB=5), zorder=0, va='center', bbox=bbox_props ) # 适当调大画布尺寸,避免边缘标签被截断 fig1, ax1 = plt.subplots(figsize=(8, 8)) labels = ["first\n1.8%", "second\n1.3%", "third\n10.5%", "fourth\n13.8%", "fifth\n7.8%", "sixth\n6.7%", "seventh\n9.9%", "eighth\n12.2%", "ninth\n12.7%", "tenth\n10.9%", "eleventh\n7.6%", "twelfth\n4.8%"] values = [1.8, 1.3, 10.5, 13.8, 7.8, 6.7, 9.9, 12.2, 12.7, 10.9, 7.6, 4.8] wedges, _ = ax1.pie(values, explode=[0.01]*12, labeldistance=1.2, startangle=90) annotations = [] for i, p in enumerate(wedges): ang = (p.theta2 - p.theta1)/2. + p.theta1 y = np.sin(np.deg2rad(ang)) x = np.cos(np.deg2rad(ang)) horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))] connectionstyle = f"angle,angleA=0,angleB={ang}" kw["arrowprops"].update({"connectionstyle": connectionstyle}) ann = ax1.annotate( labels[i], xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y), horizontalalignment=horizontalalignment, **kw ) annotations.append(ann) # 自动调整标签位置,expand_points参数控制标签间距,数值越大间距越宽 adjust_text(annotations, expand_points=(2, 2), arrowprops=dict(arrowstyle='-', lw=0.7)) plt.show()
如果调整后仍有少量重叠,只需要调大expand_points的参数值,或者进一步放大画布尺寸即可。
方案2:无额外依赖,手动均匀排布标签
如果不想安装第三方库,可以直接将标签的文本位置按数量均匀分布在饼图外侧圆周上,再将箭头指向对应扇区的中点,适合标签数量固定的场景。核心逻辑如下:
- 标签总数为n时,每个标签的角度间隔为
360/n度 - 按间隔计算每个标签的x、y坐标,放置在半径1.4~1.6的圆周上
- 箭头从该坐标指向对应扇区的中点即可
内容的提问来源于stack exchange,提问作者Cole
相关产品推荐
相关产品推荐

