Skip to content

第 11 章 样式与主题:style 与 rcParams

学习目标

  • 理解 rcParams 全局配置机制
  • 会用 plt.style.use 应用预设主题
  • plt.style.context 临时应用主题
  • 自定义配色与字体等全局参数
  • plt.rcdefaults 恢复默认

11.1 rcParams:一切样式的底层

第 1 章配置中文字体时用的 plt.rcParams["font.sans-serif"] = [...],就是 Matplotlib 的全局配置机制。

rcParams(runtime configuration parameters,运行时配置参数) 是一个字典,存着 Matplotlib 的所有默认样式:figure.facecolor(画布背景)、axes.grid(是否默认开网格)、font.size(默认字号)、axes.prop_cycle(默认颜色循环)……绘图时没显式指定的东西,全部从 rcParams 取值。

查看所有配置:

python
import matplotlib.pyplot as plt
print(len(plt.rcParams))          # 配置项总数
print(plt.rcParams["font.size"])  # 默认字号
print(plt.rcParams["axes.grid"])  # 是否默认开网格

修改某个配置:

python
plt.rcParams["font.size"] = 12
plt.rcParams["axes.grid"] = True

plt.rcParams.update({...}) 一次改多项:

python
plt.rcParams.update({
    "figure.facecolor": "#fafafa",
    "axes.facecolor": "#ffffff",
    "font.size": 11,
})

rcParams 是「全局」的:设置之后,后面所有图都受影响,直到被再次修改或 plt.rcdefaults() 恢复默认。

11.2 style:一键套用预设主题

手写一堆 rcParams 太麻烦。Matplotlib 内置了整套预设主题,用 plt.style.use(名字) 一键切换。查看可用主题:

python
import matplotlib.pyplot as plt
print(plt.style.available)

常用的几个:

主题名风格
"default"经典默认
"ggplot"仿 R 的 ggplot2,灰底白网格
"seaborn-v0_8-darkgrid"深色网格背景,学术风
"fivethirtyeight"仿新闻数据网站,深色图、亮色线
"dark_background"黑底,适合投影

下面这张图用同一条数据在四种主题下对比:

python
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(1, 13)
sales = np.array([32, 45, 40, 55, 60, 58, 66, 72, 68, 80, 76, 90])

for st in ["default", "ggplot", "seaborn-v0_8-darkgrid", "fivethirtyeight"]:
    plt.style.use(st)
    # 每个主题会重置 rcParams,需重新配置中文字体
    plt.rcParams["font.sans-serif"] = ["Noto Sans CJK SC", "DejaVu Sans"]
    plt.rcParams["axes.unicode_minus"] = False
    fig, ax = plt.subplots()
    ax.plot(x, sales, marker="o")
    ax.set_title(st)
    ...

图 11-1 是四种主题的真实输出(各子图用对应主题绘制):

图 11-1 同一数据在四种主题下的效果

注意:plt.style.use重置 rcParams,所以中文字体配置要在切换主题之后重新设置。

11.3 style.context:只在这一段生效

plt.style.use 是全局的、永久生效。只想让某一段代码用某个主题,用 plt.style.context(主题名) 上下文管理器:

python
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(1, 13)
sales = np.array([32, 45, 40, 55, 60, 58, 66, 72, 68, 80, 76, 90])

with plt.style.context("ggplot"):
    fig, ax = plt.subplots()
    ax.plot(x, sales, marker="o")
    # 离开 with 块后,主题自动还原

# 这里的图恢复默认主题

适合「报告里少数几张图换风格」的场景,不污染其他图。

11.4 自定义主题:rcParams 进阶

把常用的样式写成一个函数,每次调用即可得到统一的「公司主题」。核心是 axes.prop_cycle——默认颜色循环,决定连续画线时依次使用哪些颜色:

python
import matplotlib.pyplot as plt

def apply_brand_theme():
    plt.rcParams.update({
        "figure.facecolor": "#fafafa",   # 画布浅灰
        "axes.facecolor": "#ffffff",     # 坐标区白色
        "axes.edgecolor": "#101010",
        "axes.grid": True,
        "grid.color": "#e4e4e7",
        "grid.alpha": 0.7,
        "axes.prop_cycle": plt.cycler(
            color=["#11557c", "#ee8c18", "#40c0a6", "#d33f49"]),
        "font.size": 11,
    })

apply_brand_theme()
fig, ax = plt.subplots()
for k, base in zip(range(3), [0, 6, 12]):
    ax.plot(x, sales + base, marker="o", label=f"产品 {chr(65+k)}")
ax.set_title("自定义主题:浅灰画布、白底、品牌配色")
ax.set_xlabel("月份")
ax.set_ylabel("销量(万元)")
ax.legend()

图 11-2 真实输出:三条线自动轮流使用 prop_cycle 里的品牌色,不用手动指定 color:

图 11-2 自定义 rcParams 主题

想让自定义配置「永久生效」,可以把 rcParams 写进用户配置目录的 matplotlibrc 文件(如 Linux 的 ~/.config/matplotlib/matplotlibrc),这样每次启动自动加载。

11.5 读懂报错:主题名不存在

plt.style.use 的主题名拼错,会:

>>> plt.style.use("no-such-style")
Traceback (most recent call last):
  ...
OSError: 'no-such-style' is not a valid package style, path of style file, URL
of style file, or library style name (library styles are listed in
`style.available`)

解读:报错把可能的原因都列出来了——主题名、样式文件路径、URL。主题名以 plt.style.available 为准;自己写的样式文件则传 .mplstyle 文件路径。

动手实践

  1. 打印 plt.style.available,看看你的版本里有哪些主题。
  2. plt.style.use("ggplot") 画一张图,再切回 "default" 对比。
  3. plt.style.context("dark_background") 画一张图,验证离开 with 后主题还原。
  4. 按 11.4 写一个 apply_brand_theme() 函数,画三条自动配色线,复现图 11-2。
  5. 故意 plt.style.use("不存在的主题"),读报错。

常见错误

错误写法现象原因
plt.style.use("wrong-name")OSError: ... not a valid ... style主题名要见 style.available
style.use 之后中文变方框字体配置被重置每个主题会重置 rcParams,需重设中文字体
主题全局污染其他图后面的图全变了style.context 限定范围
rcParams 后忘了恢复交互环境里所有图都变了plt.rcdefaults()style.context
with 块外使用 context 变量主题没生效代码必须写进 with 块内

章末练习

基础

  1. 列出你本机 plt.style.available 里的 5 个主题名。
  2. "fivethirtyeight" 主题画一张折线图。
  3. style.context("ggplot") 画一张图,并验证块外主题还原。

提高

  1. 写一个自定义主题函数,统一画布色、网格、默认颜色循环,并用它画一张多线图。
  2. 对比 "seaborn-v0_8-darkgrid""dark_background" 在投影场景下的可读性,给出选择建议。

挑战

  1. 创建一个自己的 .mplstyle 文件(参照 Matplotlib 官方样式文档),包含品牌配色与字体,再用 plt.style.use("你的文件.mplstyle") 应用。
  2. 思考并实验:plt.style.use(["seaborn-v0_8-darkgrid", "grayscale"]) 叠加多个主题会怎样?用一个例子说明「后加载的主题覆盖先加载的主题」的规则。

章末自测

每题选择一个最佳答案。本书不附答案:完成后交由老师或 AI 老师批改讲解。

  1. rcParams 是什么?
    • A. 一个函数
    • B. 存所有默认样式的字典
    • C. 一种图表类型
    • D. 一个主题文件
  2. 修改默认字号用?
    • A. plt.rcParams["font.size"] = 12
    • B. plt.font(12)
    • C. plt.size(12)
    • D. ax.fontsize(12)
  3. 一键切换主题的函数?
    • A. plt.theme()
    • B. plt.style.use()
    • C. plt.set_style()
    • D. plt.style()
  4. 主题名不确定时,查看可用列表用?
    • A. plt.styles
    • B. plt.style.available
    • C. plt.list_styles()
    • D. plt.style.all
  5. 只让一段代码用某主题,用?
    • A. plt.style.use
    • B. with plt.style.context("ggplot"):
    • C. plt.style.temporarily()
    • D. plt.style.push()
  6. plt.rcdefaults() 的作用是?
    • A. 恢复默认配置
    • B. 保存当前配置
    • C. 导出主题
    • D. 打印默认值
  7. 默认颜色循环的配置项是?
    • A. axes.colors
    • B. axes.prop_cycle
    • C. lines.color
    • D. color.cycle
  8. 切换主题后中文变方框,最可能原因?
    • A. 主题不支持中文
    • B. 主题重置了 rcParams,字体配置失效
    • C. 字体损坏
    • D. 数据问题
  9. plt.style.use("bad-style") 会?
    • A. 静默忽略
    • B. OSError: ... not a valid ... style
    • C. 创建该主题
    • D. 报语法错误
  10. 下列哪个是内置主题?
    • A. "ggplot"
    • B. "redtheme"
    • C. "mychart"
    • D. "pretty"