如何为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
相关产品推荐
相关产品推荐

