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

Matplotlib子图柱状图:为不同指标柱子设置固定对应颜色

问题描述

我有多个共享坐标轴的子图,希望在每个子图中,对应Recall指标的柱子使用指定颜色,对应Precision指标的柱子使用另一固定颜色,其余指标的柱子也分别匹配专属固定颜色。
原代码运行效果参考:
共享轴子图示例

原实现代码
# data
values = list([['nan', 'nan', 0.25, 0.25],
       ['nan', 'nan', 0.813, 0.413],
       ['nan', 'nan', 0.13793, 0.793],
       [0.5, 0.4666, 0.6666666, 0.75],
       [0.725, 0.13, 0.444, 0.5],
       [0.33337, 0.7776, 0.53,
        0.86],
       [0.296, 0.33, 0.68,
        0.4722],
       [0.158, 0.166, 0.45,
        0.3477],
       [0.22063, 0.2218, 0.54,
        0.7778],
       [0.8421, 0.199, 0.57,
        0.4333],
       [0.36842105, 0.545, 0.386,
        0.155567],
       [0.62281, 0.23394, 0.46,
        0.36667]])
index_1 = ['1', '2', '4', '5']
index_2 = ['Recall', 'Precision', 'F1']
iterables = [index_1, index_2]
index = pd.MultiIndex.from_product(iterables, names=["ClusterID", "Metric"])

df = pd.DataFrame(values, columns = ['Method1', 'Method2', 'Method3', 'Method4'], index = index)


c = ['red', 'yellow', 'black']
ax = df.unstack(level=0).plot(kind='bar', subplots=True, rot=0, figsize=(20, 18), layout=(4, 4), color = c)
def_ylim = (0.0, 0.8)
plt.setp(ax, ylim = def_ylim)
plt.tight_layout(pad=0.6, w_pad=0.6, h_pad=1.0)
问题原因

直接在plot()方法里传入长度为3的颜色列表时,pandas会按列的顺序循环分配颜色,和你需要按行索引(Metric)固定匹配颜色的逻辑不匹配,无法实现同指标同色的效果。另外原数据里的'nan'是字符串格式,不是真正的空值,容易触发绘图类型错误。

实现方案

核心思路是先建立指标和颜色的固定映射表,绘图完成后遍历所有子图,按柱子对应的指标名逐一设置颜色,不受列顺序影响。
完整可运行代码如下:

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

# 加载并预处理数据 把字符串'nan'替换为真正的空值
values = [
    [np.nan, np.nan, 0.25, 0.25],
    [np.nan, np.nan, 0.813, 0.413],
    [np.nan, np.nan, 0.13793, 0.793],
    [0.5, 0.4666, 0.6666666, 0.75],
    [0.725, 0.13, 0.444, 0.5],
    [0.33337, 0.7776, 0.53, 0.86],
    [0.296, 0.33, 0.68, 0.4722],
    [0.158, 0.166, 0.45, 0.3477],
    [0.22063, 0.2218, 0.54, 0.7778],
    [0.8421, 0.199, 0.57, 0.4333],
    [0.36842105, 0.545, 0.386, 0.155567],
    [0.62281, 0.23394, 0.46, 0.36667]
]
index_1 = ['1', '2', '4', '5']
index_2 = ['Recall', 'Precision', 'F1']
iterables = [index_1, index_2]
index = pd.MultiIndex.from_product(iterables, names=["ClusterID", "Metric"])
df = pd.DataFrame(values, columns=['Method1', 'Method2', 'Method3', 'Method4'], index=index)

# 自定义指标-颜色映射 可根据汇报需求自行修改色值
metric_color = {
    'Recall': 'red',
    'Precision': 'yellow',
    'F1': 'black'
}

plot_data = df.unstack(level=0)
# 先绘图 不指定颜色
axs = plot_data.plot(
    kind='bar',
    subplots=True,
    rot=0,
    figsize=(20, 18),
    layout=(4, 4)
)

# 遍历所有子图 给对应指标的柱子设置固定颜色
metrics = plot_data.index.tolist()
for row in axs:
    for ax in row:
        if not ax.has_data():
            continue
        # 子图内柱子顺序和metrics顺序完全一致 按索引匹配即可
        for i, bar_group in enumerate(ax.containers):
            current_metric = metrics[i]
            for bar in bar_group:
                bar.set_color(metric_color[current_metric])

# 统一设置坐标轴范围 原0.8上限会截断0.813、0.86的高值柱子,调整为0.9更合适
plt.setp(axs, ylim=(0.0, 0.9))
plt.tight_layout(pad=0.6, w_pad=0.6, h_pad=1.0)
plt.show()

调整说明

  • 颜色映射直接修改metric_color字典即可,支持十六进制色值、RGB元组、matplotlib内置颜色名等所有合法颜色格式
  • 如果需要显示图例,可以在plot()参数里加legend=True,再统一给图例设置对应颜色标签即可
  • 子图标题、坐标轴标签可以根据汇报需求在遍历子图时通过ax.set_title()、ax.set_xlabel()等方法自定义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:48:30