You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:37:02