如何在matplotlib的ax.legend中为每个图例标签添加换行符
问题描述
想要修改所绘堆叠条形图的图例,在每个图例标签后添加换行符,避免长标签挤压显示空间。现有两个不可修改的字典,分别存储绘图数值、图例标签与对应颜色的映射关系。
原有实现代码如下:
import numpy as np import matplotlib.pyplot as plt text_color = "white" dico_valeur = {'A': [5, 2, 2, 6, 2, 0, 0, 1], 'B': [6, 5, 0, 0, 0, 0, 1, 0], 'C': [6, 22, 2, 5, 3, 1, 2, 1], 'D': [13, 3, 2, 1, 3, 0, 0, 0], 'E': [14, 6, 12, 1, 4, 2, 2, 0], 'F': [3, 3, 0, 0, 0, 1, 0, 0], 'G': [6, 11, 3, 6, 1, 0, 1, 1], 'H': [3, 2, 2, 1, 3, 0, 0, 1], 'I': [2, 0, 0, 0, 0, 1, 0, 0], 'J': [6, 10, 1, 5, 3, 1, 0, 0], 'K': [2, 4, 1, 1, 0, 0, 0, 0], 'L': [1, 0, 0, 0, 0, 0, 0, 0], 'M': [1, 0, 0, 0, 0, 0, 0, 0], 'N': [10, 7, 2, 3, 3, 3, 0, 0]} dico_couleur = {"a very very very very very very very very very very very very very very very very very very very very long legend": 'C0', 'another very very very very very very very very very very very very very very very very very very very very long legend, démarreur,…': 'C1', 'a very very very very very very very very very very very very very very very very very long legend': 'C2', "a very very very very very very very very very very very very very very very vry very very very long legend": 'C3', 'a very very very very very veryy very very very very very very long legend': 'C4', 'a very very very very very very very very very very very very very very very very very very very very long legend': 'C5', "a very very very very very very very very very very very very very very very very very very long legend": 'C6', 'a very very very very very very very very veryery very very very very very very very very long legend': 'C7'} category_names = [] for i in dico_couleur: category_names.append(i) results = dico_valeur labels = list(results.keys()) data = np.array(list(results.values())) data_cum = data.cumsum(axis=1) category_colors = list(dico_couleur.values()) fig, ax = plt.subplots(figsize=(15, 7)) ax.invert_yaxis() ax.xaxis.set_visible(False) ax.set_xlim(0, np.sum(data, axis=1).max()) for i, (colname, color) in enumerate(zip(category_names, category_colors)): widths = data[:, i] starts = data_cum[:, i] - widths ax.barh(labels, widths, left=starts, height=0.5, label=colname, color=color) xcenters = starts + widths / 2 for y, (x, c) in enumerate(zip(xcenters, widths)): if c != 0: ax.text(x, y, str(int(c)), ha='center', va='center', color=text_color) ax.legend(ncol=len(category_names), bbox_to_anchor=(1, 0, 0.5, 1), loc='lower left', fontsize='small') plt.show()
当前问题:运行代码后长图例标签横向排列过于拥挤,找不到为每个标签添加换行符的实现方法。
解决思路
由于无需修改原始字典,仅需要在读取图例标签生成category_names时对字符串做加工即可,不需要改动原始数据:
- 方案1:直接为每个标签末尾添加换行符
把原有生成category_names的逻辑替换为如下写法即可,每个标签末尾会自动追加换行符,撑开纵向显示空间:
category_names = [label + "\n" for label in dico_couleur.keys()]
- 方案2:自动按字数折行长标签(优化显示效果)
如果标签过长,仅加末尾换行还是会占用过多横向宽度,可以自定义折行逻辑,按指定字数拆分标签插入换行符:
def add_line_break(text, max_len=15): # 按指定最大长度拆分文本插入换行 res = [] for i in range(0, len(text), max_len): res.append(text[i:i+max_len]) return "\n".join(res) category_names = [add_line_break(label) for label in dico_couleur.keys()]
额外优化建议:原有图例参数ncol=len(category_names)强制所有图例横向排列,本身就会导致长标签拥挤,可根据调整后的标签长度适当减小ncol数值,比如设为1或2,显示效果会更合理:
ax.legend(ncol=2, bbox_to_anchor=(1, 0, 0.5, 1), loc='lower left', fontsize='small')
内容的提问来源于stack exchange,提问作者mathieu e.
相关产品推荐
相关产品推荐

