Python: 实践 解决 Ubuntu matplotlib 中文显示
1. 检查可用字体:
from matplotlib.font_manager import FontManager import subprocess fm = FontManager() mat_fonts = set(f.name for f in fm.ttflist) output = subprocess.check_output('fc-list :lang=zh -f "%{family}\n"', shell=True) output = output.decode('utf-8') # print '*' * 10, '系统可用的中文字体', '*' * 10 # print output zh_fonts = set(f.split(',', 1)[0] for f in output.split('\n')) available = mat_fonts & zh_fonts print('*' * 10, '可用的字体', '*' * 10) for f in available: print(f)
运行结果:
********** 可用的字体 ********** AR PL UMing CN Noto Sans CJK JP Noto Serif CJK JP AR PL UKai CN Droid Sans Fallback
注:某些字体中文显示正常,英文显示异常,比如 Droid Sans Fallback
2. 检查中文显示是否正常:
import matplotlib.pyplot as plt import random # 设置显示中文字体 plt.rcParams['font.family'] = 'AR PL UMing CN' # 设置正常显示负号 plt.rcParams['axes.unicode_minus']=False # 画出温度变化图 # 0.准备数据 x = range(60) y_shanghai = [random.uniform(15, 18) for i in x] y_beijing = [random.uniform(1,3) for i in x] # 1.创建画布 plt.figure(figsize=(20, 8), dpi=100) # 2.绘制图像 plt.plot(x, y_shanghai, label="上海") plt.plot(x, y_beijing, color="r", linestyle="--", label="北京") # 2.1 添加x,y轴刻度 # 构造x,y轴刻度标签 x_ticks_label = ["11点{}分".format(i) for i in x] y_ticks = range(40) # 刻度显示 plt.xticks(x[::5], x_ticks_label[::5]) plt.yticks(y_ticks[::5]) # 2.2 添加网格显示 plt.grid(True, linestyle="--", alpha=0.5) # 2.3 添加描述信息 plt.xlabel("时间") plt.ylabel("温度") plt.title("中午11点--12点某城市温度变化图", fontsize=20) # 2.4 图像保存 plt.savefig("./test.png") # 2.5 添加图例 plt.legend(loc=0) # 3.图像显示 plt.show()
运行结果:
3. 坐标轴刻度指数负号显示错误
使用字体'AR PL UMing CN',坐标轴刻度指数负号仍然显示不出来,提示:
Font 'default' does not have a glyph for '\u2212' [U+2212], substituting with a dummy symbol.
经测试,使用Ubuntu自带字体'Noto Sans CJK JP'可以解决问题。 查阅资料可知,字体'AR PL UMing CN'覆盖汉字29.1%,而'Noto Sans CJK JP'虽然是一款日文字体,但覆盖汉字40.1%,比'AR PL UMing CN'多了不少。
测试代码:
import matplotlib.pyplot as plt import numpy as np # 设置matplotlib显示中文字体 plt.rcParams['font.family'] = 'Noto Sans CJK JP' # 设置matplotlib正常显示负号 plt.rcParams['axes.unicode_minus'] = False fig, axs = plt.subplots(1, 2, figsize=(10, 3), layout='constrained') xdata = np.arange(1000) # make an ordinal for this data = 10**np.random.randn(1000) axs[0].set_title('English display') axs[0].plot(xdata, data) axs[1].set_title('刻度显示负号 -1') axs[1].set_yscale('log') axs[1].plot(xdata, data) plt.show()
运行结果: