如何在Seaborn与Pandas中实现图例按类别分栏显示?
解决Seaborn散点图图例按类别分组分栏的问题
使用Seaborn基于Pandas DataFrame绘制散点图时,通过hue和style区分不同类别,设置图例多列显示在图表上方后,因不同类别条目数量不一致导致布局混乱,希望图例分栏换行时能对应类别组的切换(同一类别的所有条目放在同一栏)。
以下提供两种可行解决方案:
方案一:拆分独立图例,分别对应hue和style
将hue和style对应的图例拆分为两个独立的图例,分别放置在图表上方的左右区域,每个图例内的条目垂直排列,布局更清晰:
import numpy as np import seaborn as sns import pandas as pd import matplotlib.pyplot as plt f, ax = plt.subplots() df = pd.DataFrame({'col1': [1, 2, 3, 1, 2, 3, 4, 1, 2, 3], 'col1b': [1.1, 1.9, 3.1, 0.9, 2.1, 3.2, 4.1, 1, 1.8, 3.2], 'col2': [1, 1, 1, 2, 2, 2, 2, 3, 3, 3], 'col3': [10, 20, 15, 10, 20, 15, 30, 10, 20, 15]}) # 绘制散点图 sns.scatterplot(data=df, x='col1', y='col1b', hue='col2', style='col3', ax=ax) # 获取并分离hue和style的图例元素 handles, labels = ax.get_legend_handles_labels() hue_indices = [labels.index(str(i)) for i in df['col2'].unique()] style_indices = [labels.index(str(i)) for i in df['col3'].unique()] hue_handles = [handles[i] for i in hue_indices] hue_labels = [labels[i] for i in hue_indices] style_handles = [handles[i] for i in style_indices] style_labels = [labels[i] for i in style_indices] # 移除默认图例 ax.legend_.remove() # 创建hue图例并添加到轴上 leg_hue = ax.legend(hue_handles, hue_labels, loc='lower center', bbox_to_anchor=(0.3, 1), ncol=1, title='col2', frameon=False) ax.add_artist(leg_hue) # 创建style图例 ax.legend(style_handles, style_labels, loc='lower center', bbox_to_anchor=(0.7, 1), ncol=1, title='col3', frameon=False) plt.savefig('mwe_fixed.png')
方案二:重新排列图例元素顺序,合并为单个分栏图例
将hue对应的所有图例条目放在前面,style的条目放在后面,设置分栏后,换行时刚好从hue组切换到style组:
import numpy as np import seaborn as sns import pandas as pd import matplotlib.pyplot as plt f, ax = plt.subplots() df = pd.DataFrame({'col1': [1, 2, 3, 1, 2, 3, 4, 1, 2, 3], 'col1b': [1.1, 1.9, 3.1, 0.9, 2.1, 3.2, 4.1, 1, 1.8, 3.2], 'col2': [1, 1, 1, 2, 2, 2, 2, 3, 3, 3], 'col3': [10, 20, 15, 10, 20, 15, 30, 10, 20, 15]}) # 绘制散点图 sns.scatterplot(data=df, x='col1', y='col1b', hue='col2', style='col3', ax=ax) # 获取图例元素并重新排序:先hue,后style handles, labels = ax.get_legend_handles_labels() hue_labels_list = [str(i) for i in df['col2'].unique()] style_labels_list = [str(i) for i in df['col3'].unique()] new_order = [labels.index(l) for l in hue_labels_list + style_labels_list] new_handles = [handles[i] for i in new_order] new_labels = [labels[i] for i in new_order] # 移除默认图例,创建新的分栏图例 ax.legend_.remove() sns.move_legend( ax, "lower center", bbox_to_anchor=(.5, 1), ncol=2, title=None, frameon=False, handles=new_handles, labels=new_labels ) plt.savefig('mwe_fixed.png')
内容的提问来源于stack exchange,提问作者SteLab
相关产品推荐
相关产品推荐

