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 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?因为它对色盲友好,而且从深到浅的过渡非常自然。我在做地理数据可视化时,几乎只用它。
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 进阶路线。你可以把它当作一个检查清单:
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