如何在matplotlib绘图中自由地使用不同字族的多样化字体
如果只是在matplotlib绘图中使用一个统一的字体是比较简单的,只要对matplotlib做全局设置即可。
matplotlib的设置方式
matplotlib的全局设置有三种方式:一是利用style来全局使用由style定义的设置,比如plt.style.use('bmh')
;
二是利用matplotlibrc文件来做默认的设置;
三是利用rcParams来进行设置。
其中,rcParams具有相对最高的灵活性,通常是最常用的。
rcParams的全局设置有两种方式:一是直接对rcParams中的key-value进行设置,比如:
mpl.rcParams['font.serif'] = ['SimSun']
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
mpl.rcParams['xtick.direction'] = 'in'#将x周的刻度线方向设置向内
mpl.rcParams['ytick.direction'] = 'in'#将y轴的刻度方向设置向内
使用rc函数还可以设置一组内的参数:
plt.rc('lines', linewidth=2, color='r') # 设置lines组内的线条的宽度和颜色
这相当于直接修改rcParams字典:
plt.rcParams['lines.linewidth'] = 2
plt.rcParams['lines.color'] = 'r'
二是先给出key-value字典,然后再更新:
config = {
"font.family":'serif',
"font.size": 20,
}
mpl.rcParams.update(config)
rcParams的灵活性在于其还能局部进行设置,比如:
with mpl.rc_context({
'lines.linewidth': 2, 'lines.linestyle': ':'}):
plt.plot(data)
利用mpl.rc_context只进行临时的设置,该图绘制完后就恢复原来的设置。
rcParams的选项和参数可以利用print(mpl.rcParams.keys())
查看。
rcParams设置全局字体
根据mpl.rcParams的信息,我们知道matplotlib提供了如下五个字族:
serif, monospace, fantasy, cursive, and sans-serif,分别是衬线、等宽、幻想、草书、非衬线。
比常规的衬线、等宽、非衬线多了两种。
rcParams 默认的字族是非衬线。即:
'font.family': ['sans-serif'],
在设置时我们只要切换这一选项,就能使用其他字族。
然而,这一选项只是设置文本选项,对于放在$$中的数学公式的字体,则有其另外的选项:
'mathtext.bf': 'sans:bold',
'mathtext.bfit': 'sans:italic:bold',
'mathtext.cal': 'cursive',
'mathtext.default': 'it',
'mathtext.fallback': 'cm',
'mathtext.fontset': 'dejavusans',
'mathtext.it': 'sans:italic',
'mathtext.rm': 'sans',
'mathtext.sf': 'sans',
'mathtext.tt': 'monospace',
可以看到,默认的字体是dejavusans,备选字体是cm,其他的字系和字形则是该字体的粗体,斜体等变形。
使用默认渲染器或后端的设置
所以,默认情况下要全局设置字体,实际上是要设置文本字体和数学字体两种,比如:
'font.family': ['serif']
'font.serif': ['Times New Roman'],
'mathtext.fontset': 'stix',
就是选择文本为衬线的Times New Roman,数学字体为与其非常相似的stix字体。
对于英文图来说,这样的设置就足以解决问题了。
然而若是一个中文图,需要在其中显示中文,就会存在问题,因为Times New Roman不包含中文字符,所以不会正常显示。
这时我们可以使用一个包含中文字符的字体,比如宋体即SimSun。
'font.family': ['serif']
'font.serif': ['SimSun'],
'mathtext.fontset': 'stix',
然而,这样虽然能显示中文,但英文文本也是宋体的,会与某些希望英文是Times New Roman字体的要求不一致。
此时,一种方式是将英文文本也用数学字体显示,这样就可以用接近Times New Roman的字体来显示英文文本。
比如:将原来的内容:
r'中文 English $y=\alpha\sin(x)$'
转变为:
r'中文 $\text{English }$y=\alpha\sin(x)$'
如此能大体解决中文期刊常要求的中文用宋体,英文用Times New Roman的要求。
示例:
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import matplotlib.font_manager as fm
mpl.rcParams['font.family'] = 'serif' #字族 'sans-serif' #serif serif, monospace, fantasy, cursive, and sans-serif
mpl.rcParams['font.serif'] = ['SimSun'] #文本字体 FangSong,SimHei,'SimSun',Microsoft YaHei,Source Han Serif
mpl.rcParams["mathtext.fontset"] = 'stix' #数学字体 'stix','cm'
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
mpl.rcParams['xtick.direction'] = 'in'#将x周的刻度线方向设置向内
mpl.rcParams['ytick.direction'] = 'in'