matplotlib字体配置

matplotlib字体配置

衬线和非衬线字体

衬线体(serif),是一种有衬线的字体,与之相对的没有衬线的字体则被称为无衬线体(sans-serif)。衬线是字形笔画的起始段与末端的装饰细节部分。衬线字体常用于正式文档和出版物,无衬线字体更加简洁现代,通常在屏幕上的可读性更好,也更适合用于演示文稿。对于中文来说,大体上对应于serif/sans-serif的字体是宋体系列/黑体系列,宋体常用于书籍等长篇文章;黑体笔画粗细基本一致,较为醒目,常用于标题、导语、和标志中,幻灯片里一般采用黑体(Ref: WikiPedia)。

image-20240424120152231 image-20240424120347194

对于拉丁文字母,流行的无衬线字体包括:

  • Arial: 非常常见且普遍使用的无衬线字体,几乎在所有计算机系统上都有。
  • Helvetica: 被广泛认为是最受欢迎和最专业的无衬线字体之一,常用于商业和专业演示。
  • Calibri: 自从2007年成为Microsoft Office的默认字体以来,这种字体在商业演示中变得非常流行。
  • Roboto: 这是Google开发的字体,非常适用于数字屏幕,并且在网页和移动应用中表现出色。

image-20240424123052487

常用的衬线字体包括:

  • Times New Roman: 非常传统的选择,适用于需要一种正式或学术感觉的演示。
  • Georgia: 在屏幕上特别易读的衬线字体,比Times New Roman看起来更现代一些。

image-20240424123352704

对于中文,流行的无衬线字体(黑体系列)包括:

  • 微软雅黑(Microsoft YaHei):微软开发的现代无衬线字体,清晰度高,非常适合屏幕显示和PPT演示。
  • 思源黑体(Source Han Sans/Noto Sans CJK):由Adobe和Google共同开发的开源字体,支持简体中文、繁体中文、日文和韩文,设计现代,非常适合商业和技术演示。
  • 文泉驿正黑(WenQuanYi Zen Hei):一个流行的开源中文无衬线字体,广泛用于Linux系统。

衬线字体(宋体系列)包括:

  • 宋体(SimSun):这是最常见的中文衬线字体,广泛用于正式文件和书籍出版。
  • 华文宋体(STSong):华文宋体也是一种流行的衬线字体,常用于出版和正式文件。

matplotlib字体配置

字体族

matplotlib的字体配置有两个层级,首先是字体族(font.family)的配置,在matplotlib中,预置了五种基本的字体族,分别是:

  1. serif - 衬线字体
  2. sans-serif - 无衬线字体
  3. monospace - 等宽字体
  4. cursive - 手写体风格的字体
  5. fantasy - 装饰性或艺术性的字体

每个字体族下面都有些默认的具体字体列表配置,用户无法定义新的字体族,但可以自定义字体族所采用的具体字体列表。字体族是虚的,而字体列表中的每一个字符串代表实际的字体文件,当采用了某个字体族后,matplotlib会首选排在前面的字体文件,当没找到这个字体对应的字体文件时,将按照列表顺序使用下一个可用的字体。可以查看matplotlib安装目录的mpl-data目录下的matplotlibrc文件,也可以通过plt.rcParams直接输出对应的设置:

1
2
3
4
5
6
import matplotlib.pyplot as plt

# 输出当前的字体族配置
print("Serif font list:", plt.rcParams['font.serif'])
print("Sans-serif font list:", plt.rcParams['font.sans-serif'])
print("Monospace font list:", plt.rcParams['font.monospace'])
1
2
3
Serif font list: ['DejaVu Serif', 'Bitstream Vera Serif', 'Computer Modern Roman', 'New Century Schoolbook', 'Century Schoolbook L', 'Utopia', 'ITC Bookman', 'Bookman', 'Nimbus Roman No9 L', 'Times New Roman', 'Times', 'Palatino', 'Charter', 'serif']
Sans-serif font list: ['DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif']
Monospace font list: ['DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Computer Modern Typewriter', 'Andale Mono', 'Nimbus Mono L', 'Courier New', 'Courier', 'Fixed', 'Terminal', 'monospace']

.mplstyle文件或通过代码直接更新rcParams,我们可以指定某个字体族并手动指定希望使用的字体,比如:

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt

# 更新rcParams来设定字体
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['Times New Roman', 'DejaVu Serif'] # 此时该.py文件使用了serif字体族,且字体族中仅包含两个字体. 如果'Times New Roman'不可用,将依次尝试列表中的其他字体

# 绘图代码
plt.title("Example Title", fontsize=20)
plt.show()

gogo

字体选择及中文字体

matplotlib使用内部的 font_manager 模块来管理和检索字体,它可以检测到系统的标准字体目录,因此我们在系统中安装了新的字体后,就可以直接在matplotlib中使用了。不同系统中的字体目录有所区别:

  • Windows: C:\Windows\Fonts
  • macOS: /Library/Fonts, /System/Library/Fonts, ~/Library/Fonts
  • Linux: /usr/share/fonts, /usr/local/share/fonts, ~/.fonts~/.local/share/fonts

image-20240424153950798

我们可以调用 font_manager 获取系统中有的所有字体:

1
2
3
4
5
6
from matplotlib import font_manager

font_paths = font_manager.findSystemFonts()
fonts = [font_manager.FontProperties(fname=path).get_name() for path in font_paths]
for font in sorted(set(fonts)):
print(font)

比如我们可以使用华文彩云(STCAIYUN)字体在matplotlib中进行绘图,而且只要所采用的字体支持中文,matplotlib就可以正确地渲染。但需要注意的是,对于字体族中的字体列表,只有当matplotlib没找到这个字体对应的字体文件时,才会使用下一个可用的字体,而不是说当这个字体遇到了不能够表示的字符时,就切换到下一个字体。因此假如字体列表的第一个成员选用了Times New Roman,此时就无法自动自动显示中文,这个时候我们可以在对应的绘图函数中通过 fontname 等参数手动指定字体。

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['STCAIYUN']

plt.figure(figsize=(3.25, 2.725))
plt.plot([1,2,3],[4,5,6])
plt.title('这是一个华文彩云字体的示例', fontsize=16)
plt.xlabel('x', fontname='Times New Roman')

huawen

数学字体集

Matplotlib内置了一个名为 mathtext 的数学渲染引擎,允许用户在图表中直接使用LaTeX风格的语法来渲染数学表达式,而无需安装LaTeX。将数学表达式放入$...$标记中就可以进行渲染。这部分的数学文本的字体,是由mathtext.fontset来配置的,mathtext.fontset允许选取以下几种预设的字体集:

  • dejavusans:默认的字体集,提供了广泛兼容的无衬线字体,适用于多种通用绘图需求。
  • dejavuserif:提供了衬线字体的选择,适合更正式或传统的文档和演示。
  • cm:Computer Modern字体是LaTeX用户非常熟悉的,它是许多学术出版物的标准字体,特别适合数学和科学文档。
  • stix:科学和技术信息交换字体(STIX)非常适合专业的科学出版,包括复杂的数学符号和公式。
  • stixsans:提供了STIX字体的无衬线版本,适合需要无衬线字体但同时需要广泛数学符号支持的情况。
  • custom:如果预设的字体集不能满足你的特定需求,你可以使用custom选项来指定自定义的字体。这需要确保你指定的字体支持必要的数学符号。

对于custom选项,可以通过指定一个字体来使用特定的字体文件,这允许更精细地控制数学文本的外观。比如:

1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['STCAIYUN']
plt.rcParams['mathtext.fontset'] = 'custom'
plt.rcParams['mathtext.rm'] = 'swgothi'
plt.rcParams['mathtext.it'] = 'swlink'
plt.rcParams['mathtext.bf'] = 'swgreks'

plt.title(r'This is a test $\mathrm{a}^2 + b^2 = \bf{c}^2$', fontsize=25)

jiji

其中非数学部分的字体由font来控制,数学部分的字体由mathext来控制。

Latex委托

matplotlib也允许我们使用Latex来渲染所有文本,并导入Tex的宏包,当然这要求我们提前配置好Latex环境。这可以通过LaTeX命令在text.latex.preamble中指定,但此时所有指定的字体就全部失效了。所以我们也可以只选择在特定的部分,比如标题中,使用usetex=True选项,只对部分文本用Latex来渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import matplotlib.pyplot as plt

# 启用 LaTeX
plt.rcParams['text.usetex'] = True
plt.rcParams['text.latex.preamble'] = r'\usepackage{siunitx}'
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = ['STCAIYUN']

# 绘制图表
plt.figure()
plt.title(r'LaTeX $\alpha^2$ and $\beta_1 a = \SI{2}{um}$', fontsize=16)
plt.xlabel('Time (s)')
plt.ylabel('Magnitude')
plt.plot([0, 1, 2, 3], [0, 1, 4, 9])

miamo