遍历barplot容器元素时部分标签缺失(endline无N值)求助
解决Seaborn条形图中Endline标签缺失N值的问题
问题原因
你的代码中,ax.containers对应每个level分组的条形容器(共3个:low、medium、high),每个容器包含两个条形(baseline和endline)。但你通过pd.DataFrame(N['id']).to_numpy()得到的是6个独立的id值(每个survey+level组合对应一个),和容器数量不匹配,导致每个容器只能获取第一个id值,第二个条形(endline)没有对应的N数据,最终标签缺失。
修正方案
重新组织N的id数据,按level分组,让每个分组对应该level下baseline和endline的两个id计数,再和容器一一匹配:
完整修正代码
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt from matplotlib.ticker import PercentFormatter 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, 21, 21, 22, 22], "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', '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', 'low', 'low', 'low', 'low'] } df = pd.DataFrame(data) N = df.groupby(['survey', 'level']).count().sort_index(ascending = True).reset_index() N['%'] = 100 * N['id'] / N.groupby('survey')['id'].transform('sum') sns.set_style('white') ax = sns.barplot(data = N, x = 'survey', y = '%', ci = None, palette="rainbow", hue = 'level') # 关键修正:按level分组提取对应baseline和endline的id计数 id_groups = N.groupby('level')['id'].apply(list).tolist() labels = [ [f'{pct:.1f}% $(N={_n})$' for pct, _n in zip(c.datavalues, ids)] for c, ids in zip(ax.containers, id_groups) ] for container, label in zip(ax.containers, labels): ax.bar_label(container, label, fontsize = 10) sns.despine(ax = ax, left = True) ax.grid(True, axis = 'y') ax.yaxis.set_major_formatter(PercentFormatter(100)) ax.set_xlabel('') ax.set_ylabel('') plt.tight_layout() plt.legend(bbox_to_anchor = (1.02, 1), loc = 'upper left', borderaxespad=0) plt.show()
核心修改说明
N.groupby('level')['id'].apply(list)会将每个level对应的baseline、endline计数打包成列表,比如low对应的列表是[baseline_low_count, endline_low_count],正好匹配每个容器中的两个条形。- 这样每个容器能获取到对应的两个N值,生成完整的百分比+N标签,解决endline标签缺失的问题。
内容的提问来源于stack exchange,提问作者Stephen Okiya
相关产品推荐
相关产品推荐

