如何为Seaborn箱线图的每个x标签单独按中位数排序?
解决Seaborn箱线图按分组内中位数单独排序的问题
Seaborn默认的boxplot没法直接实现每个x分组下的hue类别(比如你的模型)按各自中位数排序,因为hue_order是全局生效的。要实现需求,得先预处理数据计算分组内的中位数排序,再用分面绘图来分别指定每个分组的排序:
步骤1:计算每个x分组下的模型中位数排序
假设你的数据框df包含三列:noise_level(x轴标签,如"gaussian 1")、model(模型名称)、metric(箱线图的数值列)。先计算每个噪声水平下各模型的中位数,再生成对应分组的排序模型列表:
import pandas as pd # 计算每个噪声水平+模型组合的中位数 median_df = df.groupby(['noise_level', 'model'])['metric'].median().reset_index() # 按噪声水平分组,对每个组内的模型按中位数降序排序(升序把False改成True) sorted_model_dict = median_df.groupby('noise_level').apply( lambda group: group.sort_values('metric', ascending=False)['model'].tolist() ).to_dict()
步骤2:用FacetGrid分面绘制,每个分组单独指定排序
用FacetGrid把每个噪声水平拆成子图,在每个子图里用对应分组的排序模型列表作为hue_order:
import seaborn as sns import matplotlib.pyplot as plt # 创建分面网格,每个子图对应一个噪声水平 g = sns.FacetGrid(df, col='noise_level', col_wrap=3, sharex=False, sharey=True) # 给每个子图绘制箱线图,动态获取当前分组的模型排序 g.map_dataframe( sns.boxplot, x='noise_level', y='metric', hue='model', hue_order=lambda data: sorted_model_dict[data['noise_level'].iloc[0]] ) # 添加统一图例 g.add_legend() plt.tight_layout() plt.show()
替代方案(不拆分面)
如果想把所有分组放在同一个图里,可以重新构造数据,给每个模型在对应噪声水平下分配排序后的位置,再用x轴表示noise_level,hue按排序后的模型顺序,但这种方法需要手动调整x轴元素位置,不如分面直观。
内容的提问来源于stack exchange,提问作者luc
相关产品推荐
相关产品推荐

