python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python Excel图表添加数据标签

Python Excel图表添加并设置数据标签的完整指南

作者:杨利杰YJlio

本文介绍了如何使用Python为Excel图表添加数据标签,提升图表可读性和交付质量,通过5张示例图片,展示了从基础到高级的数据标签应用场景,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下

前言

这一篇主要解决的问题很明确:在使用 Python 生成图表时,如何给折线图、柱形图、组合图添加清晰的数据标签,让读者不用猜、不用估、不用再回头查原始表格。

很多图表之所以“不够交付”,不是因为图画得丑,而是因为读者需要自己判断数值。比如一根柱子看起来接近 160,但到底是 158、160 还是 163?折线图两个点看起来差不多,但到底差了多少?这些信息如果没有直接写在图上,汇报时就很容易被反问。

图表不是装饰品,图表的核心任务是降低读者理解成本。所以在周报、月报、汇报截图、工单统计、设备故障排行、Excel 自动化报表里,数据标签往往不是可有可无的小细节,而是影响交付质量的关键动作。

开篇先放一张总览图,它对应本文的核心主题:给图表添加并设置数据标签,让图表从“看趋势”升级为“直接读结论”。

从图中可以看出,数据标签的价值不是单纯把数字贴上去,而是让柱形图、折线图和组合图具备更强的可读性。尤其是在销售额、增长率、完成率这类指标场景里,读者不仅要看走势,还要看每个节点的具体数值。

本文会围绕 Matplotlib 中最常用的 plt.text()ax.text() 展开,重点讲清楚三个问题:**标签怎么加、位置怎么调、格式怎么统一**。

2. 最小可用:折线图加数据点标签

先从最容易理解的折线图开始。折线图的每个点都有两个信息:一个是横坐标位置,一个是纵坐标数值。添加数据标签,本质上就是在每个点附近再放一段文字。

在 Matplotlib 里,核心函数就是 plt.text(x, y, text)。也就是说,你要告诉 Python:文字放在哪个 x 位置、哪个 y 位置,以及文字内容是什么。

折线图标签最适合用来表达“每个月具体是多少”。例如工单数量、完成率、响应时长、销售额、满意度等,只要读者需要知道每个节点的准确值,就应该考虑加标签。

折线图场景里,下面这张图对应的是 for + text 的最小可用逻辑:先画折线,再遍历每个数据点,把对应数值标到点的上方。

从图中可以看出,每个月份的数据点上方都已经直接显示了数值。这样读者不用再根据 y 轴刻度估算,也不用再追问“这个点具体是多少”。这就是数据标签最直接的交付价值。

import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

months = ["1月", "2月", "3月", "4月", "5月", "6月"]
tickets = [120, 98, 135, 110, 150, 160]

plt.figure()
plt.plot(months, tickets, marker="o", label="工单数量")

# 给每个数据点添加标签
for i, v in enumerate(tickets):
    plt.text(i, v, str(v), ha="center", va="bottom")

plt.title("折线图:数据标签示例")
plt.xlabel("月份")
plt.ylabel("数量(单)")
plt.grid(axis="y", linestyle="dashed", alpha=0.4)
plt.legend()
plt.tight_layout()
plt.show()

这里最容易误解的是 i。因为横坐标 months 是字符串列表,所以在 plt.text() 里,我更习惯用 enumerate() 产生的数字索引作为 x 坐标。简单理解就是:第一个点放在 0,第二个点放在 1,依次往后。

如果你的 x 轴是字符串,优先使用 enumerate();如果你的 x 轴本身就是数值,使用 zip(x, y) 会更直观。

3. 用 zip 写法批量标注:逻辑更清楚

除了 enumerate(),我更推荐在数值坐标场景中使用 zip()。它的表达更接近人的思维:每次同时拿到一个 x 和一个 y,然后把 y 的值写在这个点旁边。

这种写法适合 x 轴本身就是数字的情况,比如月份序号、日期编号、批次编号、设备编号等。

import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

x = [1, 2, 3, 4, 5, 6]
y = [120, 98, 135, 110, 150, 160]

plt.figure()
plt.plot(x, y, marker="o", label="工单数量")

# zip 写法:每次同时取出 xi 和 yi
for xi, yi in zip(x, y):
    plt.text(xi, yi, f"{yi}", ha="center", va="bottom")

plt.title("zip 批量标注示例")
plt.xlabel("月份序号")
plt.ylabel("数量(单)")
plt.grid(axis="y", linestyle="dashed", alpha=0.4)
plt.legend()
plt.tight_layout()
plt.show()

zip(x, y) 的好处是坐标含义更明确。你不会把“索引位置”和“业务横坐标”混在一起。对新手来说,刚开始可以用 enumerate() 跑通;后面写规范脚本时,建议根据实际坐标类型选择更清楚的方式。

需要注意:如果 x 是字符串类别,直接把字符串传给 plt.text() 有时会导致位置控制不符合预期。所以这类场景我一般使用索引定位,再通过图表本身显示字符串刻度。

4. 柱形图加数据标签:最常见的交付场景

如果说折线图标签解决的是“趋势点具体是多少”,那么柱形图标签解决的就是“每根柱子到底是多少”。在实际汇报里,柱形图是加标签收益最高的图表类型之一。

比如部门工单量排行、设备故障次数排行、月份销售额对比、各区域库存对比,如果不加标签,读者只能靠 y 轴刻度估算;一旦加上标签,图表就能直接成为汇报结论。

柱形图场景下,标签通常放在柱子顶部,既不遮挡主体,又能让读者第一眼读到准确数值。

从图中可以看出,每个季度的销售额都被直接标在柱形图上方。这个位置非常适合汇报,因为读者先看到趋势,再看到具体数值,理解路径很顺。

import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

months = ["1月", "2月", "3月", "4月", "5月", "6月"]
tickets = [120, 98, 135, 110, 150, 160]

plt.figure()
bars = plt.bar(months, tickets, label="当月工单量", edgecolor="black", alpha=0.85)

# 给每根柱子加标签
for i, v in enumerate(tickets):
    plt.text(i, v, str(v), ha="center", va="bottom")

plt.title("柱形图:数据标签示例")
plt.xlabel("月份")
plt.ylabel("数量(单)")
plt.grid(axis="y", linestyle="dashed", alpha=0.4)
plt.legend()
plt.tight_layout()
plt.show()

柱形图加标签时,最常见的坐标设置是:x = iy = v。其中 i 表示第几根柱子,v 表示柱子的高度。文字放在 v 的位置,就会贴在柱子顶部。

我自己的习惯是:只要柱形图用于汇报、截图、邮件或周报,默认给关键柱子加标签。如果柱子数量很少,可以全部加;如果柱子太多,只标 Top N 或最大/最小值。

5. 标准交付版标签:偏移、百分比和格式化输出

基础标签只是第一步。真正用于交付的图表,还需要考虑标签是否压线、是否贴边、是否格式统一、是否符合业务口径。

例如完成率、成功率、增长率这类指标,原始数据通常是 0.820.93,但汇报时应该显示成 82%93%。如果直接把小数贴上去,读者还要自己换算,图表的交付感会明显下降。

这类场景要重点处理两个动作:**标签偏移** 和 **标签格式化**。

从图中可以看出,折线图的每个节点都显示了百分比标签,并且标签位置和数据点之间留出了合适距离。下面的指标卡也进一步补充了平均完成率、最高完成率、达成率和数据点数量,这就是比较接近汇报场景的交付版效果。

import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

months = ["1月", "2月", "3月", "4月", "5月", "6月"]
rate = [0.82, 0.76, 0.88, 0.80, 0.91, 0.93]

plt.figure()
plt.plot(months, rate, marker="o", label="成功率")

# 标签偏移,避免文字压在线上
offset = 0.015
for i, v in enumerate(rate):
    plt.text(i, v + offset, f"{v:.0%}", ha="center", va="bottom")

plt.title("成功率趋势(带数据标签)")
plt.xlabel("月份")
plt.ylabel("成功率")
plt.grid(axis="y", linestyle="dashed", alpha=0.4)
plt.legend()
plt.tight_layout()
plt.show()

这里的关键点有两个。

第一,v + offset 是为了让标签向上偏移一点,避免文字压在线条或数据点上。偏移值不能乱写,要根据数据范围调整。如果你的 y 轴是 0 到 1 的比例数据,0.010.03 通常比较合适;如果你的 y 轴是几百、几千,就要换成更大的偏移。

第二,f"{v:.0%}" 是百分比格式化。它会把 0.93 显示成 93%。如果你要保留一位小数,可以写成 f"{v:.1%}"

不要把原始数据格式直接丢到图表里。图表是给人看的,不是给程序看的。程序可以理解 0.93,但业务汇报中更应该显示 93%

6. 常见坑:标签不是越多越好

数据标签确实能提升可读性,但它不是越多越好。如果每个点都加、每条线都加、每根柱子都加,图表很容易变成“贴纸墙”。这时读者反而更难抓重点。

我自己总结下来,最容易踩的坑主要有四类。

6.1 x 轴是字符串,标签位置却用错了

如果 x 轴是 ["1月", "2月", "3月"] 这种字符串类别,直接在 plt.text() 里使用字符串并不总是最稳。更保险的方式是使用 enumerate() 得到位置索引。

for i, v in enumerate(values):
    plt.text(i, v, str(v), ha="center", va="bottom")

6.2 标签压线或压柱顶

标签压住图表主体,会让画面显得很乱。解决方法就是加偏移。

offset = 2
for i, v in enumerate(values):
    plt.text(i, v + offset, str(v), ha="center", va="bottom")

6.3 标签太多导致画面拥挤

如果数据点超过 20 个,我一般不会全部标注。更推荐只标注最大值、最小值、最后一个点,或者 Top N。

标签的目标不是把所有数字塞进图里,而是帮助读者更快看到重点。

6.4 多条线标签互相遮挡

如果一张图里有多条折线,所有线都加标签,很容易互相压住。此时可以给不同线设置不同的偏移,或者只给主指标加标签。

图表设计不是堆功能,而是做取舍。数据标签也是一样,真正成熟的做法不是“能加就加”,而是“该加才加”。

7. 可复用模板:把标签动作封装成函数

如果每次画图都手写一遍 for 循环,代码很快会变得重复。更好的方式是把“添加标签”封装成函数,以后折线图、柱形图、组合图都可以直接调用。

这一节对应的是从“会写代码”到“会做脚本模板”的提升。图表自动化真正有价值的地方,不是这次能画出来,而是下一次换数据后还能继续复用。

从图中可以看出,完整的自动化流程不是只画一张图,而是从批量 Excel 文件输入开始,经过 Python 可视化脚本处理,再套用统一的标签模板,最后批量生成带标签的结果图。这个思路比单次手工画图更适合办公自动化。

import matplotlib.pyplot as plt

def add_labels_by_index(values, fmt=str, y_offset=0):
    """
    按索引位置给图表添加数据标签。

    values:
        数值列表,例如 [120, 98, 135]
    fmt:
        标签格式化函数,例如 lambda v: f"{v:.0%}"
    y_offset:
        y 方向偏移,避免标签压住图形
    """
    for i, v in enumerate(values):
        plt.text(i, v + y_offset, fmt(v), ha="center", va="bottom")

调用方式也很简单。

months = ["1月", "2月", "3月", "4月", "5月", "6月"]
tickets = [120, 98, 135, 110, 150, 160]

plt.figure()
plt.bar(months, tickets, edgecolor="black", alpha=0.85)

add_labels_by_index(
    tickets,
    fmt=lambda v: f"{v}",
    y_offset=2
)

plt.title("工单数量柱形图")
plt.xlabel("月份")
plt.ylabel("数量(单)")
plt.tight_layout()
plt.show()

如果是百分比,也只需要换一个格式化函数。

rate = [0.82, 0.76, 0.88, 0.80, 0.91, 0.93]

plt.figure()
plt.plot(["1月", "2月", "3月", "4月", "5月", "6月"], rate, marker="o")

add_labels_by_index(
    rate,
    fmt=lambda v: f"{v:.0%}",
    y_offset=0.015
)

plt.title("成功率趋势图")
plt.tight_layout()
plt.show()

把重复动作封装成函数,是 Python 办公自动化真正开始提效的标志。前面是“写一次脚本解决一次问题”,后面是“沉淀一个函数解决一类问题”。

8. 如何验证标签是否真正可用

脚本运行成功不等于图表可用。添加数据标签后,我一般会从三个角度做验证。

8.1 数值是否正确

先核对图上的标签数值是否和原始数据一致。尤其是百分比、金额、小数位数这类格式化场景,很容易出现显示格式正确但数值口径不一致的问题。

# 示例:检查原始数据
print(rate)
print([f"{v:.0%}" for v in rate])

8.2 位置是否清楚

标签不能压住点、线、柱子或图例。生成图表后要实际打开看一眼,不能只看控制台没有报错。

如果标签重叠、贴边、压线,即使代码没错,交付效果也是不合格的。

8.3 格式是否符合业务表达

如果指标是成功率,就应该显示百分比;如果是金额,就应该显示带单位的金额;如果是数量,就不要无意义保留小数。

# 金额格式
money = 12345
label = f"¥{money:,.0f}"
print(label)  # ¥12,345

最终判断标准很简单:把图发给一个没看过原始 Excel 的人,他能不能直接读懂核心结论。如果还需要你反复解释,那说明标签设计还不够好。

9. 我的总结提升

这一篇的核心,不是简单记住“如何使用 plt.text() 添加标签”,而是要把数据标签放到 Python + Excel 办公自动化的交付场景里理解。

我从这一节带走的结论主要有三点。

第一,数据标签解决的是读图成本问题。它不是为了让图更花哨,而是让读者不用猜数值、不用看原表、不用问作者。

第二,标签位置和格式比“能不能显示”更重要。基础写法很简单,真正影响交付质量的是偏移、对齐、百分比、金额、小数位数和标签密度。

第三,重复标注动作应该封装成函数。如果每篇报表都要手写一遍标签逻辑,就没有真正自动化。只有把它变成模板,后续才能批量复用。

如果只会复制代码,但不知道标签为什么放在这里、为什么这样格式化,遇到真实报表时还是会卡住。

所以我建议把这节当成一个“小型交付模块”:先跑通基础标签,再处理偏移和格式,最后封装成自己的图表标注函数。

以上就是Python Excel图表添加并设置数据标签的完整指南的详细内容,更多关于Python Excel图表添加数据标签的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文