做数据分析这几年Matplotlib 是我用过最久、也最离不开的 Python 可视化库。刚入门的时候总觉得这玩意儿画图步骤多、参数杂一个折线图都要折腾半天后来把它的核心逻辑想通了才发现翻来覆去就是那么几个函数在来回组合。这篇东西不打算写成文档式的罗列而是想从实际使用的角度把 Matplotlib 里最常用的函数、最核心的概念、最常踩的坑一次讲清楚。不管你是在 PyCharm、VSCode 里写代码还是用 Jupyter Notebook 做探索性分析只要你需要用 Python 画图这篇文章应该都能帮上忙。1. 先把核心概念捋清楚figure、axes、axis 到底什么关系网络上经常有人问“figure、axes、axis 三个概念有什么区别”这个问题问得特别好因为大部分人画图画不明白根源就在这儿。我打个比方figure 是一面画板axes 是贴在画板上的一张画纸axis 是画纸边缘的刻度尺。你所有的图形内容折线、柱子、散点、文字都画在画纸上也就是 axes 上画纸的数量和排列方式由画板 figure 决定而 axis 只是构成 axes 的其中一部分组件负责显示坐标刻度和刻度标签。1.1 figure 是顶层容器plt.figure()创建的就是一个空白的画板它在 Matplotlib 中是最顶层的容器对象。你可以往这个画板里放多个子图即多个 axes也可以设置画布大小、背景色、分辨率等属性。我用得最多的就是fig plt.figure(figsize(8, 6), dpi100)figsize控制画布的宽和高单位是英寸dpi是输出分辨率。这个参数在论文插图和 PPT 素材制作中特别重要——配图分辨率不够打印出来全是锯齿那体验真的很糟糕。figure 不只是个空壳它还管理着全局的标题、图例、颜色条等。比如fig.suptitle()可以给整个画板设置一个大标题这在多子图对比场景下非常好用省得在每个子图里重复写说明。1.2 axes 才是真正画图的地方很多人误以为plt.plot()是往 figure 上画图其实它是往“当前的 axes”上画图。axes 即坐标轴系统它包含了 x 轴、y 轴、刻度、标签、图例、网格以及真正的内容区域。也就是说所有图形的数据表达都发生在 axes 上。创建 axes 最常用的方式有两个一是plt.subplots()直接生成画板和子图的组合fig, ax plt.subplots(2, 2, figsize(10, 8))这行代码会创建一张画板里面排布 2 行 2 列共 4 个子图返回的 ax 是一个二维数组你可以通过ax[0][0]、ax[0][1]等下标来操作每一个子图。二是用fig.add_axes([left, bottom, width, height])手动指定子图位置四个参数都是相对画板的比例值。这种方法适合精心排布图表的场景以及在主图内部镶嵌一个小图比如在大散点图的角落加一个全局缩略图。1.3 axis 只是坐标轴线本身axis 是 axes 内部的一个组件代表 x 轴、y 轴或者 z 轴的方向轴。它管理着刻度的位置ticks、刻度标签tick labels、刻度线的样式等。你在代码里偶尔会通过ax.set_xlim()、ax.set_xticks()去调整它但很少会直接操作 axis 对象。三个概念经常混在一起最简单记忆方式figure 最大装所有axes 是图的内容区axis 是内容区里的坐标线。2. 常用绘图函数逐个击破Matplotlib 的绘图函数非常多但日常高频使用的基本就是折线图、散点图、柱状图、直方图、饼图、热力图这几种再加一个比较特殊的雷达图。每一个函数都有非常灵活的参数体系我会结合典型场景给出可直接套用的写法。2.1 plot折线图是数据分析的基石plt.plot()是最基础的函数你看任何教程都逃不过它。它的基本用法是传入 x 和 y 两个序列然后自动把点按顺序连接成线。import numpy as np x np.linspace(0, 10, 100) y np.sin(x) plt.plot(x, y, colorcrimson, linewidth2, linestyle--, markero, markersize4)除了 x、y 以外最常用的参数就是 color颜色、linewidth线宽、linestyle线型、marker数据点标记。实际工作中我建议把数据准备和绘图分离先用 NumPy 或 Pandas 把数据处理好最后再画图这样代码更清晰调试也方便。2.2 scatter散点图里的透明度与网格是精髓散点图在探索两个变量之间的关系时非常好用plt.scatter()支持一个极其有用的参数 alpha也就是透明度。当数据点非常多、重叠非常严重的时候调低透明度能让你一眼看出数据的密度分布。plt.scatter(x, y, s20, alpha0.5, cy, cmapviridis) plt.grid(True, linestyle--, alpha0.6)这里的 s 控制点的大小c 控制颜色cmap 指定颜色映射方案。在数据点密集区域透明度叠加的效果会让你清楚地看到聚类中心和高密度带的形状。网格线配合透明度使用是绝配——有网格定位有透明度看密度散点图的信息量瞬间翻倍。2.3 bar 和 barh柱状图的两个方向柱状图用于离散类别的对比plt.bar()画竖直柱状图plt.barh()画水平柱状图。当类别名称很长时水平柱状图的可读性会好很多因为它给了标签足够的横向空间。categories [产品A, 产品B, 产品C, 产品D] values [23, 45, 12, 67] plt.bar(categories, values, colorsteelblue, edgecolorwhite) plt.barh(categories, values, colororange)在实际做报告时我常会在柱顶加上数值标签方法很简单就是用plt.text()在对应坐标处写上数值再调整垂直对齐方式即可。2.4 hist直方图看分布直方图是用来观察数据分布的plt.hist()最关键的两个参数是 bins 和 density。bins 是分箱数量数量太小会丢失细节太大又会让分布看起来毛毛糙糙。densityTrue 会把纵轴变成概率密度方便和数据分布曲线做对照。data np.random.randn(1000) plt.hist(data, bins30, densityTrue, alpha0.7, colorpurple)配合plt.axvline()可以画一条垂直线来标记均值或阈值这是在分布图上标注关键信息的常用技巧。2.5 pie 和 imshow饼图与热力图的定位plt.pie()做饼图时最重要的参数是 autopct显示百分比和 explode扇区突出。饼图适合展示比例关系但类别一多就不好用了实务中我一般控制在 6 个类别以内。plt.imshow()用于显示矩阵数据最常见的场景就是热力图。它和一个数值矩阵、一个颜色映射 cmap 组合起来就能把二维数据的数值大小映射成颜色深浅。热力图在相关性分析和混淆矩阵展示中非常常见。matrix np.random.rand(10, 10) plt.imshow(matrix, cmapYlGnBu, aspectauto) plt.colorbar()plt.colorbar()会自动添加一个颜色条告诉读者颜色深浅对应的数值范围这个元素不能少——没有颜色条的热力图就是一张无效的图。2.6 雷达图极坐标下的数据对比雷达图本质上仍然是 plot 或 scatter只不过把坐标系换成了极坐标。在 Matplotlib 中你不需要一个单独的 radar 函数只需要在生成子图时指定projectionpolarfig, ax plt.subplots(subplot_kw{projection: polar}) categories [A, B, C, D, E] values [3, 4, 5, 4, 3] angles np.linspace(0, 2 * np.pi, len(categories), endpointFalse).tolist() values values values[:1] angles angles angles[:1] ax.plot(angles, values, o-, linewidth2) ax.fill(angles, values, alpha0.3)注意必须把首尾连接起来否则雷达图会缺一块。这种图适合在多维度指标的对比场景中使用团队成员的能力评估、产品多维度评分对比画出来效果非常直观。3. 样式控制颜色、线型、图例与中文显示Matplotlib 好看不好看差距全在样式控制上。很多人画出来的图“一看就是 Matplotlib 默认风格”就是因为完全没有系统性地控制样式参数。3.1 颜色体系的几种写法Matplotlib 里指定颜色至少有四种方式颜色名称简写b、g、r、c、m、y、k、w、完整颜色名crimson、steelblue 等、十六进制#FF5733、RGB 元组0.1, 0.5, 0.9。我个人建议用十六进制因为可以直接从设计稿里复制颜色代码保证图表和 UI 风格统一。颜色写法示例适用场景简写字符r快速画草图临时用完整英文名steelblue常用可读性好十六进制#FF5733精确配色对接设计规范RGB 元组(0.2, 0.4, 0.8)需要程序化调整颜色时3.2 线型、标记和图例的动态插入线型常见的有-实线、--虚线、-.点划线、:点线。标记常见的有o圆点、s方形、^三角形、*星形。这些参数可以在 plot 函数里直接组合plt.plot(x, y, linestyle--, linewidth1.5, markero, markersize6)图例是图表中信息量最大的非数据元素。画多条线时每个线要提前在 plot 中加上 label 参数最后统一调用plt.legend()。图例默认放在右上角但经常遮挡数据这时可以用bbox_to_anchor和loc两个参数配合调整位置plt.legend(locupper left, bbox_to_anchor(1.02, 1), borderaxespad0)这样图例会放到图表框外部右侧完全不遮挡数据区。3.3 中文字体问题必须提前处理Matplotlib 默认字体不支持中文只要绘图中出现汉字标签就会显示成方框。这个坑几乎每个初学者都会踩而且网络上的解决方案五花八门有的还特别麻烦。我推荐的固定套路是两行代码plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False第一行设置中文字体为黑体第二行解决负号显示异常的问题。这个配置放在脚本开头执行一次整个文件里的图都会生效。如果你在 Linux 服务器上跑代码没有 SimHei 字体那就需要用plt.rcParams[font.family]配合系统字体另行设置或者直接在数据处理时把中文列名改成英文标签再画图。4. 多子图布局与组合图形的实战思路前面提到plt.subplots()可以一次性生成多子图但真正复杂的场景还需要更灵活的布局方案比如不等宽的子图、在主图内部嵌入小图。4.1 常规多子图一行代码搞定均匀网格fig, axes plt.subplots(2, 3, figsize(12, 8)) for i, ax in enumerate(axes.flat): ax.plot(np.random.randn(50)) ax.set_title(f子图 {i1})注意这里用到了axes.flat去平铺多维数组这样遍历所有子图的时候不需要写双重循环代码就优雅很多。set_title和plt.title的区别也体现在这里——前者作用于当前子图对象后者作用于当前活跃的坐标轴。plt.subplots()还有一个重要参数 sharex 和 sharey当多子图对比的数据量级一致时设置共享坐标轴会让各子图之间的对比更加直观不同子图的纵横比例也保持一致。4.2 不规则布局GridSpec 处理非均匀网格如果你希望第一行占满整行、第二行分成两列均匀网格就做不到了。这时候用GridSpecfrom matplotlib.gridspec import GridSpec fig plt.figure(figsize(10, 6)) gs GridSpec(2, 3, figurefig) ax1 fig.add_subplot(gs[0, :]) ax2 fig.add_subplot(gs[1, 0]) ax3 fig.add_subplot(gs[1, 1:])gs[0, :]表示第一行跨三列gs[1, 1:]表示第二行从第 1 列到末尾。这种布局在制作综合报告图时非常实用比如上面放总趋势图下面放分解图和占比图。4.3 在主图内部嵌入小图有时候需要在大图角落展示一个局部放大的区域这时候就要用到fig.add_axes指定小图位置fig, ax plt.subplots(figsize(8, 6)) ax.plot(x, y) ax_inset fig.add_axes([0.62, 0.58, 0.25, 0.25]) ax_inset.plot(x, y, colorgreen) ax_inset.set_xlim(4, 6) ax_inset.set_ylim(-1, 1)这里[0.62, 0.58, 0.25, 0.25]的意思是小图的左下角放在整个画布里 62% 水平、58% 垂直的位置宽度和高度各占 25%。通过调整这四个数字就能把小图放到任何位置。嵌入小图在信号处理和时序数据检查中很常用效果也非常直观。5. 环境问题排查与显示配置技巧很多新手装了 matplotlib代码也写对了但图就是弹不出来或者在 PyCharm 里只看到空白的窗口。这些问题基本都是环境配置层面的解决起来并不复杂但需要一步步排查。5.1 图不显示的常见原因与解决如果你的代码末尾写了plt.show()但还是没有界面弹出来最常见的原因是当前环境的后端backend不对。Matplotlib 支持多种后端有 GUI 后端如 TkAgg、QtAgg和静态后端如 Agg。在 PyCharm 脚本里跑代码通常会弹出交互式窗口在 Linux 命令行环境里如果没有图形界面那就只能保存文件。一个稳妥的显示方式是import matplotlib matplotlib.use(TkAgg) import matplotlib.pyplot as plt强制指定后端要在import pyplot之前执行。如果 TkAgg 不行就换成 QtAgg。另外一个比较常见的原因是安装的 Python 版本和 GUI 库的兼容问题多试两个后端基本就能解决。5.2 保存图片比弹窗更可靠在实际项目里我越来越倾向于用plt.savefig()保存图片而不是依赖plt.show()。因为弹窗必须有人守在电脑前手动关闭程序才会继续往下跑而保存图片是自动化的适合批量生成报表的场景。plt.savefig(output.png, dpi300, bbox_inchestight)dpi300适合打印和论文配图bbox_inchestight会自动去除图片周围的空白边距让图片内容撑满整个画布。如果要保存矢量图把后缀改成 pdf 或 svg 即可。这个技巧在做自动化周报时能省下大量时间——一份报告几十张图全自动批量生成排好版直接发出去。5.3 Jupyter Notebook 里的特殊配置在 Jupyter Notebook 环境中大家一般不用plt.show()而是写%matplotlib inline或者%matplotlib notebook。前者把图片静态嵌入单元格后者生成可交互的图。还有一个plt.tight_layout()值得单独拿出来说当子图重叠、标题被截断时调用这个函数能自动调整子图之间的距离和留白效果立竿见影。不过在有些复杂的 GridSpec 布局中它偶尔会失效这时就手动用fig.subplots_adjust(left0.1, right0.9, top0.9, bottom0.1)来微调。6. 常见问题速查表与实操经验下面的表格是我在平时帮同事排查 bug 时总结的高频问题清单按严重程度排序几乎每次分享都会有人问到问题现象原因解决方案图不显示无任何弹窗后端配置不对指定 matplotlib.use(TkAgg/QtAgg)中文全是小方框默认字体不支持中文设置 rcParams 的 sans-serif 为 SimHei图例不在预期位置loc 与 bbox_to_anchor 没有配合好用这两个参数联合调整savefig 保存的图缺边图片被裁剪或留白过多用 bbox_inchestightx 轴日期标签重叠密集时间点没有设置间隔用 fig.autofmt_xdate() 或手动设置 ticks多条线颜色重复颜色列表用尽或未指定用 cmap 或自定义颜色列表散点图颜色和数值无关未传入 c 参数scatter 中用 c 传入数值序列柱状图上数字重叠没有调整文字位置设置 text 的 ha 和 va 参数6.1 与 Pandas 和 NumPy 的结合用法现实中的数据很少是一行一行手写的基本上都是从 CSV、Excel 或数据库里读进来的 DataFrame。Matplotlib 与 Pandas 天然兼容DataFrame 自带了 plot 方法比如df.plot()会基于索引和列自动绘制折线图。但当你需要更精细的控制时还是建议把列抽出来传给 Matplotlibimport pandas as pd df pd.read_csv(sales.csv) fig, ax plt.subplots() ax.plot(df[date], df[amount], color#2E86AB) ax.set_title(每日销售额) ax.set_xlabel(日期) ax.set_ylabel(金额) plt.xticks(rotation45) # 解决日期标签重叠plt.xticks(rotation45)这个参数在处理日期类 x 轴时几乎是必加的不然所有日期挤成一团。另外plt.tight_layout()在加了旋转标签之后也建议调用一次避免标签和标题互相遮盖。6.2 画图前先想清楚数据维度这几年我给团队带过不少新人发现一个共同的问题拿到数据就直接调 plot结果画出来的图不是表达不清就是误导。现在我通常会建议他们在画图之前先理一理这个数据是分类的还是连续变量要比较的是趋势还是分布核心结论落到图上是哪条线、哪个柱子、哪个颜色想清楚之后代码就是水到渠成的事。比如要比较两个产品的周销量走势那一定是折线图要看用户年龄分布那一定是直方图要看各个品类占比则是饼图或者环形图。工具始终服务于表达。7. 把 Matplotlib 变成你自己的绘图工具箱文章走到这里该讲的核心概念、常用函数、样式控制、布局方式、环境排错都过了一遍。最后说点个人体会Matplotlib 的学习路径其实不需要把官方文档从头到尾啃一遍而是应该在实际项目中一个坑一个坑地填。我在实际使用中最深的一个体会是——不要每次画图都临时拼参数建议把自己常用的绘图模板沉淀成函数或配置文件。比如把中文字体、图片尺寸、颜色主题、边距设置固定成一份统一的样式文件每次画图先加载它这样你产出的所有图表在风格上都是统一的效率也会提升一大截。另外一个非常实用的小技巧把plt.savefig()写成默认行为而不仅是命令行里手动执行哪怕是在探索阶段也顺手保存一份。很多时候图看完了发现不够好想找个之前的版本做对比这时候硬盘里的历史文件就派上了用场。这个习惯救过我很多次。希望这篇文章能帮你把 Matplotlib 从“能画”提升到“画好”的状态。
企业数字化 ERP 产品动态
相关推荐
Python协议优于继承:从鸭子类型到工程实践 1. 继承很容易,维护很难:先从写代码的日常痛点说起做Python开发这些年,我接手过不少继承体系庞大的项目,也亲手维护过那种六层深、十几个父类的代码。说实话,刚开始写继承的时候感觉特别爽,子类里只需要写自… · 2026/9/26 13:48:47
从提示词碎片到模板库:Claude Code工程化实践指南 1. 为什么我会开始整理claude-code-templates:从提示词碎片到模板库先说一个我自己的真实场景。过去几个月,我几乎每天都要在终端里和 Claude Code 打交道,从需求分析、代码重构、模块设计到提交信息整理。有一段时间我发现自己在一个反复犯的… · 2026/9/26 13:48:47
Claude Code 模板化开发:从 CLAUDE.md 到自动化 AI 协作工作流 以前用 Claude Code 的时候,最头疼的就是每次打开一个新项目,都得把项目背景、代码风格、注意事项重新交代一遍。问多了它记不住,问少了我又不放心,经常是聊了十几轮才进入正题。后来我把目光转向了claude-code-templates这套东西… · 2026/9/26 13:48:47
如何让Claude Code和Cursor自动看懂代码结构:sem MCP与Skill一键配置 如何让Claude Code和Cursor自动看懂代码结构:sem MCP与Skill一键配置 【免费下载链接】sem Semantic version control > entity-level diffs, blame, and impact analysis on top of git. 28 languages via tree-sitter. Built for coding agents. 项目地址: h… · 2026/9/26 14:27:18
豆瓣图书推荐系统:用Neo4j构建可解释的知识图谱 简介:本资源是一套面向高校计算机及相关专业(人工智能、自动化、物联网等)学生的毕业设计级实践项目,聚焦豆瓣图书推荐系统与知识图谱构建,深度融合Neo4j图数据库应用,解决推荐算法实现与结构化知识建模两大… · 2026/9/26 14:27:12
AI Ops数字员工:打通大模型与工业协议的执行闭环 1. “能说”和“会做”之间,隔着整整一条工业级自动化流水线最近在给三家制造企业的IT运维团队做AI落地咨询时,反复被问到一个问题:“我们已经部署了大模型对话系统,客服能答、文档能写、会议纪要能生成——可为什么产线报警还是得… · 2026/9/26 14:27:12
DeepStream实战:多路视频AI分析从CPU瓶颈到GPU高吞吐 刚上手 DeepStream 那阵子,我其实是被一个挺尴尬的效率问题逼过去的。当时手里接了 16 路道路视频的实时分析需求,1080p 30fps 的 RTSP 流,传统做法是 CPU 拉流解码、OpenCV 转格式、再一张张送进模型做检测。听上去每一步都很常规࿰… · 2026/9/26 14:27:12
AI辅助重构83万行遗留项目:从屎山到可控流程的实战指南 最近在 GitHub 上逛到一个让我眼前一亮的重构案例,一个 83 万行级别的老项目被系统性翻新,整个过程思路极清晰。看完那套做法,我对比了一下自己这几年在“屎山”里摸爬滚打的经验,突然意识到:AI 辅助重构大型遗留项目这… · 2026/9/26 14:27:12
原神挂后台能优化游戏帧数?实测揭示显卡调频真相 把《原神》挂在后台再去玩别的游戏,帧数反而更稳了——这说法我在游戏群里见过好几回,最初只觉得是玄学。后来实在按不住好奇心,干脆花了两周做了个带控制变量的实验。结论先放在这:这不是玄学,但也不能算“原神在优化… · 2026/9/26 14:27:12
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46