基于Seaborn优化DataFrame堆叠条形图:提升百分比显示清晰度
问题描述
我有一个包含FCode和各年份数值的DataFrame,目前用Matplotlib绘制堆叠水平条形图,虽然手动计算添加了百分比标签,但可视化效果差,百分比不够突出清晰。想改用Seaborn实现更优的可视化效果,求实现代码。
数据示例
FCode 2017 2018 2019 2020 2021 3 HCPL1 2 85 207 190. 324 0 HCPL2 431 591 724 537 1025 2 HCPL3 59 202 372 422 679 1 HCPL4 188 201 282 322 557
当前Matplotlib代码
plt.rcParams["figure.figsize"] = (25,10) Test.plot( x = 'FunderCode', kind = 'barh', stacked = True, title = 'Stacked Bar Graph', mark_right = True) Test_total = Test["Count_2017"] + Test["Count_2018"] +Test["Count_2019"] + Test["Count_2020"]+ Test["Count_2021"] Test_rel = Test[Test.columns[1:]].div(Test_total, 0) * 100 for n in Test_rel: for i, (cs, ab, pc) in enumerate(zip(Test.iloc[:, 1:].cumsum(1)[n], Test[n], Test_rel[n])): plt.text(cs - ab / 2, i, str(np.round(pc, 1)) + '%', va = 'center', ha = 'center', rotation = 20, fontsize = 8)
解决方案:Seaborn实现优化的堆叠水平条形图
Seaborn更适配长格式数据,因此先将宽格式DataFrame重塑为长格式,再计算每个类别占对应行的百分比,最后绘制堆叠条形图并添加清晰的百分比标签。
完整代码
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import numpy as np # 构造数据 data = { 'FCode': ['HCPL1', 'HCPL2', 'HCPL3', 'HCPL4'], '2017': [2, 431, 59, 188], '2018': [85, 591, 202, 201], '2019': [207, 724, 372, 282], '2020': [190, 537, 422, 322], '2021': [324, 1025, 679, 557] } Test = pd.DataFrame(data) # 1. 将宽格式转为长格式 df_long = Test.melt(id_vars='FCode', var_name='Year', value_name='Value') # 2. 计算每个FCode的总和及对应年份值的百分比 df_long['Total'] = df_long.groupby('FCode')['Value'].transform('sum') df_long['Percentage'] = (df_long['Value'] / df_long['Total']) * 100 # 3. 设置绘图风格与尺寸 sns.set_style("whitegrid") plt.figure(figsize=(20, 8)) # 4. 绘制堆叠水平条形图 ax = sns.barplot( data=df_long, y='FCode', x='Value', hue='Year', palette='viridis', orient='h' ) # 5. 添加清晰的百分比标签 for p in ax.patches: width = p.get_width() if width == 0: continue y_pos = p.get_y() + p.get_height() / 2 # 匹配对应FCode和年份的百分比 fcode = ax.get_yticklabels()[int(y_pos // 1)].get_text() target_row = df_long[(df_long['FCode'] == fcode) & (df_long['Value'] == width)] percentage = target_row['Percentage'].values[0] # 绘制标签 ax.text( width / 2, y_pos, f'{np.round(percentage, 1)}%', ha='center', va='center', fontsize=10, fontweight='bold', color='white' ) # 6. 优化图表外观 ax.set_title('各FCode年度数值占比堆叠条形图', fontsize=16, pad=20) ax.set_xlabel('数值', fontsize=12) ax.set_ylabel('FCode', fontsize=12) plt.legend(title='年份', bbox_to_anchor=(1.05, 1), loc='upper left') sns.despine(left=True, bottom=True) plt.tight_layout() plt.show()
核心优化点
- 数据格式转换:用
melt将宽格式转为Seaborn友好的长格式,便于分组处理。 - 标签可读性提升:将百分比标签用白色粗体字显示在条形中心,避免旋转,视觉更突出。
- 视觉风格优化:使用
viridis调色板,配合白色网格和去边框处理,提升整体美观度。
内容的提问来源于stack exchange,提问作者GGT
相关产品推荐
相关产品推荐

