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

如何将Seaborn多分类变量countplot转换为百分比展示

好问题!确实,把countplot的计数换成百分比的话,barplot是非常合适的方案——毕竟countplot本身就是barplot的一个特例,只是自动帮你计算了计数而已。我们只需要提前算出百分比,再传给barplot就能实现需求,而且完全可以通过循环批量生成这类图表。

为什么选择barplot?

countplot的核心是自动统计分类变量的频数,但它没有直接支持将y轴切换为百分比的参数。而barplot允许我们自定义y轴的数据,刚好可以把提前计算好的百分比传进去,灵活度更高,完全匹配你的需求。

批量生成百分比barplot的实现方案

我们可以借助pandas先计算每个分类变量下(按Response分组)的百分比,再在循环里调用barplot绘图。这里提供两种常用的百分比计算方式,以及对应的完整循环代码:

方式1:用crosstab计算百分比

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

# 初始化绘图风格
sns.set_style("whitegrid")

for i, col in enumerate(df_categorical.columns):
    # 计算每个分类类别下,不同Response的占比(按分类类别归一化,总和为100%)
    cross_tab = pd.crosstab(df_categorical[col], df_categorical['Response'], normalize='index') * 100
    # 转成长格式,适配seaborn的barplot输入格式
    cross_tab_long = cross_tab.reset_index().melt(id_vars=col, var_name='Response', value_name='Percentage')
    
    # 创建画布
    plt.figure(i, figsize=(10, 6))
    # 绘制百分比柱状图
    sns.barplot(x=col, y='Percentage', hue='Response', data=cross_tab_long)
    
    # 美化图表
    plt.title(f'Response Distribution by {col} (Percentage)', fontsize=14)
    plt.ylabel('Percentage (%)', fontsize=12)
    plt.xlabel(col, fontsize=12)
    plt.xticks(rotation=45)  # 避免x轴标签重叠
    
    # 在每个柱子上添加百分比数值标签
    for p in plt.gca().patches:
        height = p.get_height()
        plt.gca().text(p.get_x() + p.get_width()/2., height + 0.5,
                       f'{height:.1f}%',
                       ha='center', va='bottom')
    
    plt.tight_layout()

方式2:用groupby计算百分比

如果你更习惯groupby的逻辑,也可以用下面的方式计算百分比:

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

sns.set_style("whitegrid")

for i, col in enumerate(df_categorical.columns):
    # 按分类变量和Response分组,计算占比并转成DataFrame
    percent_df = df_categorical.groupby(col)['Response'].value_counts(normalize=True)\
                              .mul(100)\
                              .rename('Percentage')\
                              .reset_index()
    
    plt.figure(i, figsize=(10, 6))
    sns.barplot(x=col, y='Percentage', hue='Response', data=percent_df)
    
    # 同样的美化逻辑
    plt.title(f'Response Distribution by {col} (Percentage)', fontsize=14)
    plt.ylabel('Percentage (%)', fontsize=12)
    plt.xlabel(col, fontsize=12)
    plt.xticks(rotation=45)
    
    for p in plt.gca().patches:
        height = p.get_height()
        plt.gca().text(p.get_x() + p.get_width()/2., height + 0.5,
                       f'{height:.1f}%',
                       ha='center', va='bottom')
    
    plt.tight_layout()

补充说明

  • 上面的代码是基于你原有的循环逻辑修改的,保留了批量处理所有分类变量的特性;
  • 两种计算方式的结果一致,选你习惯的即可;
  • 如果不需要按Response分组,只想看每个分类变量自身的占比,去掉hue参数,直接计算df_categorical[col].value_counts(normalize=True)*100即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:36:09