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

如何为Seaborn水平条形图的每个FacetGrid分面添加百分比标签?

解决Seaborn Facet Grid水平条形图百分比标签显示问题

你当前代码的百分比标签计算逻辑存在错误:用整个数据集的行数len(df['pct'])作为分母计算比例,完全不符合每个分组内的占比需求。另外你已经提前计算好了pct列(每个level在对应survey中的百分比),无需重新计算,直接使用条形的宽度值即可。

以下是修正后的完整代码:

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

data = {
'id': [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20],
'survey': ['baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline', 'baseline', 'endline'],
'level': ['low', 'high', 'medium', 'low', 'high', 'medium', 'medium', 'high', 'low', 'low', 'medium', 'high', 'low', 'medium', 'low', 'high', 'low', 'low', 'medium', 'high', 'high', 'high', 'high', 'medium', 'low', 'low', 'medium', 'high', 'low', 'medium', 'high', 'medium', 'low', 'high', 'high', 'medium', 'medium', 'low', 'high', 'low']
}

df = pd.DataFrame(data)

# 简化数据预处理,直接计算每个survey分组内的百分比
df = df.groupby(["survey", "level"])['id'].count().rename('count').reset_index()
df['pct'] = df.groupby('survey')['count'].transform(lambda x: (x / x.sum()) * 100)

# 创建Facet Grid
g = sns.FacetGrid(df, col="survey")
g.map_dataframe(sns.barplot, x='pct', y='level', hue='level', palette='Set1', orient='h')
g.set_axis_labels('Percentage', 'Level') 
g.set_titles(col_template='{col_name} survey')

# 修正后的注释函数
def annotate_bars(ax, data, **kwargs):
    for p in ax.patches:
        # 直接使用条形的宽度(即pct值)作为百分比
        percentage = f'{p.get_width():.1f}%'
        # 调整标签位置,避免重叠
        x = p.get_width() + 1
        y = p.get_y() + p.get_height() / 2
        ax.annotate(percentage, (x, y), fontsize=8, color='k')

g.map_dataframe(annotate_bars)

plt.show()

关键修改点:

  • 简化数据预处理:用transform直接计算每个survey分组内的百分比,避免手动循环拼接列表,代码更简洁可靠。
  • 修正注释逻辑:不再错误使用整个数据集的行数,直接利用条形的宽度值(已提前计算好的百分比)生成标签;调整x轴偏移量,让标签显示更合理。
  • 匹配子图数据:使用map_dataframe传递子图对应的数据,确保每个子图的注释逻辑对应自身的数据集。

修改后,每个水平条形图右侧会正确显示对应level在当前survey中的占比百分比。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:35:22