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

如何在Matplotlib中为条形图标签设置对应条形颜色?

问题描述

我经常需要制作带颜色编码的条形图,借助pyplot.bar_label可以轻松给条形添加标签,但让标签颜色和对应条形一致并不简单。

目前我实现的最优方式是:

fig, axe = plt.subplots()
bars = axe.bar(["A", "B", "C"], height=[4, 6, 2], color=colors, label="Data")
labels = axe.bar_label(bars, fontsize=10, fontweight=700, fmt="%.1f")
for (label, color) in zip(labels, colors):
    label.set_color(color)
axe.axhline(4, linestyle="-.", color="black", label="Limit")
axe.legend()

但直觉上直接给bar_label传color=colors会报错:

labels = axe.bar_label(bars, fontsize=10, fontweight=700, fmt="%.1f", color=colors)

报错信息如下:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [4], line 3
      1 fig, axe = plt.subplots()
      2 bars = axe.bar(["A", "B", "C"], height=[4, 6, 2], color=colors, label="Data")
----> 3 labels = axe.bar_label(bars, fontsize=10, fontweight=700, fmt="%.1f", color=colors)
      4 for (label, color) in zip(labels, colors):
      5     label.set_color(color)

File ~/.local/lib/python3.10/site-packages/matplotlib/axes/_axes.py:2678, in Axes.bar_label(self, container, labels, fmt, label_type, padding, **kwargs)
   2675     if np.isnan(dat):
   2676         lbl = ''
-> 2678     annotation = self.annotate(fmt % value if lbl is None else lbl,
   2679                                xy, xytext, textcoords="offset points",
   2680                                ha=ha, va=va, **kwargs)
   2681     annotations.append(annotation)
   2683 return annotations

File ~/.local/lib/python3.10/site-packages/matplotlib/axes/_axes.py:666, in Axes.annotate(self, text, xy, *args, **kwargs)
    664 @docstring.dedent_interpd
    665 def annotate(self, text, xy, *args, **kwargs):
-> 666     a = mtext.Annotation(text, xy, *args, **kwargs)
    667     a.set_transform(mtransforms.IdentityTransform())
    668     if 'clip_on' in kwargs:

File ~/.local/lib/python3.10/site-packages/matplotlib/text.py:1825, in Annotation.__init__(self, text, xy, xytext, xycoords, textcoords, arrowprops, annotation_clip, **kwargs)
   1822     self.arrow_patch = None
   1824 # Must come last, as some kwargs may be propagated to arrow_patch.
-> 1825 Text.__init__(self, x, y, text, **kwargs)

File ~/.local/lib/python3.10/site-packages/matplotlib/text.py:143, in Text.__init__(self, x, y, text, color, verticalalignment, horizontalalignment, multialignment, fontproperties, rotation, linespacing, rotation_mode, usetex, wrap, transform_rotates_text, parse_math, **kwargs)
    141 self._text = ''
    142 self.set_text(text)
-> 143 self.set_color(
    144     color if color is not None else mpl.rcParams["text.color"])
    145 self.set_fontproperties(fontproperties)
    146 self.set_usetex(usetex)

File ~/.local/lib/python3.10/site-packages/matplotlib/text.py:947, in Text.set_color(self, color)
    944 # "auto" is only supported by axisartist, but we can just let it error
    945 # out at draw time for simplicity.
    946 if not cbook._str_equal(color, "auto"):
-> 947     mpl.colors._check_color_like(color=color)
    948 # Make sure it is hashable, or get_prop_tup will fail (remove this once
    949 # get_prop_tup is removed).
    950 try:

File ~/.local/lib/python3.10/site-packages/matplotlib/colors.py:130, in _check_color_like(**kwargs)
    128 for k, v in kwargs.items():
    129     if not is_color_like(v):
-> 130         raise ValueError(f"{v!r} is not a valid value for {k}")

ValueError: ['orange', 'red', 'green'] is not a valid value for color

这说明bar_label的color参数仅支持单一颜色,请问有没有办法不用事后循环修改,直接在调用bar_label时设置每个标签对应条形的颜色?

解决方案

目前Matplotlib的bar_label方法本身不支持直接传入颜色列表为每个标签设置不同颜色,因为该方法会将color等关键字参数直接传递给annotate方法,而annotate的color仅接受单一颜色值。

你当前用循环逐个修改标签颜色的方式,是现阶段最直接有效的实现方法。不过可以优化写法,直接从条形对象中获取颜色,无需额外维护colors列表:

fig, axe = plt.subplots()
bars = axe.bar(["A", "B", "C"], height=[4, 6, 2], color=["orange", "red", "green"], label="Data")
labels = axe.bar_label(bars, fontsize=10, fontweight=700, fmt="%.1f")
for label, bar in zip(labels, bars):
    label.set_color(bar.get_facecolor())
axe.axhline(4, linestyle="-.", color="black", label="Limit")
axe.legend()

这种写法无需额外保存颜色列表,直接从每个条形实例提取填充色,更简洁且不易出错。

如果想要更“原生”的调用体验,可以自定义封装函数,把循环逻辑整合进去:

def bar_label_colored(ax, container, **kwargs):
    colors = kwargs.pop('colors', None)
    labels = ax.bar_label(container, **kwargs)
    if colors is None:
        colors = [bar.get_facecolor() for bar in container]
    for label, color in zip(labels, colors):
        label.set_color(color)
    return labels

# 使用方式
fig, axe = plt.subplots()
bars = axe.bar(["A", "B", "C"], height=[4, 6, 2], color=["orange", "red", "green"], label="Data")
bar_label_colored(axe, bars, fontsize=10, fontweight=700, fmt="%.1f")
axe.axhline(4, linestyle="-.", color="black", label="Limit")
axe.legend()

后续调用时就不用再写循环,直接使用自定义函数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:10:51