《超简单:用 Python 让 Excel 飞起来》读书笔记:第7章 案例03 在 Python 中制作组合图表

《超简单:用 Python 让 Excel 飞起来》读书笔记:第7章 案例03 在 Python 中制作组合图表 个人主页杨利杰YJlio❄️个人专栏《Sysinternals实战教程》 《Windows PowerShell 实战》 《WINDOWS教程》 《IOS教程》《微信助手》 《锤子助手》 《Python》 《Kali Linux》《那些年未解决的Windows疑难杂症》让复杂的事情更简单让重复的工作自动化《超简单用 Python 让 Excel 飞起来》读书笔记第7章 案例03 在 Python 中制作组合图表1. 第7章 案例03为什么要用组合图表2. 适用场景什么时候组合图最有价值3. 最小可用代码bar plot 同坐标系叠加4. 趋势线不要随便写用移动平均更稳5. 数值标签不要让读者靠眼睛估数6. 从 Excel 数据自动生成组合图7. 常见问题与踩坑记录7.1 中文乱码或标题显示方块7.2 Excel 数字被当成文本7.3 量级差太大时不要硬叠加7.4 不要只保存图片不验证结果8. 我对组合图的使用建议9. 总结组合图是报表自动化里的高频组件1. 第7章 案例03为什么要用组合图表这一篇继续整理《超简单用 Python 让 Excel 飞起来》的第 7 章内容主题是在 Python 中制作组合图表。组合图表不是为了让图看起来更复杂而是为了在一张图里同时表达两类信息柱形图负责展示当期数量折线图负责展示变化趋势。在实际办公报表里这类需求非常常见。比如每个月的工单数量、销售额、库存量、设备故障数单看柱形图可以知道哪个月高、哪个月低但不容易判断整体变化方向单看折线图能看到趋势却容易丢掉每一期的具体数值。组合图的价值就在这里既看清当前数据也看清背后走势。在进入代码之前先用一张总览图建立整体理解。组合图最适合解决的问题不是“画一张更花哨的图”而是让读者在同一个画面里同时看懂数量对比和趋势变化。从这张图可以看出组合图的核心不是把柱形图和折线图硬拼在一起而是让它们各自承担不同的信息任务。柱形图告诉我们每个月的具体规模折线图告诉我们增长率或趋势变化。如果一张图能讲清两件相关的事就不要拆成两张图让读者来回对比。我在写自动化报表时通常把组合图放在月度分析、趋势复盘、工单统计、销售变化、资产增长这类场景里。它比单纯柱形图更有解释力也比单纯折线图更适合向非技术人员汇报。Excel 原始数据读取月份与指标列绘制柱形图叠加折线图增加标签与图例保存为 PNG 或插入报告2. 适用场景什么时候组合图最有价值组合图并不是任何场景都适合使用。它最适合用于同一批横轴对象下两类相关指标需要同时观察的情况。比如横轴都是月份柱形图展示当月工单量折线图展示移动平均或者柱形图展示销售额折线图展示增长率。组合图的关键判断是两组数据必须存在业务关联。如果两个指标毫无关系只是为了把图表做得更“丰富”那反而会降低可读性。比较适合组合图的场景包括场景柱形图表达折线图表达工单月报每月工单数量3 期移动平均趋势销售分析每月销售额同比增长率 / 环比增长率设备故障统计每月故障数量故障趋势线库存管理每月库存量库存变化趋势运营报表每期访问量转化率 / 增长率需要注意的是如果两组数据量级差异太大不建议直接放在同一个坐标轴上。例如柱形图是 0~5000 的销售额折线图是 0~1 的满意度这时折线会被压到几乎看不见应该考虑双 y 轴而不是强行同轴叠加。3. 最小可用代码bar plot 同坐标系叠加最基础的组合图其实不复杂。Matplotlib 里只需要先用plt.bar()画柱形图再用plt.plot()叠加折线图就能得到一个同坐标系组合图。这个版本适合两组数据量级接近的情况。这里放一张同坐标系叠加的示意图对应的就是本节代码里的bar plot思路。这一步的核心要点是柱形图和折线图共用同一个 x 轴与 y 轴读者能同时看到月份数据和趋势变化。先画柱再画线是我更推荐的顺序因为折线会压在柱形图上方更容易被看见。importmatplotlib.pyplotasplt# 解决中文显示和负号显示问题plt.rcParams[font.sans-serif][SimHei]plt.rcParams[axes.unicode_minus]Falsemonths[1月,2月,3月,4月,5月,6月]tickets[120,98,135,110,150,160]trend[110,112,120,122,135,145]plt.figure(figsize(10,6))# 先画柱形图表达当期数量plt.bar(months,tickets,label当月工单量,edgecolorblack,alpha0.85)# 再画折线图表达趋势变化plt.plot(months,trend,label趋势线,linewidth2,markero)plt.title(工单量柱 趋势线线组合图)plt.xlabel(月份)plt.ylabel(数量)plt.grid(axisy,linestyledashed,alpha0.4)plt.legend()plt.tight_layout()plt.show()这段代码已经能跑通最基础的组合图。它适合教学和快速验证但如果要用于正式报表还需要继续补充趋势线计算、数值标签、图片保存和 Excel 数据读取。4. 趋势线不要随便写用移动平均更稳很多示例代码里的趋势线是手写数组这样适合演示但不适合实际报表。真实业务里趋势线应该尽量从原始数据计算出来。最常用的方法之一就是移动平均。移动平均的作用是平滑短期波动让趋势更清楚。它不会改变原始柱形数据只是在折线部分帮我们过滤掉一部分噪声。移动平均适合放在趋势分析部分因为它比普通折线更适合解释“整体方向”。这一步的核心要点是蓝色柱形代表每期原始数据发光折线代表移动平均后的趋势。柱形图保留了每个月的波动折线图则帮助读者判断整体是否向上、向下或横盘。做汇报时趋势线最好能解释数据而不是只负责装饰。importpandasaspdimportmatplotlib.pyplotasplt plt.rcParams[font.sans-serif][SimHei]plt.rcParams[axes.unicode_minus]Falsemonths[1月,2月,3月,4月,5月,6月,7月,8月]tickets[120,98,135,110,150,160,142,170]spd.Series(tickets)# 3期移动平均用于平滑短期波动ma3s.rolling(window3).mean()plt.figure(figsize(10,6))plt.bar(months,tickets,label当月工单量,edgecolorblack,alpha0.85)plt.plot(months,ma3,label3期移动平均,linewidth2,markero)plt.title(工单量柱 3期移动平均线)plt.xlabel(月份)plt.ylabel(数量)plt.grid(axisy,linestyledashed,alpha0.4)plt.legend()plt.tight_layout()plt.show()这里有一个容易忽略的点rolling(window3).mean()的前两个结果会是空值因为前两期还凑不够 3 个数据点。这不是报错而是移动平均本身的计算规则。5. 数值标签不要让读者靠眼睛估数正式报表里柱形图最好加上数值标签。因为读者看图时并不想靠网格线去猜大概是多少尤其在截图、PPT、压缩图片里坐标轴经常看不清。把数值写在柱子上方是提升可读性的低成本动作。下面这张图对应的就是数值标签场景柱形图上直接显示具体数字读者不用再目测。从这里可以看出数值标签让图表的信息密度明显提高。尤其是季度、部门、产品类别这类场景标签能帮助读者快速锁定最大值、最小值和变化幅度。importmatplotlib.pyplotasplt plt.rcParams[font.sans-serif][SimHei]plt.rcParams[axes.unicode_minus]Falsemonths[1月,2月,3月,4月,5月,6月]tickets[120,98,135,110,150,160]trend[110,112,120,122,135,145]plt.figure(figsize(10,6))barsplt.bar(months,tickets,label当月工单量,edgecolorblack,alpha0.85)plt.plot(months,trend,label趋势线,linewidth2,markero)# 给每根柱子加数值标签fori,vinenumerate(tickets):plt.text(i,v,str(v),hacenter,vabottom)plt.title(工单量组合图柱形图数值标签)plt.xlabel(月份)plt.ylabel(数量)plt.grid(axisy,linestyledashed,alpha0.4)plt.legend()plt.tight_layout()plt.show()这段代码最关键的是plt.text(i, v, str(v), hacenter, vabottom)。其中i是 x 轴位置v是柱子的高度。标签的位置不是随便放的而是根据柱子的坐标动态计算出来的。6. 从 Excel 数据自动生成组合图前面的代码都是手写数据适合学习语法真正办公自动化时数据通常来自 Excel。更实用的做法是读取 Excel 表格取出月份列和指标列计算移动平均然后自动生成组合图并保存为 PNG。这一节对应“Excel 数据 → 自动化模板 → 图表输出”的完整流程。这一步的核心要点是组合图不应该只停留在手动演示而应该沉淀成可复用模板。只要 Excel 字段保持一致后续每个月换一份数据就可以自动生成新的图表。这才是 Python 办公自动化真正省时间的地方。假设 Excel 文件中有一张名为数据的工作表包含两列月份和工单数量。importpandasaspdimportmatplotlib.pyplotaspltfrompathlibimportPath plt.rcParams[font.sans-serif][SimHei]plt.rcParams[axes.unicode_minus]Falsedefcombo_bar_line_from_excel(xlsx_path:str,sheet_name:str,x_col:str,bar_col:str,ma_window:int3,out_png:strout/组合图.png): 从 Excel 读取数据生成柱形图 移动平均折线图组合图。 参数说明 xlsx_path : Excel 文件路径 sheet_name : 工作表名称 x_col : 横轴字段例如“月份” bar_col : 柱形图字段例如“工单数量” ma_window : 移动平均窗口 out_png : 输出图片路径 dfpd.read_excel(xlsx_path,sheet_namesheet_name)ifx_colnotindf.columns:raiseValueError(f未找到横轴字段{x_col})ifbar_colnotindf.columns:raiseValueError(f未找到数值字段{bar_col})xdf[x_col].astype(str).tolist()bar_ypd.to_numeric(df[bar_col],errorscoerce).fillna(0)mabar_y.rolling(windowma_window).mean()plt.figure(figsize(11,6))plt.bar(x,bar_y,labelbar_col,edgecolorblack,alpha0.85)plt.plot(x,ma,labelf{ma_window}期移动平均,linewidth2,markero)fori,vinenumerate(bar_y.tolist()):plt.text(i,v,str(int(v)),hacenter,vabottom)plt.title(f{bar_col}柱{ma_window}期移动平均线组合图)plt.xlabel(x_col)plt.ylabel(数量)plt.grid(axisy,linestyledashed,alpha0.4)plt.legend()plt.xticks(rotation30)plt.tight_layout()out_pngPath(out_png)out_png.parent.mkdir(parentsTrue,exist_okTrue)plt.savefig(out_png,dpi200)plt.close()returnstr(out_png)if__name____main__:png_pathcombo_bar_line_from_excel(xlsx_pathreport.xlsx,sheet_name数据,x_col月份,bar_col工单数量,ma_window3,out_pngout/工单组合图.png)print(组合图已输出,png_path)这里最容易出错的是字段名。Excel 里的列名如果叫“工单数”代码里写“工单数量”程序就会找不到字段。因此实际使用时第一步不是改图表样式而是先确认字段名和工作表名称。7. 常见问题与踩坑记录组合图本身不难真正容易翻车的是细节。尤其是中文字体、字段名、数据类型和坐标轴量级这几类问题在实际办公自动化里非常常见。7.1 中文乱码或标题显示方块如果图表标题、坐标轴、图例中的中文显示为方块通常是 Matplotlib 没有找到可用中文字体。Windows 环境下可以优先尝试SimHei或Microsoft YaHei。plt.rcParams[font.sans-serif][SimHei]plt.rcParams[axes.unicode_minus]False建议把这两行固定放到脚本顶部。这样后面所有图表都能复用不用每次都重新处理中文显示问题。7.2 Excel 数字被当成文本很多 Excel 表格里的数字看上去是数字实际可能是文本比如带空格、逗号、单位或从系统导出的字符串。直接画图时可能会排序异常或计算失败。bar_ypd.to_numeric(df[bar_col],errorscoerce).fillna(0)这行代码的作用是把目标列尽量转成数值无法转换的内容用 0 兜底。如果是正式业务数据更严谨的做法是把无法转换的数据单独导出检查而不是全部静默改成 0。7.3 量级差太大时不要硬叠加如果柱形图是销售额折线图是百分比增长率两者量级差异会很大。这时折线可能贴在底部看起来像没有变化。这种情况不要强行用同坐标系组合图。可以考虑双 y 轴或者拆成两张图。如果读者看不清图表再复杂也没有意义。7.4 不要只保存图片不验证结果脚本运行成功不代表图表正确。至少要检查三件事图片是否生成、横轴顺序是否正确、柱形和折线是否对应同一批数据。验证清单 1. out 目录下是否生成 PNG 文件 2. 横轴月份是否按预期排序 3. 柱形图数值是否与 Excel 原始数据一致 4. 折线趋势是否符合移动平均计算逻辑 5. 中文标题、图例、坐标轴是否正常显示8. 我对组合图的使用建议组合图不是越复杂越好。它的价值取决于读者能不能在 3 秒内看懂图表想表达什么。如果一张组合图里堆了太多指标、太多颜色、太多线条最后就会变成视觉噪音。我自己的使用原则比较简单原则说明一张图只讲一个主题不要把所有指标都塞进一张图柱形图表达规模适合展示当期数量、金额、次数折线图表达趋势适合展示移动平均、增长率、目标线标签只标关键数据不要把图表标得像表格颜色不要过多颜色越多读者越难判断重点真正适合交付的组合图应该是“信息多但不乱”。读者能看清当期值也能看清趋势还能通过图例快速理解每个图形元素的含义。如果一张图需要你解释半天才能让别人看懂说明图表设计本身就有问题。这时候不要继续加装饰应该减少指标、简化结构或者拆分图表。9. 总结组合图是报表自动化里的高频组件这一节表面上是在学习 Matplotlib 的bar()和plot()但真正值得带走的是一个报表思路柱形图讲当前规模折线图讲变化趋势组合图负责把两者放到同一个业务上下文里。从办公自动化角度看这篇笔记至少可以沉淀出三个可复用模块最小组合图模块用plt.bar()plt.plot()快速生成图表移动平均模块用rolling().mean()自动生成趋势线Excel 自动化模块从 Excel 读取数据并自动保存 PNG 图表。后续真正建议做的是把这段代码封装成自己的报表模板。这样每个月只需要替换 Excel 数据源就能自动输出统一风格的组合图减少手工制图时间也降低复制粘贴出错的概率。下一步如果继续扩展可以把 PNG 自动插回 Excel或者批量生成多个部门、多个产品、多个月份的组合图。到那个阶段Python 就不只是画图工具而是完整的报表自动化工具链。返回顶部