Matplotlib多类型图表末尾值标注及代码优化求助
解决方案:图表末尾标注实现与代码优化
一、末尾数据标注实现(按图表类型适配)
针对不同图表类型,封装统一的标注函数,解决ax.annotate使用问题:
1. 折线图
取每条线的最后一个数据点,通过偏移量调整标注位置,避免遮挡线条
2. 垂直柱状/堆叠柱状图
- 普通柱状:直接取柱子顶部高度作为标注值
- 堆叠柱状:累加同组内前序柱子的高度,得到当前堆叠层的顶部值
3. 水平柱状/堆叠水平柱状图
- 普通水平柱状:取柱子右端宽度作为标注值
- 堆叠水平柱状:累加同组内前序柱子的宽度,得到当前堆叠层的右端值
二、代码优化方案
1. 模块化封装
将绘图、标注、样式设置拆分为独立函数,避免重复代码,120张图表只需调用统一接口
2. 全局样式统一
通过matplotlib.rcParams一次性配置所有图表的字体、尺寸、颜色等样式,无需逐个设置
3. 日期字符串标准化
用pandas.to_datetime统一解析日期,strftime格式化输出,避免重复处理逻辑
示例代码
import matplotlib.pyplot as plt import pandas as pd import numpy as np # 全局样式统一配置(适配中文、统一尺寸) plt.rcParams.update({ 'font.family': 'SimHei', 'axes.unicode_minus': False, 'figure.figsize': (12, 6), 'font.size': 12, 'axes.titlepad': 15 }) def annotate_last_point(ax, chart_type, data, offset=5): """为图表标注末尾数据值""" if chart_type == 'line': # 折线图标注 for line in ax.lines: x_last = line.get_xdata()[-1] y_last = line.get_ydata()[-1] ax.annotate(f'{y_last:.2f}', (x_last, y_last), xytext=(offset, offset), textcoords='offset points') elif chart_type in ['bar', 'stacked_bar']: # 垂直/堆叠柱状图标注 col_count = len(data.columns) if 'stacked' in chart_type else 1 for i, patch in enumerate(ax.patches): if chart_type == 'stacked_bar': # 堆叠柱状需累加同组前序值 group_idx = i // col_count col_idx = i % col_count y_last = data.iloc[-1, :col_idx+1].sum() else: y_last = patch.get_height() x_last = patch.get_x() + patch.get_width() / 2 ax.annotate(f'{y_last:.2f}', (x_last, y_last), xytext=(0, offset), textcoords='offset points', ha='center') elif chart_type in ['barh', 'stacked_barh']: # 水平/堆叠水平柱状图标注 col_count = len(data.columns) if 'stacked' in chart_type else 1 for i, patch in enumerate(ax.patches): if chart_type == 'stacked_barh': group_idx = i // col_count col_idx = i % col_count x_last = data.iloc[-1, :col_idx+1].sum() else: x_last = patch.get_width() y_last = patch.get_y() + patch.get_height() / 2 ax.annotate(f'{x_last:.2f}', (x_last, y_last), xytext=(offset, 0), textcoords='offset points', va='center') def plot_economic_chart(data, chart_type, title, xlabel, ylabel): """统一绘制经济图表并自动添加标注""" fig, ax = plt.subplots() # 绘制对应类型图表 plot_kws = {'stacked': True} if 'stacked' in chart_type else {} data.plot(ax=ax, kind=chart_type.split('_')[-1], **plot_kws) # 设置标题与坐标轴 ax.set_title(title) ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) # 日期轴格式化 if isinstance(data.index, pd.DatetimeIndex): ax.tick_params(axis='x', rotation=45) ax.set_xticklabels(data.index.strftime('%Y-%m-%d')) # 添加末尾标注 annotate_last_point(ax, chart_type, data) plt.tight_layout() return ax # 模拟使用:生成测试数据并绘制图表 dates = pd.date_range('2023-01-01', '2023-12-01', freq='MS') test_data = pd.DataFrame({ 'GDP': np.random.randint(100, 200, size=12), 'CPI': np.random.uniform(1.0, 3.0, size=12), 'PPI': np.random.uniform(-1.0, 2.0, size=12) }, index=dates) # 绘制折线图 plot_economic_chart(test_data, 'line', '2023年核心经济指标走势', '日期', '数值') # 绘制堆叠柱状图 plot_economic_chart(test_data, 'stacked_bar', '2023年经济指标月度堆叠', '日期', '数值') plt.show()
内容的提问来源于stack exchange,提问作者WX1505
相关产品推荐
相关产品推荐

