如何实现两组上下配对的Boxplot并排展示?
箱线图分组并排+上下配对展示需求
我有4个数据集需要绘制箱线图并做横向对比,具体要求:
- ab组:
gp-ab和mf-ab箱线图上下(或重叠)展示 - ba组:
gp-ba和mf-ba箱线图上下展示 - ab组与ba组整体并排
但用Seaborn生成的结果是4个箱线图全部并排(如下),不知道如何实现分组配对的效果。
当前全部并排效果:
当前Seaborn代码:
#Seaborn 代码 import pandas as pd import seaborn as sns import numpy as np import matplotlib.pyplot as plt seed=3 legendclass = np.concatenate([['gp-ab']*seed,['mf-ab']*seed,['gp-ba']*seed,['mf-ba']*seed]).T.reshape(4, seed) fid = legendclass.reshape(seed*(4)) #(seedx4) pts = [[6., 6., 6., 6., 6., 6., 6., 6., 6., 6., 6., 6.], [8., 8., 8., 8., 8., 8., 8., 8., 8., 8., 8., 8.]] rm_6 = np.array([34.97867074, 34.7816484 , 34.53641255, 15.37061205, 15.82006291, 30.69718637, 15.15036871, 15.08025984, 17.3527419 , 17.46879552, 33.28589986, 11.28854684]) df6 = pd.DataFrame({'fid-type': fid, '6' : pts[0], 'rmse-gp':rm_6}) fig, ax = plt.subplots(figsize=(12,8)) sns.boxplot(data=df6, x='6', y='rmse-gp', hue='fid-type', dodge=True, ax=ax, width=0.3)
另外我试过用NumPy实现,但无法调整水平间距,效果如下:
实现方案
核心思路是拆分数据集的分组逻辑:把ab/ba作为一级分组(控制左右并排),把gp/mf作为二级分组(控制上下/重叠),通过自定义箱线图位置来实现需求。
步骤1:重构数据结构
将原有的fid-type字段拆分为group(ab/ba)和method(gp/mf),明确分组层级:
# 拆分fid-type为分组和方法字段 df6['group'] = df6['fid-type'].str.split('-').str[1] df6['method'] = df6['fid-type'].str.split('-').str[0]
步骤2:自定义箱线图位置
给ab组、ba组分配不同的x坐标,同一组内的两个方法设置微小垂直偏移(实现上下排列),完整代码如下:
import pandas as pd import seaborn as sns import numpy as np import matplotlib.pyplot as plt seed=3 legendclass = np.concatenate([['gp-ab']*seed,['mf-ab']*seed,['gp-ba']*seed,['mf-ba']*seed]).T.reshape(4, seed) fid = legendclass.reshape(seed*(4)) #(seedx4) rm_6 = np.array([34.97867074, 34.7816484 , 34.53641255, 15.37061205, 15.82006291, 30.69718637, 15.15036871, 15.08025984, 17.3527419 , 17.46879552, 33.28589986, 11.28854684]) df6 = pd.DataFrame({'fid-type': fid, 'rmse-gp':rm_6}) # 拆分分组和方法字段 df6['group'] = df6['fid-type'].str.split('-').str[1] df6['method'] = df6['fid-type'].str.split('-').str[0] fig, ax = plt.subplots(figsize=(8,8)) # 定义分组的x位置和垂直偏移量 group_positions = {'ab': 0, 'ba': 1} offset = 0.1 # 同一组内两个箱线图的垂直偏移量 # 遍历分组和方法绘制箱线图 for group in ['ab', 'ba']: for idx, method in enumerate(['gp', 'mf']): subset = df6[(df6['group'] == group) & (df6['method'] == method)] # 自定义位置:x控制左右分组,y加偏移实现上下排列 sns.boxplot( data=subset, x=[group_positions[group]] * len(subset), y=subset['rmse-gp'] + idx*offset, width=0.3, ax=ax, label=f'{method}-{group}' ) # 设置轴标签和图例 ax.set_xticks([0, 1]) ax.set_xticklabels(['ab组', 'ba组']) ax.set_ylabel('RMSE') ax.legend(title='方法-分组') plt.tight_layout() plt.show()
灵活调整说明
- 若要重叠展示同一组内的箱线图,删除
y参数中的+ idx*offset即可,同时可调整width让两个箱线图部分重叠。 - 若要调整ab组和ba组的水平间距,修改
group_positions中的数值(比如把ba设为1.5,间距会变大)。 - 该方式比NumPy手动绘制更灵活,可直接复用Seaborn的样式和统计计算能力。
内容的提问来源于stack exchange,提问作者theprogressor
相关产品推荐
相关产品推荐

