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

如何在带hue的Seaborn factorplot箱线图上显示样本量

在带Hue的Seaborn箱线图上添加样本数量标注

我明白你遇到的问题了——当用Seaborn的catplot(注意factorplot已经被官方弃用,推荐用catplot替代)加上hue参数后,每个x类别下会有多个分组的箱线,原来单x轴时直接取刻度位置的方法就失效了。下面我用tips数据集给你两套完整的解决方案,你可以按需选择:

方法一:手动计算Hue分组的位置偏移

这种方法适合你明确知道hue类别数量的场景,逻辑清晰,容易理解:

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

sns.set_style("whitegrid")
# 加载tips数据集
tips = sns.load_dataset("tips")

# 绘制带hue的箱线图,用catplot替代弃用的factorplot
g = sns.catplot(x="day", y="total_bill", hue="sex", kind="box", data=tips)
ax = g.ax  # 获取绘图的轴对象

# 计算每个(x类别, hue类别)组合的样本数量
counts = tips.groupby(['day', 'sex']).size().reset_index(name='count')

# 获取x轴的刻度位置和对应的类别
x_ticks = ax.get_xticks()
x_categories = tips['day'].unique()

# 遍历每个x类别,给对应的两个hue分组添加标注
for i, day in enumerate(x_categories):
    # 筛选当前x类别下的所有hue分组计数
    day_counts = counts[counts['day'] == day]
    # 男性分组的位置:x刻度位置 - 0.2(因为箱线默认宽度0.8,两个分组各占0.4)
    ax.text(x_ticks[i] - 0.2, ax.get_ylim()[1] * 0.98, 
            f'n={day_counts[day_counts["sex"]=="Male"]["count"].values[0]}',
            ha='center', va='top', fontsize=10)
    # 女性分组的位置:x刻度位置 + 0.2
    ax.text(x_ticks[i] + 0.2, ax.get_ylim()[1] * 0.98, 
            f'n={day_counts[day_counts["sex"]=="Female"]["count"].values[0]}',
            ha='center', va='top', fontsize=10)

plt.tight_layout()
plt.show()

方法二:自动获取箱线位置(更通用)

如果你的hue类别数量不确定,或者想让代码更灵活,可以直接获取箱线图的矩形patch对象,自动提取位置信息:

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

sns.set_style("whitegrid")
tips = sns.load_dataset("tips")

g = sns.catplot(x="day", y="total_bill", hue="sex", kind="box", data=tips)
ax = g.ax

# 计算每个分组的样本数量,注意顺序要和箱线图的绘制顺序一致
counts = tips.groupby(['day', 'sex']).size().values

# 筛选出所有箱线对应的矩形patch(排除其他辅助元素)
boxes = [patch for patch in ax.patches if isinstance(patch, plt.Rectangle)]

# 遍历每个箱线,添加样本数量标注
for box, count in zip(boxes, counts):
    # 获取箱线的中心x坐标
    x_center = box.get_x() + box.get_width() / 2
    # 获取箱线的顶部y坐标(也可以放在中位数位置,看你需求)
    y_top = box.get_y() + box.get_height()
    # 添加文本标注
    ax.text(x_center, y_top, f'n={count}', ha='center', va='bottom', fontsize=10)

plt.tight_layout()
plt.show()

关键说明

  • 为什么原来的方法失效?因为添加hue后,Seaborn会在同一个x刻度位置左右偏移绘制多个箱线,不再是刚好对齐x刻度,所以直接用ax.get_xticks()的位置会对应到分组中间,不是单个箱线的位置。
  • 如果你想把标注放在中位数位置,可以通过ax.lines获取中位数线的位置,不过上面两种方法放在箱线顶部已经足够清晰直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:13:57