如何实现Matplotlib饼图图例自动避开其他元素的通用方案?
批量生成饼图自动放置图例的解决方案
针对批量生成饼图时图例与百分比标签重叠的问题,有几种可靠的自动处理方案:
1. 使用matplotlib内置的自动最优位置
直接将图例的loc参数设为'best',matplotlib会自动评估图表内的空白区域,选择避开所有元素的位置放置图例,无需手动指定固定位置。
示例代码:
import pandas as pd import matplotlib.pyplot as plt fake_df = pd.DataFrame([71, 15, 14], columns=['category'], index=['Category Name 1', 'Category Name 2', 'Category Name 3']) # 绘制饼图 ax = fake_df.plot.pie(y='category', labels=None, autopct="%1.0f%%", pctdistance=1.2, ) # 自动选择最优图例位置 plt.legend(fake_df.index, loc='best') plt.show()
2. 将图例放在饼图外部(完全避免重叠)
如果希望彻底消除重叠风险,可将图例放置在饼图外侧,通过bbox_to_anchor参数指定位置,同时调整图表间距防止图例被截断。这种方法适用于所有数据情况,无需判断内部空间。
示例代码:
import pandas as pd import matplotlib.pyplot as plt fake_df = pd.DataFrame([70, 15, 15], columns=['category'], index=['Category Name 1', 'Category Name 2', 'Category Name 3']) ax = fake_df.plot.pie(y='category', labels=None, autopct="%1.0f%%", pctdistance=1.2, ) # 将图例放在饼图右侧外部 plt.legend(fake_df.index, loc='upper left', bbox_to_anchor=(1.02, 1)) # 调整右侧留白,适配图例宽度 plt.subplots_adjust(right=0.7) plt.show()
3. 自定义空白区域判断逻辑(精准控制内部位置)
如果必须将图例放在饼图内部,可通过代码提取百分比标签的位置,计算出空白最多的角落,再指定图例位置。这种方法适合对图例位置有严格要求的场景。
示例代码:
import pandas as pd import matplotlib.pyplot as plt import math def find_optimal_inner_loc(ax): # 获取所有百分比标签的坐标 text_coords = [text.get_position() for text in ax.texts if text.get_text().endswith('%')] # 定义四个候选角落的参考坐标(以饼图中心(0,0)为基准) candidate_locs = { 'upper left': (-1, 1), 'upper right': (1, 1), 'lower left': (-1, -1), 'lower right': (1, -1) } best_loc = 'upper right' max_min_distance = -1 # 计算每个候选位置与所有标签的最小距离,选最小距离最大的位置 for loc, (ref_x, ref_y) in candidate_locs.items(): min_dist = min(math.hypot(x - ref_x, y - ref_y) for x, y in text_coords) if min_dist > max_min_distance: max_min_distance = min_dist best_loc = loc return best_loc fake_df = pd.DataFrame([71, 15, 14], columns=['category'], index=['Category Name 1', 'Category Name 2', 'Category Name 3']) ax = fake_df.plot.pie(y='category', labels=None, autopct="%1.0f%%", pctdistance=1.2, ) # 调用自定义函数获取最优位置 optimal_loc = find_optimal_inner_loc(ax) plt.legend(fake_df.index, loc=optimal_loc) plt.show()
内容的提问来源于stack exchange,提问作者Ben P
相关产品推荐
相关产品推荐

