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

Matplotlib不平衡数据集堆叠柱状图:小堆叠百分比标签优化求助

解决Matplotlib堆叠柱状图小区域标签拥挤问题

基于大规模不平衡数据集绘制堆叠柱状图,需要为每个堆叠添加百分比标签,但堆叠区域过小时标签显示杂乱拥挤。数据集为动态数据无法修改,尝试用matplotlib.text调整未解决问题,原实现代码如下:

def plot_stack_bar(plot_df, xlabel, ylabel, title):
    
    plot_df_percent=pd.DataFrame()
    cols = list(plot_df)
    plot_df_percent[cols] = plot_df[cols].div( plot_df[cols].sum(axis=1), axis=0 )
    
    plot_df.plot(kind='bar', stacked=True, figsize=(20, 17))
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    plt.title(title)


    for n, x in enumerate([*plot_df.index.values]):
        i=0
        for (proportion, y_loc) in zip(plot_df_percent.loc[x],
                                       plot_df_percent.loc[x].cumsum()):
           
            y_loc = plot_df.iloc[n,I] / 2 + plot_df.iloc[n,:i].sum()
            plt.text(x=n-0.17,
                     y=y_loc,
                     s=f'{np.round(proportion * 100, 1)}%', 
                     color="black",
                     fontsize=12,
                     fontweight="bold")
            i=i+1
    plt.savefig(f'draft/{title}.png')        
    plt.show()

解决思路

  • 过滤极小占比标签:设置占比阈值(如1%),占比低于阈值的标签直接不显示,从根源避免小区域标签拥挤
  • 动态调整字体大小:根据占比大小自动缩小小占比标签的字号,既保留关键信息又减少空间占用
  • 修正标签位置计算:修复原代码中变量大小写错误(I改为i),确保标签始终落在堆叠区域的垂直中心
  • 可选优化柱子宽度:绘制柱状图时指定width参数缩小柱子宽度,给标签预留更多横向空间

修改后的代码

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

def plot_stack_bar(plot_df, xlabel, ylabel, title, label_threshold=1):
    # 计算各堆叠的百分比
    cols = plot_df.columns
    plot_df_percent = plot_df[cols].div(plot_df[cols].sum(axis=1), axis=0)
    
    # 绘制堆叠柱状图,可选调整柱子宽度
    ax = plot_df.plot(kind='bar', stacked=True, figsize=(20, 17), width=0.8)
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    plt.title(title)

    # 遍历每个柱子和堆叠层
    for n, x in enumerate(plot_df.index.values):
        cumulative_sum = 0
        for i, (col, proportion) in enumerate(zip(cols, plot_df_percent.loc[x])):
            current_value = plot_df.iloc[n, i]
            # 计算标签垂直位置:当前堆叠的中心
            y_loc = cumulative_sum + current_value / 2
            # 计算百分比数值
            percent = np.round(proportion * 100, 1)
            
            # 仅显示占比超过阈值的标签
            if percent >= label_threshold:
                # 根据占比动态调整字体大小,最小保证8号字可读性
                font_size = max(8, 12 - int((10 - percent) * 0.4))
                plt.text(
                    x=n - 0.17,
                    y=y_loc,
                    s=f'{percent}%', 
                    color="black",
                    fontsize=font_size,
                    fontweight="bold"
                )
            cumulative_sum += current_value

    plt.savefig(f'draft/{title}.png')        
    plt.show()

代码关键说明

  • label_threshold为可自定义参数,可根据数据集情况调整(比如设为0.5显示更低占比的标签)
  • 字体大小随占比动态变化,避免小区域标签过大占用空间
  • 用cumulative_sum替代原代码的切片求和,计算更高效且逻辑更清晰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:20:31