Matplotlib图表美化:Spines与坐标轴设置全攻略 做数据可视化这几年我越来越觉得一张图好不好看关键不是配色多花哨、特效多炫技而是那些最容易被忽略的“基础件”处理得干不干净。Matplotlib作为Python生态里最常用的绘图库功能确实强大但默认出图的边框线和坐标轴总带着一股“实验室原始风”。你要是直接把这个图放进报告或者论文里哪怕数据再漂亮观感上也会打个折扣。这篇我专门拆一下Matplotlib里边框线Spines和坐标轴Axes的设置把常用API、参数逻辑和实操中容易踩的坑一次讲透。这篇内容适合两类人一类是刚开始用Matplotlib、画出来的图总觉得“哪里不对”的新手另一类是做论文插图或技术报告、需要对图表细节做精细化控制的老手。不管是把多余的边框线去掉、让坐标轴穿过原点还是精确控制刻度标签的格式这篇文章都会给出可以直接复制的代码和踩坑经验。我尽量按照从整体到细节的顺序来讲先搞明白Matplotlib的坐标系结构再逐层拆解边框线和刻度标签的控制方法。1. 先搞明白坐标系结构决定了你改的是谁很多教程上来就甩一堆代码但你跟着抄完了想改个细节又不知道该动哪里。这背后的根本原因是没搞懂Matplotlib里的层级关系。先花两分钟把这个问题捋清楚后面所有设置都会变得顺理成章。1.1 Figure、Axes与Spines的层级关系Matplotlib里有两个最容易被混淆的核心对象一个是Figure整张画布一个是Axes画布上的子图区域。很多人看到plt.plot()就直接画图了觉得Axes这东西离自己很远实际上你每次调用plt模块下的绘图函数底层都是在操作一个默认创建好的Axes对象。可以这么理解Figure是一张白纸Axes是纸上用铅笔框出来的一个绘图区域真正画线条、写文字的位置都在Axes里。那Spines又是什么它就是Axes区域那四条边线也就是上下左右四个方向的框。默认情况下Matplotlib会把这四条边全部显示出来构成了一个完整的矩形边框。四条边分别叫top、bottom、left、right对应上、下、左、右四个位置的边框线。你可以通过ax.spines[top]这种方式拿到某一条边再对它做隐藏、改颜色、移动位置等操作。这里有一点需要特别注意Axes对象还有一个常用的获取方式。有些老教程习惯用plt.gca()拿到当前子图对象这个函数全称是Get Current Axes在某些简单场景下确实好用但代码一旦变复杂比如多子图、循环绘图依赖gca很容易拿错对象。我更建议画图一开始就显式创建Figure和Axes后面所有设置都基于这两个变量来操作代码可读性和稳定性都会好很多。1.2 默认边框线的样式与特点直接用plt.plot()画个最简单的正弦曲线然后不加任何额外设置你会看到Matplotlib给了你一个完整的矩形框。四个方向的边框线都是黑色粗细大概是0.8到1.0磅不同版本可能略有差异。这个默认样式没有什么硬伤但问题在于上边框和右边框通常承载不了任何数据信息它们的存在只会让图表看起来“被关在盒子里”视觉上显得压抑。究其原因这与Matplotlib最初模仿Matlab绘图风格有关。Matlab的传统图形界面里图表的默认样式就是完整矩形边框。但现代数据可视化的主流审美尤其是以《The Wall Street Journal》和《Economist》为代表的图表风格都在强调“数据至上”尽量减少无关的装饰性元素。所以你会看到很多高质量的图表只保留下边框和左边框甚至下边框也去掉只留一条基线。这并不说Matplotlib的默认设置是错的而是在传达图表信息时我们有了更多主动选择的权利。我在实际项目里见过不少研发同事画完图之后完全不做任何坐标轴处理直接嵌到PPT里。数据本身没任何问题但整个图看上去像半成品。后来我在团队内部定了一个小规范凡是要对外发布的图表至少要把上边框和右边框去掉只保留左、下两条轴线。就这一个改动图表质感立刻不一样。接下来我详细讲具体怎么做以及各个参数背后调节的是什么。2. 边框线设置从隐藏到定制一条龙边框线这一块看着简单其实就是四个方向的spines对象。但核心操作拆分出来无外乎三种隐藏、改样式、移动位置。每一种在实际场景里都有对应的用途我一个个说。2.1 隐藏多余的顶部和右侧边框隐藏不需要的边框线是让图表瞬间变清爽最有效的手段。操作上就一行代码import matplotlib.pyplot as plt import numpy as np x np.linspace(0, 10, 100) y np.sin(x) fig, ax plt.subplots(figsize(8, 5)) ax.plot(x, y) # 隐藏上边框和右边框 ax.spines[top].set_visible(False) ax.spines[right].set_visible(False) plt.show()这段代码的核心是set_visible(False)它的作用是让对应边框线在渲染时直接“消失”。设置完之后图表只剩下左边框和下边框视觉中心会立刻转移到数据曲线上。但有两个细节容易被忽略。第一个是隐藏边框线并不会自动隐藏对应的刻度线。比如你隐藏了右边框但如果你之前设置过右边的刻度标签它们依然会显示。另一点是隐藏上边框后如果坐标轴范围变更导致数据越界隐藏的边框也不会再出现所以不用担心“隐藏失效”。这两个细节看似不起眼但很多人在做复杂图表时就是因为这些残留元素反复调代码都调不对。如果是多个子图逐个获取spines会比较繁琐。这种情况下可以写一个小循环一次性把需要隐藏的边框统一处理fig, axes plt.subplots(2, 2, figsize(10, 8)) for ax_row in axes: for ax in ax_row: ax.spines[top].set_visible(False) ax.spines[right].set_visible(False)要是你希望整个项目里所有图表默认都不显示上、右边框还有更极简的做法。Matplotlib的rcParams参数体系里可以全局设定但需要说明的是spines本身没有直接的rcParams开关通常的折中方案是封装一个统一的自定义绘图函数。我自己的习惯是写一个小工具函数专门处理这些“图表清洁工作”后面所有图都调用它省得每个脚本里重复写三五行设置代码。2.2 修改边框线的颜色、线宽与线型隐藏只是边框线设置的第一步很多场景下我们还需要让保留的边框线更符合图表的整体风格。比如学术论文里坐标轴线通常要加粗一点让数据在打印后依然清晰可辨做商业汇报时边框线的颜色可能会跟随品牌色系调整。Matplotlib给spines提供了完善的样式设置接口用法跟plt.plot()里的线条参数几乎一样ax.spines[left].set_color(#2E86AB) ax.spines[left].set_linewidth(1.5) ax.spines[left].set_linestyle(--) ax.spines[bottom].set_color(#2E86AB) ax.spines[bottom].set_linewidth(1.5)这里set_color接收任何Matplotlib支持的颜色表示包括十六进制字符串、RGB元组、颜色名称等。set_linewidth的单位是磅默认通常是1.0论文插图我一般设到1.5到2.0电子屏幕展示的话1.2到1.5就够。set_linestyle可以设置成实线、虚线、点划线等常见的取值包括-实线、--虚线、-.点划线、:点线。这三个方法也可以合并成一条set()调用一次搞定多个属性ax.spines[bottom].set(color#2E86AB, linewidth1.5, linestyle--)在真正的应用场景里我通常只保留下边框和左边框并且把它们设置成深灰色而不是纯黑色。纯黑色在屏幕上看起来对比度太高时间久了眼睛容易疲劳打印出来又容易显得死板。深灰色比如#333333在大多数场合都更耐看。2.3 让坐标轴穿过原点或指定位置刚才上面提到的操作都是在原位置调整边框线的外观。但有一种特殊场景需要把坐标轴从“矩形下边和左边”移动到数据区域的中间位置最常见的就是让坐标轴穿过原点做出数学课本里那种经典的笛卡尔坐标系效果。这个操作的核心方法是set_position它接收一个字符串或元组控制的是边框线在Axes区域里的锚定方式。官方文档里给了三种定位方式但实际最常用的是zero和data。# 让左边框和底边框都穿过原点 ax.spines[left].set_position(zero) ax.spines[bottom].set_position(zero)zero表示让边框线位于数据坐标为0的位置。但要注意如果数据的y轴范围不包含0比如y值在[5, 15]之间那zero这个位置实际是在可视区域外的边框线会被自动裁剪看起来像是消失了。对于更一般的情况比如想让左边框穿过x2的位置可以用(data, 2)这种格式ax.spines[left].set_position((data, 2))这段的含义是“以数据坐标定位让边框线出现在x等于2的地方”。这种写法在绘制对称函数、信号波形图时非常常见。另外还有一个axes定位模式比如(axes, 0.5)表示把边框线放置在Axes区域高度的50%处即子图的几何中心不受数据范围影响。做完原点移动后记得把另一侧的边框隐藏掉否则会出现边框线交叉或者多余线框的问题。比如你要做一个通过原点的十字坐标系就需要把top和right都隐藏然后left和bottom都指向零点ax.spines[top].set_visible(False) ax.spines[right].set_visible(False) ax.spines[left].set_position(zero) ax.spines[bottom].set_position(zero)这里有个实操中的小坑移动了边框线之后原来朝下的刻度标签位置不会自动跟着变。如果你把左边框移到了坐标轴中间但刻度标签还在底部边框上视觉上会有点错乱。后文讲刻度标签时我会一并说明怎么配合调整。3. 坐标轴刻度从位置到格式的精细控制边框线是坐标轴的“骨架”刻度标签就是坐标轴上的“文字信息”。一张图表要让读者快速读懂刻度设计功不可没。Matplotlib对刻度的控制分成两块刻度位置Tick Locations和刻度标签Tick Labels。前者决定哪些数据点显示刻度线后者决定刻度线旁边显示什么文字。3.1 指定刻度位置set_xticks与set_yticks默认情况下Matplotlib会根据数据范围自动计算刻度间隔尝试给出“看起来比较整齐”的刻度位置。比如数据范围0到10它可能会在0、2、4、6、8、10处放置刻度。这个自动计算在大多数场景下够用但遇到特殊业务需求比如想精确显示某几个点或者想让x轴刻度按周、按月对齐自动刻度就不太够了。手动设置刻度位置的方法很简单ax.set_xticks([0, 2, 4, 6, 8, 10]) ax.set_yticks([-1.0, -0.5, 0.0, 0.5, 1.0])这里传入一个列表列表里每一个值代表该坐标轴上要显示刻度线的数据坐标。注意set_xticks只改变刻度线的位置不改变数据的显示范围。它不会帮你裁剪图形也不会影响数据的绘制纯粹就是“在这些位置画上刻度线”。如果你不仅要设置位置还要批量修改刻度标签的显示文本可以用set_xticklabelsax.set_xticks([1, 2, 3, 4]) ax.set_xticklabels([一, 二, 三, 四])这里有个高频错误必须提醒先设置set_xticks再设置set_xticklabels顺序不能反。如果你在设置set_xticklabels时传入的标签数量与刻度数量不一致Matplotlib会发出警告并且标签对齐会出现错乱。还有一点某些版本的Matplotlib里如果你只设置set_xticklabels而不手动设置set_xticks可能会导致刻度和标签错位因为自动刻度的数量跟你给的标签数量很难严格匹配。所以我的习惯是但凡要改标签文本一定是set_xticks和set_xticklabels成对出现。3.2 刻度标签的旋转、字号与格式控制业务图表里最常遇到的尴尬场景是x轴标签文字太长、相互重叠。尤其是类别名称比如“2024年第一季度”、“华东大区”这种默认横排显示几乎必然叠成一团。解决办法有两个方向一是让标签旋转二是让标签竖排或者缩短内容。旋转标签用的是rotation参数可以直接在set_xticklabels或tick_params里设置ax.set_xticklabels([2024Q1, 2024Q2, 2024Q3, 2024Q4], rotation30)旋转角度30表示顺时针旋转30度45度是更常见的做法视觉上比较均衡。如果标签文字很长还可以配合ha参数调整水平对齐方式避免旋转之后标签偏离刻度点太远ax.set_xticklabels(labels, rotation45, haright)haright表示标签的水平对齐方式为右对齐。旋转45度时如果不对齐方式做微调看起来容易参差不齐。还有一个实际经验是旋转角度在30到60度之间时haright或hacenter效果都不错但旋转90度时建议用hacenter配合vatop效果更像竖排文字。字号和字体颜色的控制可以在set_xticklabels里通过fontsize和color设置但我更推荐用tick_params统一管理。tick_params是Matplotlib提供的“批处理接口”它可以同时设置刻度线的长度、方向、宽度以及刻度标签的字号、颜色等参数。比如ax.tick_params(axisx, labelsize12, labelcolor#333333, length5, width1.2, directionin)这行代码统一处理了x轴的刻度线长度、宽度、方向和标签字号。其中directionin是学术论文里很常见的设置表示刻度线朝绘图区域内部延伸而不是默认的外部。我个人做论文插图时通常会把direction设为in同时top和right的刻度也打开tick_params里设topTrue, rightTrue这是很多期刊排版风格的要求。3.3 刻度数值的格式化显示百分比、货币与科学计数有时候数据本身是0.25314这种带着很多小数位的值直接显示在坐标轴上既占空间又不好读。格式化刻度文本是为了让人一眼看懂数字代表什么。Matplotlib提供了多种方式最简单的是用FuncFormatter配合自定义函数from matplotlib.ticker import FuncFormatter def pct(x, pos): return f{x * 100:.0f}% ax.yaxis.set_major_formatter(FuncFormatter(pct))这个函数的逻辑是x是当前刻度值pos是刻度位置序号一般用不上返回值就是显示在坐标轴上的字符串。上面这个例子把0.23这种小数转成“23%”的形式显示。对于数值较大的情况比如百万、千万级的数据直接显示一长串数字会显得拥挤。一种常见的做法是在坐标轴标题里注明单位但更省事的是用ScalarFormatter配合科学计数法from matplotlib.ticker import ScalarFormatter ax.yaxis.set_major_formatter(ScalarFormatter(useMathTextTrue))设置之后大数值会以数学公式的方式显示成和$10^6$的乘积形式专业感很强。不过我实际做业务报表时更多是用FuncFormatter把数据手动转成“1.2万”“3.4亿”这种更符合中文阅读习惯的表示。3.4 隐藏刻度与边框的联动最后相对冷门但很实用的一个技巧有时候你连刻度标签都不想要只想保留一条干干净净的坐标轴线。比如做分布图时均值线旁边的标签可能会干扰数据点呈现。这时可以用set_xticks([])传入空列表把所有刻度都移除或者用tick_params(labelleftFalse)只隐藏标签而保留刻度线。这里要特别说一下“隐藏刻度后边框能动”的联动问题。回到前面提到过的原点坐标系场景当你把left的边框线移动到x0位置后y轴刻度标签的位置默认还是在左侧边缘不会跟着边框一起移动。要让刻度标签也跟着边框线走推荐做法是先把left边框移动到零点然后在tick_params里设置labelleftTrue并配合set_yticks保证标签位置合理。如果你不想深入处理这些联动另一个省事的方案是隐藏左边框改用ax.axhline(0, colorblack, linewidth1.2)画一条参考线这样刻度标签就不会受影响。这个替代方案我经常用在快速出图场景避免在刻度联动上消耗过多时间。4. 坐标轴范围、显示开关与网格线边界线设置解决了“框”的问题刻度设置解决了“数字”的问题。但一张图最终呈现的数据区域大小、坐标轴是否完全隐藏、背景是否加网格这些全局性的显示选项同样决定着一张图的主视觉风格。这一节把这三块内容打包讲清楚因为它们在实际应用中经常被同时调整。4.1 设置与缩放xlim/ylimMatplotlib默认会根据数据的最小值和最大值自动计算坐标轴范围但这种方式有时候会让图形出现大量留白或者把关键区域压得太扁。手动设置坐标轴范围是一个高频操作。ax.set_xlim(0, 12) ax.set_ylim(-1.5, 1.5)set_xlim和set_ylim接收两个参数分别代表坐标轴的最小值和最大值。设置之后图形显示区域会严格限定在这个范围内。设置坐标轴范围在处理异常值的时候尤其重要——比如你的数据里有一个极端大的值自动坐标轴会被这个异常值拉伸导致正常数据的波动看起来很小。手动裁剪坐标轴后主要数据特征立马能看清。set_xlim还有一个反向用法如果两个参数设置成从大到小比如set_xlim(10, 0)坐标轴会反向显示数据从右往左延伸。这在某些对比图表中偶尔会用到但如果不是刻意设计建议谨慎使用否则容易让读者产生读图困惑。实操中还有个小细节值得记住如果你想让坐标轴范围自动适应数据但需要留出一些边距可以直接通过ax.margins(margin0.05)来设置。这个方法会给数据范围统一增加5%的余量效果是图中的数据点不会顶在坐标轴边缘视觉上更透气。对我来说margins比手动算xlim方便得多尤其在数据范围动态变化时它不需要你重新计算边界值。4.2 让坐标轴整个消失axis off有些图表完全不需要坐标轴比如展示图片、画热力图、做装饰性的数据分布图这时坐标轴反而是干扰信息。Matplotlib提供了两种常见的“彻底隐藏”方法。第一种是ax.axis(off)。这一行代码会同时隐藏坐标轴边框、刻度、刻度标签和坐标轴标题相当于这整个坐标体系都从画布上消失了。第二种是分别调用ax.set_xticks([])和ax.set_yticks([])这只会隐藏刻度及其标签但边框线还在。两者的区别在于前者是“完全隐藏”后者是“保留骨架但去掉数字”。# 方法一完全隐藏 ax.axis(off) # 方法二保留边框但去掉刻度与标签 ax.set_xticks([]) ax.set_yticks([])哪种方法更好取决于场景。比如用imshow显示一张图像时通常会彻底关掉坐标轴让图像占据整个绘图区域而绘制某些装饰性图形时可能只需要去掉刻度数字保留边框线让画面更有结构感。4.3 网格线的打开与调优网格线是提升图表可读性的一大利器但用不好就是视觉灾难。Matplotlib里打开网格线非常简单在plot之后调用一句ax.grid(True)即可。默认的网格线样式在纯白背景下是灰色实线视觉效果偏重。如果你希望网格线“看起来有但又不抢数据风头”我建议调整以下三个参数ax.grid(True, linestyle--, alpha0.5, linewidth0.8, color#CCCCCC)这里linestyle--把实现改成虚线alpha0.5降低透明度linewidth0.8控制线条粗细color#CCCCCC选一个浅灰色。这样处理后网格线在背景里若隐若现既能起到参考作用又不会比数据本身更引人注目。如果只想让x轴或y轴有网格线可以给axis参数传值ax.grid(True, axisy)只在y方向画横向网格线ax.grid(True, axisx)只在x方向画纵向网格线。这种“单向网格”在时间序列图中非常常见——只画横向网格线帮助读数值纵向则保持清爽。5. 实战案例自定义坐标轴风格的销售趋势图前面说了这么多单一功能点这一节我用一个完整的例子把边框线、坐标轴、刻度标签、网格线这些内容串起来。这个例子的背景是“某公司”2024年各月销售数据的趋势展示要求图表简洁、专业可以直接放进季度汇报PPT。5.1 数据准备与基础绘图假设我们有12个月的销售额数据月份用1到12表示销售额在单位上取“万元”。import matplotlib.pyplot as plt import numpy as np months np.arange(1, 13) sales np.array([52, 68, 75, 80, 92, 105, 98, 112, 124, 138, 145, 160]) fig, ax plt.subplots(figsize(10, 6)) ax.plot(months, sales, markero, color#2E86AB, linewidth2)这里我用了简单的折线图实心圆点标记每个月的具体数值。基础图形出来之后可以看到默认的矩形边框和自动刻度范围但这个状态离“能放进汇报PPT”还有明显距离。5.2 分步骤定制坐标轴与边框线接下来按照我自己的处理顺序一步一步把图做精细。第一步处理边框线。隐藏上边框和右边框左边框和底边框设置深灰色和略粗的线宽让线条在演示时有足够的视觉重量。ax.spines[top].set_visible(False) ax.spines[right].set_visible(False) ax.spines[left].set_color(#333333) ax.spines[left].set_linewidth(1.2) ax.spines[bottom].set_color(#333333) ax.spines[bottom].set_linewidth(1.2)第二步调整坐标轴范围和刻度。销售额数据从52到160如果从0开始显示折线图上方和下方会有大段空白。这里我手动把y轴范围设为40到170让数据曲线在图中占据更多高度视觉更饱满。x轴刻度固定为1到12标签换成“1月、2月...”这样的中文格式。ax.set_xlim(0.5, 12.5) ax.set_ylim(40, 170) ax.set_xticks(range(1, 13)) ax.set_xticklabels([f{i}月 for i in range(1, 13)], fontsize10, rotation0) ax.set_yticks(range(50, 171, 20))range(50, 171, 20)表示从50开始到170结束每隔20取一个刻度。这样y轴刻度就是50、70、90、110、130、150、170数字不长也足够精确。第三步打开柔和网格线并给坐标轴加上标题和单位说明。ax.grid(True, linestyle--, alpha0.6, linewidth0.8, color#DDDDDD) ax.set_xlabel(月份, fontsize12) ax.set_ylabel(销售额万元, fontsize12) ax.set_title(某公司2024年销售额月度趋势, fontsize14, pad15)这里我把alpha设置成0.6网格线能看清但不会抢眼。标题加了pad15让标题和图表顶部之间有一点空隙不会贴得太紧。5.3 最终效果与手动微调把所有代码汇总运行后我一般还会做一个微调动作检查一下数据点是否会与网格线重叠太多以及刻度标签是否在视觉上对齐。比如这里x轴标签旋转0度横排在12个类别时刚刚好如果换成24个类别那就要考虑旋转45度了。另外有一个实际的汇报场景需要考虑如果这张图要投影到会议屏幕上浅灰色的网格线和1.2磅的坐标轴线在远距离看可能偏细。针对投影场景我会把坐标轴线的线宽提到1.8数据线的线宽提到2.5网格线的alpha降一点保证主次分明。这就是图表调整的核心逻辑针对不同输出媒介反复检查线条粗细和颜色对比度而不是一次性定死所有参数。6. 常见问题与避坑指南这一节整理我在实际使用中遇到最多的问题也是各种技术问答社区里反复出现的高频坑。每一个看着都不是大问题但一旦踩中排查起来相当费时间。6.1 刻度消失或错位有读者经常遇到这样的情况设置了set_xticklabels之后原本正常的刻度消失了或者标签和刻度位置对不上。这个问题的原因多半是忘记同步设置set_xticks。由于Matplotlib内部自动刻度位置和你手动传入的标签数量不一定匹配就会出现标签丢失或错位。解决思路很简单在设置标签之前先手动设置刻度位置保证“刻度位置”和“刻度标签”长度一致。写成代码就是这样ax.set_xticks([1, 2, 3, 4]) ax.set_xticklabels([A, B, C, D])另外如果在循环里处理多个子图时注意区分操作的是哪个Axes对象别把标签设到错误的子图上。6.2 坐标轴移动后刻度标签没跟上前面说过把left边框移动到x0后刻度标签可能还待在原来的位置。这个问题的主要原因是刻度标签的位置是相对于整个Axes区域的而边框线只是边界上的装饰线它移动后并不会自动通知刻度标签跟着走。最简单的规避方案是直接隐藏原有的left边框改用ax.axvline或ax.axhline在数据坐标位置画参考线。这样数据和标签完全独立不会牵一发而动全身。如果你坚持用边框移动的方式那就需要在移动后额外调用tick_params手工调整标签方向和位置过程比较繁琐非必要不推荐。6.3 什么时候该隐藏边框什么时候该保留很多初学者学完隐藏边框的技巧后就喜欢把所有图的上、右边框全部去掉结果有些场景反而弄巧成拙。比如当图表有多个子图并需要通过闭合边框来划分区域时去掉边框会让子图之间缺乏边界感。再比如画双y轴图时右边的y轴往往需要对应的右边框线来承载刻度标签这时候如果把右边框隐藏了右边轴刻度标签就会悬浮在图表边缘观感非常怪异。我的个人经验是隐藏边框主要适用于单轴折线图、柱状图、散点图这类“数据自解释”的图表。遇到双轴图、多面板图或者需要明确区域边界的场合保持完整边框反而是更稳妥的选择。这条经验不是绝对的但它能帮你在大方向上少走弯路。6.4 中文显示乱码的处理坐标轴标签和刻度标签中经常要显示中文比如“月份”“销售额”。很多时候图跑出来中文全变成了方框。这是因为Matplotlib默认字体不包含中文字符集需要在绘图前显式指定中文字体。plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, WenQuanYi Zen Hei] plt.rcParams[axes.unicode_minus] Falsefont.sans-serif设置成多个中文字体名是为了在不同操作系统上都能找到可用的字体。第二行axes.unicode_minus的作用是让负号正常显示不设置的话坐标轴上的负号可能也会变成乱码。这个配置放到绘图脚本的最顶部基本能解决90%的中文乱码问题。如果换到无中文字体的Linux服务器上可能还需要手动安装字体文件那就属于另一个话题了。说了这么多Matplotlib里面边框线和坐标轴的设计说到底是一种“克制”的艺术。我见过很多图数据是真的不错但坐标轴上顶满了各种不必要的元素反而让人抓不住重点。真正好的图表是让读者一眼看到数据本身的趋势和异常而不是在研究边框线的颜色和刻度的密度。也许你花了很多时间调这些细节但最后做出来的图看起来却像是“什么都没做”——这就对了。最高级的视觉呈现就是让所有辅助元素都退到幕后数据走到台前。后续我还会继续整理坐标轴标题、图例、多子图布局等方面的实操经验有需要的朋友可以持续关注。