3、Matplotlib 进阶:告别默认样式,打造杂志级图表。

说实话,Matplotlib 的默认样式,我用了好几年都没觉得有啥问题。直到有一次,我把一张图表丢进项目报告里,被甲方爸爸委婉地吐槽了一句:“这图...是不是 Excel 直接截的?”

嗯,那一刻我意识到,默认的灰色网格、蓝色折线、锯齿状字体,确实配不上我们精心准备的数据。今天我们就来聊聊,怎么让 Matplotlib 图表从「能用」变成「好看」。

3.1 为什么默认样式不够用?

Matplotlib 的默认设置,说白了是为「快速验证」设计的。它追求的是:你扔进去一组数据,马上能看到趋势。但如果你要拿去打印、投屏、或者放进正式文档里,默认样式就显得有点「糙」了。

我个人习惯把图表分为两类:

  • 探索型图表:自己看,怎么快怎么来,默认样式完全够用。
  • 展示型图表:给别人看,必须精修。字体、颜色、间距、图例,一个都不能含糊。

你想想看,一份几十页的行业报告,突然出现一张带着锯齿、颜色刺眼的图表,是不是瞬间拉低了整份文档的档次?

3.2 快速切换主题:plt.style.use()

Matplotlib 内置了不少现成的样式,这是最快摆脱默认风格的方法。我常用的几个:

import matplotlib.pyplot as plt

# 查看所有可用样式
print(plt.style.available)

# 直接切换
plt.style.use('ggplot')      # 仿 R 语言 ggplot2 风格
plt.style.use('seaborn-v0_8') # 更柔和的配色
plt.style.use('fivethirtyeight') # 数据新闻风格
plt.style.use('bmh')          # 贝叶斯方法风格

我在项目中遇到过最实用的是 seaborn-v0_8。它的背景是浅灰色,网格线很淡,配色也舒服。基本上,你只要加上这一行,图表的颜值就能提升 30%。

小技巧:如果你不想全局修改,可以用 with 语句临时切换样式:
with plt.style.context('ggplot'):
    plt.plot(x, y)
    plt.show()
这样只有这段代码内的图表会使用新样式,不影响其他图表。

3.3 自定义配色:别再用默认的蓝橙绿红了

Matplotlib 默认的颜色循环是 ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', ...]。说实话,这几个颜色单独看还行,放在一起就有点「幼儿园彩笔盒」的感觉。

我建议你准备一套自己的配色方案。比如我常用的:

# 一套比较「高级感」的配色
colors = ['#2E86AB', '#A23B72', '#F18F01', '#C73E1D', '#3B1F2B']

# 或者直接用 colormap
cmap = plt.cm.get_cmap('viridis')  # 渐变色,适合热力图
cmap = plt.cm.get_cmap('Set2')     # 离散色,适合分类数据

为什么会推荐 viridis?因为它对色盲友好,而且从深到浅的过渡非常自然。我在做地理数据可视化时,几乎只用它。

避坑指南:我曾经在项目里直接用默认颜色画了 8 条折线,结果有两条颜色几乎分不出来。后来我学乖了,要么限制折线数量不超过 5 条,要么用不同线型(实线、虚线、点线)来区分。

3.4 字体与文本:让图表「读」起来舒服

默认的字体是 DejaVu Sans,在英文环境下还行,但一旦出现中文,就会变成方框。这是很多新手踩过的坑。

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题

除了字体,字号也很关键。我个人的经验是:

  • 标题:16-18pt,加粗
  • 轴标签:12-14pt
  • 刻度标签:10-11pt
  • 图例:10-11pt

你想想看,一张图表里,标题比正文还小,是不是很奇怪?

3.5 去除冗余元素:少即是多

杂志级图表和默认图表最大的区别是什么?是「干净」。默认图表有很多冗余元素:

  • 上边框和右边框(默认是有的,但通常不需要)
  • 多余的网格线(网格线太密反而干扰阅读)
  • 图例放在图表内部遮挡数据

我通常这样处理:

# 去掉上边框和右边框
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

# 只保留水平网格线,去掉垂直网格线
ax.grid(axis='y', linestyle='--', alpha=0.7)
ax.grid(axis='x', visible=False)

# 图例放到图表外部
ax.legend(loc='upper left', bbox_to_anchor=(1.02, 1))

嗯,这里要注意:bbox_to_anchor 的参数是相对于坐标轴的。如果你把图例放在右侧,记得调整图表宽度,给图例留出空间。

3.6 实战:从默认到杂志级的完整示例

我们拿一个简单的折线图来演示。这是默认样式:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, label='sin')
plt.plot(x, y2, label='cos')
plt.title('Sin and Cos')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

这是经过精修后的版本:

# 设置全局样式
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi'] = 150

# 创建画布
fig, ax = plt.subplots(figsize=(8, 5))

# 配色
colors = ['#2E86AB', '#A23B72']

# 绘制数据
ax.plot(x, y1, color=colors[0], linewidth=2.5, label='正弦')
ax.plot(x, y2, color=colors[1], linewidth=2.5, linestyle='--', label='余弦')

# 标题和标签
ax.set_title('正弦与余弦函数', fontsize=16, fontweight='bold', pad=15)
ax.set_xlabel('x 值', fontsize=12)
ax.set_ylabel('y 值', fontsize=12)

# 坐标轴设置
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.tick_params(labelsize=10)

# 网格线
ax.grid(axis='y', linestyle='--', alpha=0.6)
ax.grid(axis='x', visible=False)

# 图例
ax.legend(loc='upper left', bbox_to_anchor=(1.02, 1), fontsize=11)

# 自动调整布局
plt.tight_layout()
plt.show()

你看,改动其实不大,但效果天差地别。去掉冗余边框、调整配色、优化字体,图表立刻就有了「杂志感」。

3.7 知识体系总览

下面这张图,是我自己总结的 Matplotlib 进阶路线。你可以把它当作一个检查清单:

Matplotlib 进阶:从默认到杂志级 默认样式 → 进阶 样式主题 plt.style.use() ggplot / seaborn / fivethirtyeight 配色方案 自定义颜色 / colormap viridis / Set2 / 色盲友好 字体与文本 中文字体 / 字号层级 标题 / 标签 / 刻度 去除冗余元素 隐藏边框 / 精简网格 图例外置 / 留白 输出与保存 DPI / 格式 / 尺寸 PDF / SVG / 高清PNG 核心原则:干净、一致、可读

3.8 保存与输出:别让你的努力白费

图表画好了,怎么保存也是个学问。我见过太多人用截图工具直接截屏,结果放到 PPT 里一放大,全是锯齿。

# 高清保存
plt.savefig('chart.png', dpi=300, bbox_inches='tight')

# 矢量格式(推荐用于报告)
plt.savefig('chart.pdf', bbox_inches='tight')
plt.savefig('chart.svg', bbox_inches='tight')

bbox_inches='tight' 这个参数很关键。它会自动裁剪掉图表周围的空白区域,省得你手动调整。我在写技术报告时,一律用 PDF 格式保存,插入到 LaTeX 或 Word 里,效果非常干净。

核心要点回顾:
  • plt.style.use() 快速切换主题,告别默认灰
  • 自定义配色,避免「彩笔盒」效果
  • 设置中文字体,解决方框乱码
  • 去掉冗余边框和网格,让图表更干净
  • 高清保存,用 PDF 或 SVG 矢量格式

说实话,Matplotlib 进阶并不需要学什么高深技巧。你只需要在每次画图前,多花 30 秒调整一下样式,图表的质感就能提升一个档次。下次我们聊聊怎么用 Matplotlib 做交互式图表,那个更有意思。


公众号:蓝海资料掘金营,微信deep3321