MatplotLib在MacOS下的中文乱码问题

背景

最近在JupyterMatplotlib绘制一些图表的时候,遇到一个很久没遇到的中文乱码问题,类似下图里的图例,中文变成了方块:

问题原因

以前使用Linux系统的时候,经常会遇到这个问题。通常的原因就是编码格式不支持或者使用的字体里没有中文导致。而Matplotlib出现这个问题,就是因为其使用的字体里没有中文导致。

Matplotlib默认使用的字体是一种衬线字体,叫做DejaVu。我们要规避这个问题,就是要把这个字体改掉。

解决办法

1. 找到合适的字体

字体的选择,有两个方案:

  1. 从互联网上下载自己喜欢的字体,安装到电脑上

  2. 从MacOS中查找包含中文的字体,直接拿来用

这里着重说一下第2条,如何在本机上找到合适的字体。我们可以通过下面这个脚本,打印出电脑上所有可用的字体,从中选择自己喜欢的即可。

1
2
3
4
5
6
7
8
from matplotlib.font_manager import FontManager
fm = FontManager()
mat_fonts = sorted(set(f.name for f in fm.ttflist))
print(mat_fonts)


# output
# ['.Aqua Kana', '.Keyboard', ... '.SF Compact', '.SF Compact Rounded']

而我最终选择的字体是PingFang HK,这个字体是Apple官方在黑体的基础上开发的字体,中文的显示效果比较能接受。

2. 临时解决方案

在绘图时,我们可以通过rcParams参数,设置单张图表使用的字体,如下:

1
2
3
4
5
6
7
8
9
10
from matplotlib import rcParams
rcParams['font.family'] = 'PingFang HK'
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([1, 2, 3], label='你好')

ax.legend()
plt.show()

3. 长久解决方案

如果我们不想每次画图的时候,都要写一下字体参数,则可以修改Matplotlib的配置文件,让配置长久生效。

1. 查找配置文件的路径

由于Matplotlib可能通过多种途径安装,如pipconda等。其安装路径千差万别,配置文件的路径也有不同,需要我们通过一些途径找到。如下面这段代码:

1
2
3
4
5
import matplotlib

print(matplotlib.matplotlib_fname())

# output: /xxx/matplotlib/mpl-data/matplotlibrc

2. 修改字体配置

在配置文件中,我们可以找到font.family变量,它可以设定为具体的文字名,如PingFang HK,也可以是官方预定义的几个枚举,如:

  • ‘serif’ (e.g., Times),
  • ‘sans-serif’ (e.g., Helvetica),
  • ‘cursive’ (e.g., Zapf-Chancery),
  • ‘fantasy’ (e.g., Western), and
  • ‘monospace’ (e.g., Courier).

如果使用上面的枚举的时候,Matplotlib会从其对应的字体数组中从前向后查找。这也是为什么默认字体是DejaVu的原因,因为其在所有数组的第一个。

修改后的配置如下:

1
2
3
4
5
6
font.family:  'PingFang HK'
#font.style: normal
#font.variant: normal
#font.weight: normal
#font.stretch: normal
#font.size: 10.0