Seaborn散点气泡图如何拆分颜色与大小两类图例分置不同位置
双面板气泡散点图拆分图例实现方案
要实现拆分图例的需求,核心逻辑是关闭sns.scatterplot默认生成的合并图例,手动提取两类映射的图例元素分别添加,具体实现如下:
首先是基于tips数据集的可运行验证示例:
import seaborn as sns import matplotlib.pyplot as plt tips = sns.load_dataset('tips') tips["percentage"] = tips["tip"] / tips["total_bill"] * 100 # 绘图时关闭自动生成的合并图例 ax = sns.scatterplot(data=tips, x="total_bill", y="tip", hue="time", size="percentage", sizes=(100, 1500), legend=False) # 提取颜色分类(对应你场景里的大洲)的图例元素,tips中time分类共2类所以取前2个 hue_handles, hue_labels = ax.get_legend_handles_labels() hue_handles = hue_handles[:2] hue_labels = hue_labels[:2] # 提取气泡大小(对应你场景里的死亡率)的图例元素,从分类之后的位置开始取 size_handles, size_labels = ax.get_legend_handles_labels() size_handles = size_handles[2:] size_labels = size_labels[2:] # 添加颜色分类图例到右上角,markerscale=1保证气泡大小不被缩放 leg1 = ax.legend(hue_handles, hue_labels, loc="upper right", title="用餐时段", markerscale=1) # 把第一个图例添加到轴上,避免被后续图例覆盖 ax.add_artist(leg1) # 添加气泡大小图例到右下角 ax.legend(size_handles, size_labels, loc="lower right", title="小费占比(%)", markerscale=1) plt.show()
适配你双面板场景的修改后代码:
import seaborn as sns import matplotlib.pyplot as plt fig, (ax1, ax2) = plt.subplots(2,1, figsize=(15,17), sharex=True) # 绘图时关闭默认图例 sns.scatterplot(data=merged, x="gdp_per_capita", y="life_expectancy", size="death_rate", hue="continent", cmap="Accent", sizes=(100, 1500), ax=ax1, legend=False) sns.scatterplot(data=merged, x="gdp_per_capita", y="human_development_index", size="death_rate", hue="continent", cmap="Accent", sizes=(100, 1500), ax=ax2, legend=False) ax1.set(xlabel='GDP per Capita', ylabel ='Life Expectancy', title='Choose') ax2.set(xlabel='GDP per Capita', ylabel ='Human Development Index', title='Choose') # 此处替换为你实际的大洲分类数量,比如共5个大洲就填5 CONTINENT_COUNT = 5 # 配置第一个子图图例 hue_handles1, hue_labels1 = ax1.get_legend_handles_labels() hue_handles1 = hue_handles1[:CONTINENT_COUNT] hue_labels1 = hue_labels1[:CONTINENT_COUNT] size_handles1, size_labels1 = ax1.get_legend_handles_labels() size_handles1 = size_handles1[CONTINENT_COUNT:] size_labels1 = size_labels1[CONTINENT_COUNT:] leg1 = ax1.legend(hue_handles1, hue_labels1, loc="upper right", title="大洲", markerscale=1) ax1.add_artist(leg1) ax1.legend(size_handles1, size_labels1, loc="lower right", title="死亡率", markerscale=1) # 配置第二个子图图例 hue_handles2, hue_labels2 = ax2.get_legend_handles_labels() hue_handles2 = hue_handles2[:CONTINENT_COUNT] hue_labels2 = hue_labels2[:CONTINENT_COUNT] size_handles2, size_labels2 = ax2.get_legend_handles_labels() size_handles2 = size_handles2[CONTINENT_COUNT:] size_labels2 = size_labels2[CONTINENT_COUNT:] leg2 = ax2.legend(hue_handles2, hue_labels2, loc="upper right", title="大洲", markerscale=1) ax2.add_artist(leg2) ax2.legend(size_handles2, size_labels2, loc="lower right", title="死亡率", markerscale=1) # 自动调整布局避免元素重叠 plt.tight_layout() plt.show()
补充说明:
markerscale=1参数保证图例内的气泡大小和图中实际映射大小完全一致,不会出现缩放后变形或者超出图例区域的问题- 如果图例遮挡了图内内容,可以给
legend方法添加bbox_to_anchor=(x,y)参数微调位置,也可以设置参数把图例放到图的外侧
内容的提问来源于stack exchange,提问作者Callum Marley
相关产品推荐
相关产品推荐

