注:这是一篇旧文的中文翻译版本。
前不久,我在使用 Matplotlib 画图的时候,发现一些 Unicode 字符(例如,汉字) 无法正常显示:在生成的图片中,汉字是乱码的,显示为一个方框。经过大量的查找和阅读,我终于明白了如何在使用 Matplotlib 时,正确渲染 Unicode 字符1。
简单来说,之所以中文字符被显示为方框,是因为 Matplotlib 默认使用的字体并不支持中文字符,并不是 Matplotlib 本身的原因。为了能够在图片上正确显示中文字符,我们需要指示 Matplotlib 使用一种支持中文的字体即可。或者,更直接地,我们在画图时可以直接给 Matplotlib 提供一个中文字体的路径。
本文假设 fc-list
命令安装在你的电脑上。如果你的电脑上没有这个命令,你应该先安装 fontconfig。在 Linux 系统上,这个程序通常是自带的,无需安装;在 Windows 系统上,可以安装 MiKTeX 或 TeX Live 来使用 fc-list
命令。
以下介绍几种在 Matplotlib 中使用中文字符的不同方式。
指定中文字体名称#
第一种使用中文的方式是给 Matplotlib 提供一个有效的中文字体名。再开始下面步骤之前,确保你的系统上已经安装了中文字体,如果你使用的是中文系统,这应该不是问题;或者如果你想使用一种新的中文字体,可以尝试 Google 和 Adobe 发布的 Source Han Serif。首先,你需要在系统上安装中文字体2。
找到有效的中文字体名#
Matplotlib 提供了FontManager 类来处理字体相关的操作。这个类有一个 ttflist
属性,该属性提供了 Matplotlib 所能够发现到的字体列表。从这个字体列表,我们也可以很容易得到这些字体的名称。问题是,我们不清楚这些字体中有哪些字体是支持中文的。
这时候,我们就需要 fc-list 帮助了。这个命令行工具可以帮助我们找到系统上安装的中文字体:使用 fc-list :lang=zh
可以列出系统上可用的中文字体。值得注意的是,这些中文字体并非都可以被 Matplotlib 使用:Matplotlib 无法使用其中的 ttc 格式的字体(参见这里)。所以我们需要得到 Matplotlib 索引的字体和系统提供的中文字体两个集合的交集。
使用字体#
找到了 Matplotlib 索引的中文字体以后,我们可以通过更改 Matplotlib rc 指示 Matplotlib 使用中文字体。这样设置以后,后续脚本中的画图语句都会使用新指定的中文字体。加入我们在系统中安装了 STKaiti
这个字体,下面的脚本将会使用这个字体来渲染图片中的中文:
import matplotlib as mpl
font_name = "STKaiti"
mpl.rcParams['font.family']=font_name
mpl.rcParams['axes.unicode_minus']=False # in case minus sign is shown as box
plt.text(0.5, 0.5, s=u'测试')
plt.show()
在上面的代码中,font_name
可以任意一个有效的中文字体名。另外,如果你仅仅想在某个画图命令中使用中文字体,可以在画图命令中指定使用的字体名称,如下所示:
plt.text(0.5, 0.5, s=u'测试', fontname=font_name)
这种方式是我认为比较好的在 Matplotlib 中使用中文的方式。
指定中文字体的具体路径#
为了使用系统中的任何字体,我们也可以使用第二种方式:直接给 Matplotlib 提供一个字体的路径。代码如下:
import matplotlib.font_manager as mfm
import matplotlib.pyplot as plt
font_path = "/usr/share/fonts/custom/simhei.ttf"
prop = mfm.FontProperties(fname=font_path)
plt.text(0.5, 0.5, s=u'测试', fontproperties=prop)
plt.show()
上述代码中,变量 font_path
是系统上某个中文字体的绝对路径。
结论#
以上提供的两种方式都比较方便实用,我们可以根据自己的实际需要选取使用。要获取完整的代码,可以参考 这里。
参考链接#
- 第一种方式
- 第二种方式
- 两种方式都提到
- 如何使用 fontconfig 模式查找字体