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

如何绘制两个不重叠的100%堆叠条形图?Seaborn使用问题

解决堆叠条形图重叠及异常图形问题

问题根源

  1. 原代码使用累计百分比(percent_cum)绘制,导致后续条形覆盖前序条形;指定y参数后,每个条形都从0延伸到累计值,最终出现块状异常。
  2. 拆分多个小数据框绘制,既繁琐又容易出现轴对齐偏差。
  3. 未指定统一的ax参数,默认每次创建新坐标轴,直接导致图形重叠。

修正步骤

1. 调整数据结构:计算相对百分比(而非累计)

堆叠条形图需要每个类别单独的占比,而非累计值。先转换数据格式,再合并两个数据集并增加分组标识:

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

# 计算每个类别的相对占比(从累计值转换)
dfInd = pd.DataFrame({
    'Winner': ['Dog', 'Cat', 'Neither'],
    'percent': [13, 48-13, 100-48],  # Dog:13, Cat:35, Neither:52
    'Group': ['Individual', 'Individual', 'Individual']
})

dfGen = pd.DataFrame({
    'Winner': ['Dog', 'Cat', 'Neither'],
    'percent': [20, 53-20, 100-53],  # Dog:20, Cat:33, Neither:47
    'Group': ['General', 'General', 'General']
})

# 合并为统一数据集
df = pd.concat([dfInd, dfGen], ignore_index=True)

2. 正确绘制堆叠条形图

利用seaborn.barplot的bottom参数实现堆叠,同时指定y="Group"区分两个条形的Y轴位置,所有绘图统一使用同一个坐标轴:

sns.set_theme(style="whitegrid")
f, ax = plt.subplots(figsize=(10, 6))

# 定义类别颜色映射
color_map = {'Dog': '#756bb1', 'Cat': '#bcbddc', 'Neither': '#efedf5'}

# 按顺序绘制每个堆叠层
for winner in ['Dog', 'Cat', 'Neither']:
    # 计算当前层的底部位置(前序所有类别占比的累计和)
    prev_winners = ['Dog', 'Cat'][:list(color_map.keys()).index(winner)]
    bottom = df[df['Winner'].isin(prev_winners)].groupby('Group')['percent'].sum().reindex(['Individual', 'General'], fill_value=0)
    
    # 绘制当前层
    sns.barplot(
        x='percent',
        y='Group',
        data=df[df['Winner'] == winner],
        color=color_map[winner],
        ax=ax,
        bottom=bottom.values
    )

# 美化图表
ax.set_xlabel('Percentage')
ax.set_ylabel('')
ax.set_title('100% Stacked Bar Chart')
handles = [plt.Rectangle((0,0),1,1, color=color_map[w]) for w in color_map]
ax.legend(handles, color_map.keys(), title='Winner')

plt.tight_layout()
plt.show()

3. 关键说明

  • 相对百分比:必须将累计值转换为每个类别的单独占比,堆叠后才能准确达到100%。
  • bottom参数:指定当前条形的底部位置为前序类别占比的总和,是实现堆叠效果的核心。
  • 统一坐标轴:所有绘图指定同一个ax,避免多轴重叠问题。

更简洁的替代方案(使用matplotlib原生绘制)

如果不需要seaborn的样式,直接用matplotlib的堆叠条形图功能会更高效:

import pandas as pd
import matplotlib.pyplot as plt

# 转换为宽格式数据,适配matplotlib堆叠需求
df_wide = pd.DataFrame({
    'Group': ['Individual', 'General'],
    'Dog': [13, 20],
    'Cat': [35, 33],
    'Neither': [52, 47]
})

colors = ['#756bb1', '#bcbddc', '#efedf5']
ax = df_wide.set_index('Group').plot(kind='barh', stacked=True, color=colors, figsize=(10,6))

ax.set_xlabel('Percentage')
ax.set_title('100% Stacked Bar Chart')
plt.legend(title='Winner')
plt.tight_layout()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:33:33