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

如何用Matplotlib/Seaborn绘制并排的两组堆叠直方图

在同一图表中绘制并排堆叠直方图(Matplotlib & Seaborn)

Matplotlib 实现方法

你说得对,Matplotlib 没有直接的"一键式"函数生成并排堆叠直方图,但我们可以通过positions参数调整每组堆叠柱的位置,避免手动计算所有条形的高度,这应该是最接近原生支持的方式了。

核心思路是:

  • 先计算每个bin的中心位置,然后给两组堆叠柱分别设置左右偏移,让它们在同一个bin区间内并排显示
  • 通过rwidth控制每组堆叠柱的宽度,确保两组之间留有空隙

下面是完整代码示例:

import matplotlib.pyplot as plt
import numpy as np

# 模拟你的数据(替换成你自己的correct_a、incorrect_a等)
np.random.seed(42)
correct_a = np.random.normal(5, 1, 100)
incorrect_a = np.random.normal(7, 1, 50)
correct_b = np.random.normal(5.5, 1, 120)
incorrect_b = np.random.normal(6.5, 1, 60)

# 共用的bin edges(和你原代码一致)
edges = np.linspace(2, 10, 9)
bin_width = edges[1] - edges[0]
bin_centers = (edges[:-1] + edges[1:]) / 2  # 每个bin的中心位置
offset = bin_width * 0.25  # 左右偏移量,确保两组柱不重叠

# 绘制第一组堆叠柱(A组),向左偏移
plt.hist([correct_a, incorrect_a], bins=edges, stacked=True, 
         color=['green', 'red'], rwidth=0.4, alpha=0.7,
         label=['Correct A', 'Incorrect A'],
         positions=bin_centers - offset)

# 绘制第二组堆叠柱(B组),向右偏移
plt.hist([correct_b, incorrect_b], bins=edges, stacked=True, 
         color=['blue', 'orange'], rwidth=0.4, alpha=0.7,
         label=['Correct B', 'Incorrect B'],
         positions=bin_centers + offset)

# 美化图表
plt.xlabel('数值')
plt.ylabel('计数')
plt.legend()
plt.title('并排堆叠直方图(Matplotlib)')
plt.show()

Seaborn 实现方法

Seaborn 目前确实没有原生支持这种并排堆叠直方图的函数,但我们可以通过预处理数据、计算bin内的计数,再用条形图来实现。步骤如下:

  1. 将所有数据整理成长格式的DataFrame
  2. 用pd.cut给每个数据点分配对应的bin
  3. 分组统计每个bin、每组、每个类型的计数
  4. 用bar函数绘制堆叠的并排条形

代码示例:

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

# 模拟数据(替换成你的真实数据)
np.random.seed(42)
correct_a = np.random.normal(5, 1, 100)
incorrect_a = np.random.normal(7, 1, 50)
correct_b = np.random.normal(5.5, 1, 120)
incorrect_b = np.random.normal(6.5, 1, 60)

# 整理成长格式DataFrame
df_a = pd.DataFrame({
    'value': np.concatenate([correct_a, incorrect_a]),
    'type': ['Correct']*len(correct_a) + ['Incorrect']*len(incorrect_a),
    'group': 'A'
})
df_b = pd.DataFrame({
    'value': np.concatenate([correct_b, incorrect_b]),
    'type': ['Correct']*len(correct_b) + ['Incorrect']*len(incorrect_b),
    'group': 'B'
})
df = pd.concat([df_a, df_b])

# 定义bin edges并分配每个数据点的bin
edges = np.linspace(2, 10, 9)
bin_width = edges[1] - edges[0]
bin_centers = (edges[:-1] + edges[1:]) / 2
df['bin'] = pd.cut(df['value'], bins=edges, labels=bin_centers)

# 统计每个bin、group、type的计数
counts = df.groupby(['bin', 'group', 'type']).size().unstack('type').fillna(0).astype(int)

# 绘制并排堆叠条形图
bar_width = bin_width * 0.4
x = np.arange(len(bin_centers))
fig, ax = plt.subplots()

# 绘制A组堆叠柱
ax.bar(x - bar_width/2, counts.loc[:, ('A', 'Correct')], 
       width=bar_width, color='green', alpha=0.7, label='Correct A')
ax.bar(x - bar_width/2, counts.loc[:, ('A', 'Incorrect')], 
       width=bar_width, bottom=counts.loc[:, ('A', 'Correct')], 
       color='red', alpha=0.7, label='Incorrect A')

# 绘制B组堆叠柱
ax.bar(x + bar_width/2, counts.loc[:, ('B', 'Correct')], 
       width=bar_width, color='blue', alpha=0.7, label='Correct B')
ax.bar(x + bar_width/2, counts.loc[:, ('B', 'Incorrect')], 
       width=bar_width, bottom=counts.loc[:, ('B', 'Correct')], 
       color='orange', alpha=0.7, label='Incorrect B')

# 设置x轴刻度
ax.set_xticks(x)
ax.set_xticklabels(bin_centers.round(1))
ax.set_xlabel('数值')
ax.set_ylabel('计数')
ax.legend()
plt.title('并排堆叠直方图(Seaborn)')
plt.show()

这样就能实现你想要的效果:每个bin旁分别展示一组绿/红堆叠柱和一组蓝/橙堆叠柱啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:37:33