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

Python Seaborn如何在填充箱线图上叠加带阴影线的箱线图

叠加带阴影线箱线图的颜色不一致问题修复

问题描述

需要在填充样式的基础箱线图上,叠加带阴影线(hatched)的第二层箱线图。现有代码运行后整体布局效果符合预期,但存在箱线帽线、中位线与箱线边框颜色不统一的问题。

  • 放开第一个exit()的注释可得到单层基础填充箱线图效果
  • 放开第二个exit()的注释可得到两层箱线图叠加、未调整样式的效果
    经测试matplotlib没有原生提供箱线图叠加的专用接口,现有单组箱线图添加阴影线的方案仅覆盖单层箱线图场景,不适用于两层叠加的需求。

箱线图叠加效果示意图

测试复现代码

import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns

fig, ax = plt.subplots(figsize=(2, 5))

tips = sns.load_dataset("tips")
tips['total_bill_plus5'] = tips['total_bill'] + 5

# 绘制第一层基础填充箱线图
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, fliersize=0, whis=0)
plt.ylim(0, 50)
#exit()
# 绘制第二层待加阴影线的箱线图
sns.boxplot(x="day", y="total_bill_plus5", hue="smoker", data=tips, fliersize=0, whis=0)
#exit()
ax.get_legend().remove()

box_patches = [patch for patch in ax.patches if type(patch) == matplotlib.patches.PathPatch]
if len(box_patches) == 0:  # 兼容matplotlib 3.5以前版本,该版本箱型块存储在ax.artists中
    box_patches = ax.artists

num_patches = len(box_patches)
lines_per_boxplot = len(ax.lines) // num_patches
col = (.5, .5, .5, 1)

# 原有存在bug的样式设置逻辑
for i, patch in enumerate( box_patches[int(num_patches/2):] ):
    patch.set_edgecolor(col)
    patch.set_facecolor('None')

    # 每个箱线对应多个Line2D对象(须、帽线、中位线、离群点等)
    for line in ax.lines[i * lines_per_boxplot: (i + 1) * lines_per_boxplot]:
        line.set_color(col)
        line.set_mfc(col)  # 离群点填充色
        line.set_mec(col)  # 离群点边框色
        patch.set_hatch('////')

问题原因

原有样式遍历逻辑存在索引错误:两次调用boxplot后,轴内的箱型块(patch)、线元素(lines)都是按绘制顺序存储的,第一层基础箱线的元素排在前半段,第二层待加阴影线的箱线元素排在后半段。原循环遍历第二层箱型块时,线元素切片从索引0开始取,实际修改的是第一层基础箱线的线颜色,第二层箱线的帽线、中位线仍保留默认颜色,因此出现颜色不匹配的问题。

修复方案

调整线元素的切片起始位置,确保遍历的线元素和当前处理的第二层箱型块一一对应即可,修正后的样式设置代码如下:

second_layer_patch_start = int(num_patches / 2)
second_layer_line_start = second_layer_patch_start * lines_per_boxplot

for idx, patch in enumerate(box_patches[second_layer_patch_start:]):
    # 设置箱型块样式
    patch.set_edgecolor(col)
    patch.set_facecolor('none')
    patch.set_hatch('////')
    # 对应设置当前箱型块关联的所有线元素样式
    line_slice_start = second_layer_line_start + idx * lines_per_boxplot
    line_slice_end = second_layer_line_start + (idx + 1) * lines_per_boxplot
    for line in ax.lines[line_slice_start:line_slice_end]:
        line.set_color(col)
        line.set_mfc(col)
        line.set_mec(col)

运行修正后的代码,第二层带阴影线的箱线边框、须线、帽线、中位线颜色会完全统一,达到预期效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:24:22