如何合并Matplotlib柱状图图例中的重复标签?
解决Matplotlib图例重复显示问题
问题背景
从PostgreSQL获取包含(ID, Object, Percentage, Color)的数据集后,使用Matplotlib绘制柱状图时,图例中相同颜色(如Red)的标签重复出现。
测试数据
result = [ (1, 'Apple', 10, 'Red'), (2, 'Blueberry', 40, 'Blue'), (3, 'Cherry', 94, 'Red'), (4, 'Orange', 68, 'Orange') ]
原始绘图代码
import pandas as pd from matplotlib import pyplot as plt import psycopg2 conn = psycopg2.connect( host="localhost", port="5432", database="db", user="user", password="123") cur = conn.cursor() cur.callproc("test_stored_procedure") result = cur.fetchall() cur.close() conn.close() print(result) result = pd.DataFrame(result, columns=['ID', 'Object', 'Percentage', 'Color']) fruits = result.Object counts = result.Percentage labels = result.Color s = 'tab:' bar_colors = [s + x for x in result.Color] fig, ax = plt.subplots() for x, y, c, lb in zip(fruits, counts, bar_colors, labels): ax.bar(x, y, color=c, label=lb) ax.set_ylabel('fruit supply') ax.set_title('Fruit supply by kind and color') ax.legend(title='Fruit color', loc='upper left') plt.show()
问题现象
图表图例中,Red标签重复显示两次,不符合“每种颜色仅显示一次图例”的需求。
原因分析
原始代码在循环绘制每个柱状条时,都会为当前条目的颜色添加一次label参数。当多个条目颜色相同时,就会生成多个相同的图例标签,最终导致重复显示。
解决方案
方法1:手动去重图例条目
提取图例的手柄(handles)和标签(labels),利用字典的唯一性去重后重新生成图例:
# 保留原始绘图逻辑,仅修改图例部分 fig, ax = plt.subplots() for x, y, c, lb in zip(fruits, counts, bar_colors, labels): ax.bar(x, y, color=c, label=lb) ax.set_ylabel('fruit supply') ax.set_title('Fruit supply by kind and color') # 新增去重逻辑 handles, labels = ax.get_legend_handles_labels() # 字典自动去重,保留最后一个出现的条目(需保留第一个可反转后再转回) unique_legend = dict(zip(labels, handles)) ax.legend(unique_legend.values(), unique_legend.keys(), title='Fruit color', loc='upper left') plt.show()
方法2:按颜色分组绘制
利用Pandas的groupby按颜色分组,每组仅添加一次标签,从根源避免重复:
result = pd.DataFrame(result, columns=['ID', 'Object', 'Percentage', 'Color']) fig, ax = plt.subplots() # 按颜色分组绘制,每组仅添加一次标签 for color, group in result.groupby('Color'): ax.bar(group['Object'], group['Percentage'], color=f'tab:{color}', label=color) ax.set_ylabel('fruit supply') ax.set_title('Fruit supply by kind and color') ax.legend(title='Fruit color', loc='upper left') plt.show()
方法3:循环时仅首次添加标签
在循环过程中记录已添加过的颜色,仅为每种颜色的第一个柱状条添加标签:
result = pd.DataFrame(result, columns=['ID', 'Object', 'Percentage', 'Color']) fruits = result.Object counts = result.Percentage labels = result.Color s = 'tab:' bar_colors = [s + x for x in result.Color] fig, ax = plt.subplots() seen_colors = set() for x, y, c, lb in zip(fruits, counts, bar_colors, labels): # 仅首次遇到该颜色时设置label,后续条目不设置 current_label = lb if lb not in seen_colors else None ax.bar(x, y, color=c, label=current_label) seen_colors.add(lb) ax.set_ylabel('fruit supply') ax.set_title('Fruit supply by kind and color') ax.legend(title='Fruit color', loc='upper left') plt.show()
内容的提问来源于stack exchange,提问作者muted_buddy
相关产品推荐
相关产品推荐

