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

如何自动为非均匀列表字典生成的箱线图添加标注(如计数)

解决箱线图非均匀分类的自动标注问题

嘿,我太懂你这种折腾手动坐标的痛苦了——每次字典变了都要重新调位置,效率低到爆炸。咱们直接搞个完全自动适配的方案,以后不管字典加多少键、值的长度怎么变,标注都能乖乖跑到对应的分类下面!

核心思路

箱线图的每个分类在x轴上的位置其实是固定的数值(第一个分类在x=1,第二个x=2,以此类推),这些数值可以通过ax.get_xticks()直接获取。我们不用费劲转换坐标系,直接用这个位置结合混合坐标系(x用数据坐标,y用轴比例坐标)来放标注,就能完美适配任何情况。

改进后的代码

import numpy as np
import matplotlib.pyplot as plt

# 测试用的字典,随便加键值对都能自动适配
dictionary = {
    "a": [1, 2, 3, 4, 5],
    "b": [1, 2, 3, 4, 5, 6, 7],
    "c": [0, 0, 1, 3, 5, 8, 10, 12],
    "d": [5, 5, 5, 5]
}

fig, ax = plt.subplots(figsize=(8, 6), bottom=0.15)  # 留出底部空间放标注
ax.boxplot(dictionary.values())
ax.set_xticklabels(dictionary.keys())

# 遍历每个分类,自动添加计数标注
for x_pos, category in zip(ax.get_xticks(), dictionary.keys()):
    count = len(dictionary[category])
    # 用ax.get_xaxis_transform()实现混合坐标:x是数据坐标,y是轴比例坐标
    ax.text(
        x_pos, -0.1,  # y=-0.1表示在x轴下方10%的位置
        f"n={count}",
        ha="center", va="top",
        transform=ax.get_xaxis_transform()
    )

plt.show()

关键细节解释

  1. 混合坐标系:ax.get_xaxis_transform()是神器!它让x坐标用数据坐标系(完美对应箱线图的分类位置),y坐标用axes坐标系(0是x轴底部,1是顶部)——不管y轴是线性还是对数刻度,这个位置都不会乱。
  2. 自动适配字典变化:zip(ax.get_xticks(), dictionary.keys())会自动匹配每个分类的x位置和键,哪怕你新增/删除分类,代码都不用改。
  3. 预留空间:创建子图时设置bottom=0.15,给底部标注留出足够显示空间,避免被切掉。

如果你想用更复杂的标注(比如带框的)

如果需要像你之前尝试的AnnotationBbox那种带样式的标注,也可以用同样的坐标逻辑:

from matplotlib.offsetbox import TextArea, AnnotationBbox

for x_pos, category in zip(ax.get_xticks(), dictionary.keys()):
    count = len(dictionary[category])
    text_box = TextArea(f"n={count}", textprops={"ha":"center"})
    ab = AnnotationBbox(
        text_box, xy=(x_pos, 0),  # xy用数据坐标
        xybox=(0, -30), boxcoords="offset points",
        pad=0.3, frameon=True,
        xycoords=ax.get_xaxis_transform()  # 同样用混合坐标
    )
    ax.add_artist(ab)

这个方案彻底摆脱了手动试错的麻烦,不管字典怎么变,标注都能精准到位!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:02:37