请求修复Matplotlib堆叠条形图图例:每个灾害类型仅显示一次
修复堆叠条形图重复图例问题
我需要帮助修复图表图例。在某一可视化中图例显示正常,但当前的堆叠条形图中,每个灾害类型对应多个颜色,图例重复显示。我希望每个灾害类型在图例中仅出现一次。已尝试使用colormap和颜色列表,但结果相同,期望实现图例中每个灾害类型仅显示一次的效果。
用户提供的原始代码:
continent_filter = widgets.SelectMultiple( options=['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'], value=[pivot_df.columns.get_level_values(0).unique()[0]], description='Continent', disabled=False ) colors = ['red', 'green', 'blue', 'orange', 'purple', 'yellow', 'cyan', 'magenta', 'lime', 'pink', 'teal', 'brown', 'gray', 'olive', 'navy'] def update_plot(continent): ax = pivot_df[continent].plot(kind="bar", stacked=True, color= colors, figsize=(15, 6)) plt.xlabel('Year') plt.ylabel('Number of Events') plt.title('Number of Events by Year, Continent, and Disaster Type') plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') xtick_labels = [label.get_text().split('-')[0] for label in ax.get_xticklabels()] ax.set_xticklabels(xtick_labels) plt.xticks(rotation=45) plt.show() widgets.interact(update_plot, continent=continent_filter)
解决方案
问题根源在于pivot_df的列是多级索引(大陆+灾害类型),调用plot()时会为每个子列生成图例项,导致同一灾害类型重复出现。以下是修复步骤:
1. 创建灾害类型-颜色映射
确保同一灾害类型始终对应相同颜色,避免视觉混乱:
# 获取所有唯一的灾害类型 disaster_types = pivot_df.columns.get_level_values(1).unique() # 创建灾害类型与颜色的映射字典 color_map = dict(zip(disaster_types, colors[:len(disaster_types)]))
2. 修改绘图函数,去重图例
在绘图后提取图例的手柄(handle)和标签(label),过滤重复的灾害类型,仅保留每个类型的第一个实例:
修改后的完整代码:
continent_filter = widgets.SelectMultiple( options=['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'], value=[pivot_df.columns.get_level_values(0).unique()[0]], description='Continent', disabled=False ) colors = ['red', 'green', 'blue', 'orange', 'purple', 'yellow', 'cyan', 'magenta', 'lime', 'pink', 'teal', 'brown', 'gray', 'olive', 'navy'] # 预创建灾害类型-颜色映射 disaster_types = pivot_df.columns.get_level_values(1).unique() color_map = dict(zip(disaster_types, colors[:len(disaster_types)])) def update_plot(continent): ax = pivot_df[continent].plot(kind="bar", stacked=True, color=color_map, figsize=(15, 6)) plt.xlabel('Year') plt.ylabel('Number of Events') plt.title('Number of Events by Year, Continent, and Disaster Type') # 提取图例并去重 handles, labels = ax.get_legend_handles_labels() seen = set() new_handles = [] new_labels = [] for h, l in zip(handles, labels): # 从多级索引标签中提取灾害类型(l是元组,格式为(大陆, 灾害类型)) disaster_type = l[1] if disaster_type not in seen: seen.add(disaster_type) new_handles.append(h) new_labels.append(disaster_type) # 使用去重后的图例 plt.legend(new_handles, new_labels, bbox_to_anchor=(1.05, 1), loc='upper left') xtick_labels = [label.get_text().split('-')[0] for label in ax.get_xticklabels()] ax.set_xticklabels(xtick_labels) plt.xticks(rotation=45) plt.show() widgets.interact(update_plot, continent=continent_filter)
说明
- 颜色映射
color_map确保同一灾害类型在不同大陆的图表中颜色一致; - 图例去重逻辑通过遍历所有图例项,记录已出现的灾害类型,仅保留首次出现的手柄和标签,最终生成唯一的灾害类型图例。
内容的提问来源于stack exchange,提问作者nchrista
相关产品推荐
相关产品推荐

