Matplotlib子图散点图图例被覆盖问题求解
子图统一图例生成方案
通过for循环批量生成子图散点图时,若在循环内每次调用plt.legend(),图例会被后续子图覆盖,最终仅显示最后一个子图的图例。需要生成一个涵盖所有年份(2019、2020、2021、2022)的全局统一图例。
解决方案
核心思路是提前生成全局统一的图例元素,循环内仅绘制散点,最后在整个画布上添加一次图例,避免重复覆盖。
修改后的代码:
import pandas as pd import matplotlib.pyplot as plt import matplotlib.patches df = pd.read_excel(path) spp = df.SPP.unique() # 提前获取所有年份的唯一值,生成全局统一的图例元素 all_years = df['Year'].unique() all_years.sort() # 可选:按年份排序保证图例顺序一致 handles = [matplotlib.patches.Patch(color=plt.cm.tab10(i), label=c) for i, c in enumerate(all_years)] fig, axs = plt.subplots(nrows=8, ncols=4, figsize=(14, 14)) for spp_i, ax in zip(spp, axs.flat): df_1 = df[df['SPP'] == spp_i] x = df_1['Length_mm'] y = df_1['Weight_g'] # 基于全局年份的因子化,确保颜色与图例对应 levels = df_1['Year'].map(dict(zip(all_years, range(len(all_years))))) colors = [plt.cm.tab10(i) for i in levels] ax.scatter(x, y, c=colors) # 移除循环内的plt.legend()调用 # 在整个画布上添加全局图例,可调整位置参数 fig.legend(handles=handles, loc='upper right', bbox_to_anchor=(1.1, 1), title='Year') plt.savefig('Test.png', bbox_inches='tight', pad_inches=0.1, dpi=600)
修改说明
- 提前提取所有年份并生成统一的图例
handles,确保所有子图的颜色与图例一一对应。 - 循环内删除
plt.legend()调用,避免每次覆盖图例。 - 使用
fig.legend()替代plt.legend(),将图例绑定到整个画布而非单个子图,通过bbox_to_anchor参数可灵活调整图例位置,避免遮挡子图内容。 - 对年份进行排序(可选操作),保证图例中年份的顺序符合逻辑。
内容的提问来源于stack exchange,提问作者Orla Osborne
相关产品推荐
相关产品推荐

