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

如何绘制按类别分组的两列平均值分组条形图?

解决方案:实现同类别条形同色的分组均值条形图

针对你的需求——让每个类别(Column1)对应的两个均值条形(Column2、Column3)颜色一致,且不同类别颜色唯一,下面提供两种可行方案:

方案1:用Matplotlib手动绘制(精准控制颜色)

这种方式直接基于聚合后的均值数据绘图,能完全掌控每个条形的颜色:

import matplotlib.pyplot as plt
import pandas as pd

# 加载并预处理数据
data = [    
    ['Bananas', 1, 5],
    ['Apple', 4, 2],
    ['Bananas', 2, 5],
    ['Oranges', 3, 6],
    ['Apple', 4, 2],
    ['Apple', 2, 5],
    ['Oranges', 1, 2],
    ['Apple', 5, 5],
    ['Oranges', 6, 1]
]
df = pd.DataFrame(data, columns=['Column1', 'Column2', 'Column3'])
df[['Column2', 'Column3']] = df[['Column2', 'Column3']].astype(float)

# 计算每个类别下的均值
mean_df = df.groupby('Column1')[['Column2', 'Column3']].mean().reset_index()

# 为每个类别分配唯一颜色(可自行替换为你喜欢的色值)
category_colors = {
    'Bananas': '#f7931e',
    'Apple': '#5ac8fa',
    'Oranges': '#8bc34a'
}

bar_width = 0.35
categories = mean_df['Column1']
x_pos = range(len(categories))

plt.figure(figsize=(10, 6))

# 绘制Column2的条形,颜色对应所属类别
bars_col2 = plt.bar([x - bar_width/2 for x in x_pos], 
                    mean_df['Column2'], 
                    width=bar_width, 
                    color=[category_colors[cat] for cat in categories])
# 绘制Column3的条形,颜色与同类别Column2一致
bars_col3 = plt.bar([x + bar_width/2 for x in x_pos], 
                    mean_df['Column3'], 
                    width=bar_width, 
                    color=[category_colors[cat] for cat in categories])

# 添加数值标签
for bar in bars_col2:
    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height(),
             f'{bar.get_height():.2f}', ha='center', va='bottom', fontsize=12)
for bar in bars_col3:
    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height(),
             f'{bar.get_height():.2f}', ha='center', va='bottom', fontsize=12)

# 调整坐标轴与标题
plt.xticks(x_pos, categories, fontsize=14)
plt.yticks(fontsize=12)
plt.xlabel('类别', fontsize=14)
plt.ylabel('平均值', fontsize=14)
plt.title('各类别Column2/Column3平均值分组条形图', fontsize=16)

# 添加图例(可选,用于区分两列数据)
plt.legend([bars_col2[0], bars_col3[0]], ['Column2', 'Column3'], fontsize=12)

plt.tight_layout()
plt.show()

方案2:基于你现有的Seaborn+Melt代码修改

如果你想继续使用已有的数据融合(melt)逻辑,只需为每个数据行匹配对应类别的颜色即可:

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

data = [    
    ['Bananas', 1, 5],
    ['Apple', 4, 2],
    ['Bananas', 2, 5],
    ['Oranges', 3, 6],
    ['Apple', 4, 2],
    ['Apple', 2, 5],
    ['Oranges', 1, 2],
    ['Apple', 5, 5],
    ['Oranges', 6, 1]
]
df = pd.DataFrame(data, columns=['Column1', 'Column2', 'Column3'])
df[['Column2', 'Column3']] = df[['Column2', 'Column3']].astype(float)

# 数据融合
dfm = df.melt(id_vars=["Column1"], var_name="Test1", value_name="Test2")

# 定义类别颜色映射
category_colors = {
    'Bananas': '#f7931e',
    'Apple': '#5ac8fa',
    'Oranges': '#8bc34a'
}

# 为每一行分配对应类别的颜色
color_list = [category_colors[row['Column1']] for _, row in dfm.iterrows()]

plt.figure(figsize=(10, 6))
p = sns.barplot(data=dfm, x="Column1", y="Test2", hue="Test1", 
                palette=color_list, errorbar=('ci', False))

# 隐藏默认图例(若不需要区分Column2/Column3)
plt.legend([], [], frameon=False)

# 添加数值标签
for container in p.containers:
    plt.bar_label(container, fmt='%.2f', label_type='edge', padding=1, fontsize=12)

# 调整样式
plt.xticks(fontsize=14)
plt.yticks(fontsize=12)
plt.xlabel('类别', fontsize=14)
plt.ylabel('平均值', fontsize=14)
plt.title('各类别Column2/Column3平均值分组条形图', fontsize=16)

plt.tight_layout()
plt.show()

关键说明

你之前的代码无法实现需求的原因是:Seaborn默认会为hue参数(即你的Test1,对应Column2和Column3)的不同取值分配颜色,而非按Column1的类别分配。通过上述两种方式,我们将颜色映射绑定到Column1的类别,从而实现同一类别下的两个条形颜色一致,不同类别颜色唯一的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:25:18