如何为水平条形图的每个条形右侧标注计数及百分比数据

原有实现说明
当前代码仅支持在水平条形右侧标注计数,需要调整为同时展示计数和对应的百分比,原有实现代码如下:
import pandas as pd import matplotlib.pyplot as plt age = ['0-17','18-60','61-80'] df3 = pd.DataFrame(data={'Male':[82,550,25], 'Female':[72,309,7]}, index=age) print(df3) ax = df3.plot(kind='barh', ylabel='Age', title='Passenger Count by Age and Sex') ax.set(xlabel='No. of Passengers') for c in ax.containers: # set the bar label ax.bar_label(c, fmt='%.0f', label_type='edge') ax.legend(title='Sex', bbox_to_anchor=(1, 1.02), loc='upper left') ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) plt.show()
解决方法
调整bar_label的传参逻辑,手动生成包含计数+百分比的自定义标签即可,修改后的完整代码如下:
import pandas as pd import matplotlib.pyplot as plt age = ['0-17','18-60','61-80'] df3 = pd.DataFrame(data={'Male':[82,550,25], 'Female':[72,309,7]}, index=age) print(df3) # 计算总乘客数,作为百分比计算基准 total_pass = df3.sum().sum() ax = df3.plot(kind='barh', ylabel='Age', title='Passenger Count by Age and Sex') ax.set(xlabel='No. of Passengers') for c in ax.containers: # 生成自定义标签:计数 + 百分比(保留1位小数) labels = [f'{w:.0f} ({w/total_pass*100:.1f}%)' for w in [v.get_width() for v in c]] ax.bar_label(c, labels=labels, label_type='edge', padding=2) ax.legend(title='Sex', bbox_to_anchor=(1, 1.02), loc='upper left') ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) # 自动调整画布布局,避免标签、图例被截断 plt.tight_layout() plt.show()
可选调整说明
- 如果需要百分比为对应年龄组的内部占比,只需将百分比计算逻辑修改为按行求和即可
- 调整
padding参数可以修改标签与条形边缘的间距,避免文字重叠 - 调整标签内的格式符(比如将
.1f改为.0f)可以修改百分比的小数位数
内容的提问来源于stack exchange,提问作者Miguel Logan
相关产品推荐
相关产品推荐

