Pandas绘图:在X轴展示多层索引标签并添加条形值标签
解决方案
核心修改点
针对你的需求,主要做了两处关键调整:实现X轴双标签(forecast + year)展示、给条形添加顶部观测值标签,同时优化了子图布局样式。
1. 规整多层索引结构
先确保你的DataFrame以forecast为第一层索引,year为第二层索引,这样每个子图对应一个forecast分组:
df_par_trans = df.set_index(['forecast', 'year'])
2. 重写绘图函数实现双X轴标签
在绘图函数中替换原X轴刻度逻辑,用文本标注实现双层标签:
- 清空默认X轴刻度,在每个条形下方居中位置添加
forecast主标签 - 在主标签下方添加
year次级标签(灰色小字体) - 移除原X轴标题,改用子图标题展示当前
forecast值
3. 添加条形顶部的观测值标签
遍历每个条形,在其顶部居中位置添加most important observation列的内容,通过Y轴偏移量避免标签与条形重叠。
4. 优化布局与样式
- 统一隐藏刻度线,保持图表简洁
- 增加底部边距,避免次级X轴标签被截断
- 共享Y轴保证子图数据的可比性
完整代码
import pandas as pd import matplotlib.pyplot as plt # 构造示例数据 data = { 'year': [2020, 2050, 2099, 2020, 2050, 2099], 'forecast': ['PV6SM', 'PV6SM', 'PV6SM', 'PV3S', 'PV3S', 'PV3S'], 'most important observation': ['Harkins', 'Harkins', 'Harkins', 'PV3S', 'PV3S', 'PV3S'], 'percent increase when left out': [17.371021, 10.569719, 12.343476, 34.095863, 32.565513, 26.110555] } df = pd.DataFrame(data) df_par_trans = df.set_index(['forecast', 'year']) def plot_function(forecast, ax): sub_df = df_par_trans.xs(forecast) # 绘制条形图 bars = sub_df['percent increase when left out'].plot(kind='bar', ax=ax, legend=False) # 设置子图标题为当前forecast ax.set_title(forecast, weight='bold') # 获取X轴位置和对应的year值 x_ticks = ax.get_xticks() years = sub_df.index.tolist() # 清空原X轴标签和标题 ax.set_xticklabels([]) ax.set_xlabel('') # 添加双X轴标签:forecast在上,year在下 y_bottom = ax.get_ylim()[0] y_range = ax.get_ylim()[1] - y_bottom for x, year in zip(x_ticks, years): # 主标签:forecast ax.text(x, y_bottom - y_range*0.05, forecast, ha='center', fontsize=10) # 次级标签:year(灰色小字体) ax.text(x, y_bottom - y_range*0.1, str(year), ha='center', fontsize=8, color='#666666') # 添加条形上方的观测值标签 for bar, obs in zip(bars.patches, sub_df['most important observation']): height = bar.get_height() ax.text(bar.get_x() + bar.get_width()/2., height + y_range*0.01, obs, ha='center', va='bottom', fontsize=9) return bars # 创建子图 n_subplots = len(df_par_trans.index.levels[0]) fig, axes = plt.subplots(nrows=1, ncols=n_subplots, sharey=True, figsize=(14, 8)) # 映射forecast到对应轴并绘图 for forecast, ax in zip(df_par_trans.index.levels[0], axes): plot_function(forecast, ax) # 设置Y轴标签 axes[0].set_ylabel('Percent Increase When Left Out', fontsize=11) # 隐藏所有刻度线 for ax in axes: ax.tick_params(axis='both', which='both', length=0) # 调整布局,避免标签被截断 fig.subplots_adjust(wspace=0.3, bottom=0.2) plt.show()
效果说明
- 每个子图对应一个
forecast分组,X轴每个位置显示forecast主标签,下方展示对应的year次级标签 - 每个条形顶部显示
most important observation列的内容 - 共享Y轴保证不同子图数据的可比性,整体布局简洁美观
内容的提问来源于stack exchange,提问作者user11958450
相关产品推荐
相关产品推荐

