如何为matplotlib多个子图添加统一侧边单列4项散点图例
matplotlib 5行2列散点子图统一侧边图例实现方案
修正后完整代码
import matplotlib.pyplot as plt # 提前创建图例手柄(空散点仅用于定义图例样式,不会实际渲染到图中) legend_handles = [ plt.scatter([], [], c='#738A3E', alpha=0.3, marker='^', label='X[12] >75 & X[10] >7000'), plt.scatter([], [], c='#738A3E', alpha=0.3, marker='v', label='X[12] >75 & X[10] ≤7000'), plt.scatter([], [], c='#007CAE', alpha=0.3, marker='^', label='X[12] ≤75 & X[10] >7000'), plt.scatter([], [], c='#007CAE', alpha=0.3, marker='v', label='X[12] ≤75 & X[10] ≤7000') ] # 创建5行2列子图,提前预留图例空间 fig, axes = plt.subplots(nrows=5, ncols=2, figsize=(7, 12)) axes = axes.flatten() # 把子图二维数组转为一维,方便循环遍历 # 逐个绘制子图 for i in range(10): ax = axes[i] ax.set_title(f'Range {i+1}') # 绘制当前子图所有散点 for j in range(X.shape[1]): if X[12,j] > 75 and X[10,j] > 7000: ax.scatter(X[i,j], y[i,j], c='#738A3E', alpha=0.3, marker='^') elif X[12,j] > 75 and X[10,j] <= 7000: ax.scatter(X[i,j], y[i,j], c='#738A3E', alpha=0.3, marker='v') elif X[12,j] <= 75 and X[10,j] > 7000: ax.scatter(X[i,j], y[i,j], c='#007CAE', alpha=0.3, marker='^') else: ax.scatter(X[i,j], y[i,j], c='#007CAE', alpha=0.3, marker='v') # 设置当前子图x轴范围 ax.set_xlim(X[i,:].min(), X[i,:].max()) # 调整子图布局,右侧预留15%宽度放图例 fig.tight_layout(rect=[0, 0, 0.85, 1]) # 添加全局统一图例 fig.legend(handles=legend_handles, loc='upper right', bbox_to_anchor=(1.02, 0.9)) plt.show()
关键实现说明
- 提前生成空散点作为图例手柄:不需要从每个子图提取图例元素,空散点不会在画布上渲染,仅用来定义图例的颜色、标记、透明度样式,顺序和要求的4种样式完全一致。
- 用
subplots批量生成子图对象,避免循环调用subplot导致的子图管理混乱,所有绘图操作直接对应当前子图对象ax。 tight_layout的rect参数限定子图绘制区域为画布左侧85%,剩余空间用来放置侧边图例,不会出现图例被截断的问题。fig.legend是画布级别的全局图例,不属于任何子图,通过bbox_to_anchor调整位置固定在画布右侧,实现所有子图共用一个图例。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

