查看: 146|回复: 3

Python自动生成Excel组合图表(双轴)的完整实现

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
在实际数据分析与汇报中,常常需要在一张图表内同时展示数量与趋势——例如工单数量(柱形图)与解决率(折线图)。若分两张图,读者需来回对照;若强行共用同一纵轴,量级差异大的数据会使折线被压扁。Python 的 matplotlib 库配合 pandas 读取 Excel 数据,可以快速生成可复用的组合图表(Combo Chart),并直接输出为 PNG 图片用于报告。本文从基本同轴组合图入手,重点讲解双 y 轴组合图的实现,并提供一个从 Excel 一键读取、自动出图的脚本模板,最后总结常见坑与验证标准。
  1. # 1. 同坐标轴组合图:适合量级相近的数据
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. plt.rcParams["font.sans-serif"] = ["SimHei"]
  5. plt.rcParams["axes.unicode_minus"] = False
  6. months = ["1月", "2月", "3月", "4月", "5月", "6月"]
  7. tickets = [120, 98, 135, 110, 150, 160]      # 柱形:工单数量
  8. avg_time = [80, 75, 90, 82, 88, 95]          # 折线:处理效率评分
  9. x = np.arange(len(months))
  10. plt.figure(figsize=(9, 6))
  11. plt.bar(x, tickets, width=0.6, label="工单数量", alpha=0.75)
  12. plt.plot(x, avg_time, marker="o", linewidth=2, label="处理效率评分")
  13. plt.xticks(x, months)
  14. plt.title("组合图:工单数量 + 处理效率评分")
  15. plt.xlabel("月份")
  16. plt.ylabel("数值")
  17. plt.grid(axis="y", linestyle="--", alpha=0.4)
  18. plt.legend()
  19. plt.tight_layout()
  20. plt.show()
复制代码

上述代码中,柱形图与折线图共享同一个 y 轴。只有当两组数据的数量级相近(如 80~160 与 80~95)时,这种图表才能清晰传达信息。若一组数据为 0~10000,另一组为 0~100,折线会被压成一条几乎无起伏的线,此时应改用双 y 轴。
  1. # 2. 双 y 轴组合图:解决单位与量级差异
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. plt.rcParams["font.sans-serif"] = ["SimHei"]
  5. plt.rcParams["axes.unicode_minus"] = False
  6. months = ["1月", "2月", "3月", "4月", "5月", "6月"]
  7. tickets = [120, 98, 135, 110, 150, 160]    # 柱形:工单数量
  8. solve_rate = [92, 88, 95, 90, 96, 97]      # 折线:解决率(%)
  9. x = np.arange(len(months))
  10. fig, ax1 = plt.subplots(figsize=(9, 6))
  11. # 左轴:柱形图
  12. ax1.bar(x, tickets, width=0.6, alpha=0.75, label="工单数量")
  13. ax1.set_xlabel("月份")
  14. ax1.set_ylabel("工单数量(单)")
  15. ax1.set_xticks(x)
  16. ax1.set_xticklabels(months)
  17. ax1.grid(axis="y", linestyle="--", alpha=0.4)
  18. # 右轴:折线图
  19. ax2 = ax1.twinx()
  20. ax2.plot(x, solve_rate, marker="o", linewidth=2, linestyle="--", label="解决率(%)")
  21. ax2.set_ylabel("解决率(%)")
  22. ax2.set_ylim(0, 100)   # 百分比指标锁定范围
  23. # 合并图例(重要:双轴需从两个对象分别取 handles 和 labels)
  24. h1, l1 = ax1.get_legend_handles_labels()
  25. h2, l2 = ax2.get_legend_handles_labels()
  26. ax1.legend(h1 + h2, l1 + l2, loc="upper left")
  27. plt.title("组合图:工单数量(柱) + 解决率(折线)")
  28. plt.tight_layout()
  29. plt.show()
复制代码

使用 ax1.twinx() 创建共享 x 轴的第二个 y 轴。左轴承载数量,右轴承载百分比。关键点:右轴必须显式设定 y 轴范围(set_ylim(0, 100)),否则 matplotlib 自动缩放会夸大微小波动。另外,图例必须合并两个 axes 的 handles 和 labels,否则只显示柱形图的图例。
  1. # 3. 企业可交付版:从 Excel 读取数据,一键生成组合图并保存 PNG
  2. import pandas as pd
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. from pathlib import Path
  6. plt.rcParams["font.sans-serif"] = ["SimHei"]
  7. plt.rcParams["axes.unicode_minus"] = False
  8. def excel_to_combo_chart(
  9.     xlsx_path: str,
  10.     sheet: str,
  11.     x_col: str,
  12.     bar_col: str,
  13.     line_col: str,
  14.     out_png: str = "out/combo.jpg",
  15.     line_is_percent: bool = True
  16. ) -> str:
  17.     """
  18.     从 Excel 读取数据生成组合图(柱形+折线,双y轴)并保存为PNG
  19.     :param xlsx_path: Excel文件路径
  20.     :param sheet: 工作表名
  21.     :param x_col: 用作x轴标签的列名(如"月份")
  22.     :param bar_col: 柱形图数据列名
  23.     :param line_col: 折线图数据列名
  24.     :param out_png: 输出图片路径
  25.     :param line_is_percent: 折线数据是否为百分比(如果是则锁定右轴0-100)
  26.     :return: 输出图片路径
  27.     """
  28.     df = pd.read_excel(xlsx_path, sheet_name=sheet)
  29.     x_labels = df[x_col].astype(str).tolist()
  30.     bar = pd.to_numeric(df[bar_col], errors="coerce").fillna(0).tolist()
  31.     line = pd.to_numeric(df[line_col], errors="coerce").fillna(0).tolist()
  32.     x = np.arange(len(x_labels))
  33.     fig, ax1 = plt.subplots(figsize=(10, 6))
  34.     ax1.bar(x, bar, width=0.6, alpha=0.75, label=bar_col)
  35.     ax1.set_xlabel(x_col)
  36.     ax1.set_ylabel(bar_col)
  37.     ax1.set_xticks(x)
  38.     ax1.set_xticklabels(x_labels)
  39.     ax1.grid(axis="y", linestyle="--", alpha=0.4)
  40.     # 柱形图数据标签
  41.     for i, v in enumerate(bar):
  42.         ax1.text(i, v, str(int(v)), ha="center", va="bottom")
  43.     ax2 = ax1.twinx()
  44.     ax2.plot(x, line, marker="o", linewidth=2, linestyle="--", label=line_col)
  45.     ax2.set_ylabel(line_col)
  46.     if line_is_percent:
  47.         ax2.set_ylim(0, 100)
  48.     h1, l1 = ax1.get_legend_handles_labels()
  49.     h2, l2 = ax2.get_legend_handles_labels()
  50.     ax1.legend(h1 + h2, l1 + l2, loc="upper left")
  51.     plt.title(f"组合图:{bar_col}(柱) + {line_col}(折线)")
  52.     plt.tight_layout()
  53.     out_png = Path(out_png)
  54.     out_png.parent.mkdir(parents=True, exist_ok=True)
  55.     plt.savefig(out_png, dpi=200)
  56.     plt.close()
  57.     return str(out_png)
  58. if __name__ == "__main__":
  59.     png = excel_to_combo_chart(
  60.         xlsx_path="report.xlsx",
  61.         sheet="数据",
  62.         x_col="月份",
  63.         bar_col="工单数量",
  64.         line_col="解决率",
  65.         out_png="out/组合图_工单数量_解决率.jpg",
  66.         line_is_percent=True
  67.     )
  68.     print("已输出:", png)
复制代码

此函数为完整自动化流程:pandas 读取 Excel 指定列,清洗数值(非数值填充为0),建立双y轴,生成图片并保存。使用时只需维护 report.xlsx 内的数据,每次运行即可获得最新组合图。

常见坑与验证要点:
1. 右轴范围:百分比指标务必锁定 0~100,避免自动缩放造成视觉误导。
2. 单位标注:左右轴必须分别写明单位(如“单”、“%”),否则图表失去可读性。
3. 图例合并:双轴图表需从 ax1 和 ax2 分别获取 handles 和 labels 后合并,再调用一次 legend(),否则折线图例可能缺失。
4. 数据标签:柱形图顶部的数据标签不宜过多,避免遮挡。
5. 验收标准:生成 PNG 后检查标题是否说明主题、左右轴单位是否明确、图例是否完整、坐标范围是否合理、数据标签是否影响阅读。真正的验证不是“图有没有生成”,而是“图能否支持你想表达的判断”。

组合图不是为了让图表更复杂,而是在一张图内同时呈现“量 + 趋势 + 质量”。理解了业务关联性(如工单量与解决率是否共同增长),才能正确选择使用同轴还是双轴。上述代码已可直接复制到 Python 环境中运行,适用于桌面支持月报、销售数据分析、KPI 看板等场景。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python自动生成Excel组合图表(双轴)的完整实现

感谢楼主分享,这个双轴组合图的实现非常清晰实用。之前手动在Excel里调双轴图总要对齐半天,用python自动生成确实省事很多。那个合并图例的细节特别关键,之前自己试的时候经常漏掉右轴的图例,踩坑了。不知道楼主有没有遇到过双轴标签重叠的问题,如何调整布局?
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python自动生成Excel组合图表(双轴)的完整实现

楼主这个教程写得非常清楚,尤其是双 y 轴和图例合并的部分,正好解决了我之前做报表时折线被压扁的痛点。不过最后那个 `excel_to_combo_chart` 函数定义好像没贴完,后面是打算怎么读取 Excel 并传参的?另外如果 Excel 里有多余的空行或者列名不标准,有没有什么容错处理?期待楼主分享完整版。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python自动生成Excel组合图表(双轴)的完整实现

感谢分享这个教程,写得很清晰!我之前做双轴图时经常遇到图例合并和右轴范围的问题,看完第 2 节的示例终于知道怎么规范处理了。特别是 `set_ylim(0, 100)` 这一步,以前没注意,确实能避免折线被过度拉伸误导。第三部分的通用函数也很有参考价值,回头试试改造成自己的数据模板。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-11 14:01 , Processed in 0.038358 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部