You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Seaborn箱线图:按hue分组设置均值标记颜色

问题解决:Seaborn箱线图均值标记颜色匹配hue分组及图例修复

问题分析

  • 带hue的箱线图中,部分类别仅单组数据,均值标记颜色未与hue分组匹配
  • 旧方案依赖ax.patches获取箱体,但新版Seaborn中箱体以PathCollection形式存在,导致ax.patches为空
  • 箱体透明度设置影响图例显示

解决方案

步骤1:正确获取箱体元素

使用ax.collections替代ax.patches获取箱线图的箱体集合,适配新版Seaborn的渲染逻辑。

步骤2:映射均值标记与hue颜色

提前构建hue分组与调色板颜色的对应关系,再匹配对应位置的均值标记颜色。

步骤3:修复图例透明度

先保存图例的原始视觉属性,修改箱体后再恢复,避免透明度设置影响图例显示。

完整修改代码

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

tpar = "val"
data = {'type': {0: 'a', 1: 'b', 2: 'b', 3: 'c', 4: 'c', 5: 'c', 6: 'c', 7: 'c', 8: 'd', 9: 'd', 10: 'e', 11: 'e', 12: 'e', 13: 'b', 14: 'b', 15: 'd', 16: 'e', 17: 'b', 18: 'd', 19: 'd', 20: 'e', 21: 'f', 22: 'f', 23: 'g', 24: 'h', 25: 'h', 26: 'h', 27: 'h', 28: 'h', 29: 'i', 30: 'j', 31: 'b', 32: 'b', 33: 'b', 34: 'b', 35: 'b', 36: 'b', 37: 'b', 38: 'b', 39: 'b', 40: 'b', 41: 'b', 42: 'c', 43: 'c', 44: 'c', 45: 'c', 46: 'c', 47: 'c', 48: 'c', 49: 'c', 50: 'c', 51: 'd', 52: 'd', 53: 'd', 54: 'd', 55: 'd', 56: 'd', 57: 'd', 58: 'd', 59: 'd', 60: 'e', 61: 'e', 62: 'e', 63: 'e', 64: 'e', 65: 'e', 66: 'e', 67: 'e', 68: 'e', 69: 'k', 70: 'k', 71: 'k', 72: 'k', 73: 'k', 74: 'k', 75: 'k'}, 'loc': {0: '1', 1: '1', 2: '1', 3: '1', 4: '1', 5: '1', 6: '1', 7: '1', 8: '1', 9: '1', 10: '1', 11: '1', 12: '1', 13: '1', 14: '1', 15: '1', 16: '1', 17: '1', 18: '1', 19: '1', 20: '1', 21: '2', 22: '2', 23: '2', 24: '2', 25: '2', 26: '2', 27: '2', 28: '2', 29: '2', 30: '2', 31: '2', 32: '2', 33: '2', 34: '2', 35: '2', 36: '2', 37: '2', 38: '2', 39: '2', 40: '2', 41: '2', 42: '2', 43: '2', 44: '2', 45: '2', 46: '2', 47: '2', 48: '2', 49: '2', 50: '2', 51: '2', 52: '2', 53: '2', 54: '2', 55: '2', 56: '2', 57: '2', 58: '2', 59: '2', 60: '2', 61: '2', 62: '2', 63: '2', 64: '2', 65: '2', 66: '2', 67: '2', 68: '2', 69: '2', 70: '2', 71: '2', 72: '2', 73: '2', 74: '2', 75: '2'}, 'val': {0: 9.707793424913127, 1: 13.386094727644041, 2: 23.79163880820678, 3: 10.39395928554849, 4: 16.10737178534521, 5: 14.280981644500402, 6: 13.37284106485653, 7: 9.438051071191, 8: 13.428417031257947, 9: 11.201719882794471, 10: 7.231770732496349, 11: 4.338483085841884, 12: 1.50907053154171, 13: 7.660083168740548, 14: 22.444633122805286, 15: 17.47145308755451, 16: 20.69718471318728, 17: 18.315282738981132, 18: 17.978380949794715, 19: 17.665480789484036, 20: 4.50274108225081, 21: 13.00879424293115, 22: 11.190356759760153, 23: 15.892212467377552, 24: 12.931549456351844, 25: 5.463525490936832, 26: 10.156762200578838, 27: 12.092758762869726, 28: 4.342703737075237, 29: 6.751842159450817, 30: 20.42046084888383, 31: 17.624071472791666, 32: 15.743860368917321, 33: 13.185896322157518, 34: 22.180832538032085, 35: 20.24978364632158, 36: 17.59687639466673, 37: 10.066630571468492, 38: 21.153824756899414, 39: 11.757339048404415, 40: 9.967497539236037, 41: 13.105560648792903, 42: 11.508803850577317, 43: 27.324971768461026, 44: 15.590194689475396, 45: 17.644975051594866, 46: 17.884712323792073, 47: 15.137560053438719, 48: 11.150836819567878, 49: 13.86822928951128, 50: 15.072225938867279, 51: 19.36268729077879, 52: 14.020243772704816, 53: 11.868300735988246, 54: 11.30447305533902, 55: 11.759812170322407, 56: 9.208486801410231, 57: 12.09441671041434, 58: 8.721831182283529, 59: 17.032203415542853, 60: 7.220149059582103, 61: 7.331398497538517, 62: 8.429772191688613, 63: 5.4195686050848, 64: 8.784087645946556, 65: 3.88845812696214, 66: 3.9065489464341416, 67: 3.8681574564882153, 68: 13.116477449330214, 69: 17.377320489000613, 70: 21.290156451172408, 71: 21.431382329030203, 72: 10.522720845810566, 73: 11.65610643463835, 74: 25.79359143984027, 75: 13.299067374572909}}
indata = pd.DataFrame.from_dict(data)

fig, ax = plt.subplots()
# 提前构建hue分组与颜色的映射
palette = sns.color_palette("bright", n_colors=indata['loc'].nunique())
loc_order = indata['loc'].unique()
color_map = dict(zip(loc_order, palette))

# 绘制箱线图
sns.boxplot(y=tpar, x="type", hue='loc', data=indata, linewidth=0.5, palette=palette, showmeans=True)

# 保存图例原始属性,避免透明度影响
handles, labels = ax.get_legend_handles_labels()
original_alphas = [handle.get_alpha() for handle in handles]
original_colors = [handle.get_facecolor() for handle in handles]

# 修改箱体样式:添加黑色边框、设置透明度
for coll in ax.collections:
    if hasattr(coll, 'get_facecolor'):
        coll.set_edgecolor('black')
        coll.set_alpha(0.1)

# 匹配均值标记与对应hue颜色
mean_lines = [line for line in ax.lines if line.get_marker() != '']
# 获取每个x位置对应的loc分组
x_ticks = ax.get_xticks()
type_loc_pairs = []
for x in x_ticks:
    type_name = indata['type'].unique()[x]
    locs = indata[indata['type'] == type_name]['loc'].unique()
    type_loc_pairs.extend(locs)

# 为每个均值标记设置对应颜色
for line, loc in zip(mean_lines, type_loc_pairs):
    color = color_map[loc]
    line.set_markerfacecolor(color)
    line.set_markeredgecolor('black')
    line.set_markeredgewidth(0.5)

# 恢复图例原始视觉属性
for handle, alpha, color in zip(handles, original_alphas, original_colors):
    handle.set_alpha(alpha)
    handle.set_facecolor(color)
ax.legend(handles=handles, labels=labels, bbox_to_anchor=(1.12, 0.5), loc='center', borderaxespad=10)

# 其他绘图设置
ax.set_ylim(0, max(indata.get(tpar)))
plt.yticks(np.arange(0, max(indata.get(tpar))+10,5))
plt.title('Test')
plt.xticks(rotation=45)
ax.grid(b=True, which='major', color='black', linewidth=0.075)
ax.grid(b=True, which='minor', color='black', linewidth=0.075)

plt.show()

关键修改说明

  1. 箱体元素获取:用ax.collections替代ax.patches,适配新版Seaborn的箱体渲染方式。
  2. 颜色映射:提前构建hue分组(loc)与调色板颜色的对应字典,确保均值标记颜色准确匹配。
  3. 图例修复:先保存图例的原始透明度和颜色,修改箱体后再恢复,避免透明度设置影响图例显示。
  4. 均值标记匹配:通过x轴位置对应每个type下的loc分组,将均值标记与对应hue颜色绑定,解决部分类别仅单组数据的颜色匹配问题。

内容的提问来源于stack exchange,提问作者JSV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:37:00