核心概念:
- 支援中文其實就是想辦法讓系統支援 CJK 字型;所以本質上是「換字型」的方法。用 "customized font" 當關鍵字下去找,會比「中文 支援 matplotlib」的資料豐富。
- 想辦法讓 matplotlib 有對應的 CJK 字型、並且在畫圖的時候找得到那些字型
- matplotlib 可以說是 seaborn 的底層元件
所以實做上會是:
- 確認系統某處有中文字型,或是怎麼準備需要的字型檔案。
- matplotlib 吃 ttf
- 指令 fc-list :lang=zh or fc-cache -fv
- 搞清楚 matplotlib 要讀的字型要放哪裡
- 搞清楚 matplotlib 可以怎麼讀
- 討清楚 matplotlib 讀到的字型,可能是怎麼傳遞給 seaborn
查看系統中字型
查看字型(限 zh)
fc-list :lang=zh
查看字型快取
fc-cache -fv
查看 matplotlib 讀得到的字型
from matplotlib.font_manager import FontManager
import subprocess
fm = FontManager()
mat_fonts = set(f.name for f in fm.ttflist)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
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') | |
zh_fonts = set(f.split(',', 1)[0] for f in output.split('\n')) | |
available = mat_fonts & zh_fonts | |
print('*' * 10, '系統中的字體', '*' * 10) | |
print(zh_fonts) | |
print('*' * 10, 'matplotlib 讀到的字體', '*' * 10) | |
print(mat_fonts) | |
print('*' * 10, '可用的字體 - 系統中和 matplotlib 讀到的字體交集', '*' * 10) | |
for f in available: | |
print(f) |
存放 matplotlib 讀得到的字型的地方
/usr/share/fonts/truetype/arphic
或是
site-packages/matplotlib/mpl-data/fonts/ttf
因為吃 ttf,而現在很多字型已經是 ttc 這種格式(把好幾個 ttf 打包起來),所以可以將系統中的中文字型抽出來放進上述目錄裡。這支小程式可以幫忙做這種轉檔
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Convert TTC font to TTF using fontforge with python extension. | |
**Warning** The scripts saves splitted fonts in the current working directory. | |
Usage: | |
split_ttc_font_to_ttf.py Droid.ttc | |
Preinstallation: apt-get install python-fontforge | |
""" | |
import sys | |
import fontforge | |
fonts = fontforge.fontsInFile(sys.argv[1]) | |
for fontName in fonts: | |
font = fontforge.open('%s(%s)'%(sys.argv[1], fontName)) | |
font.generate('%s.ttf'%fontName) | |
font.close() |
讓 matplotlib 開始讀字型
注意,每一次的新增刪減字型,都要把快取移除,新的狀態才會生效
rm -fr ~/.cache/matplotlib
每一次使用的時候決定要使用的字型
new_fonts = ['AR PL UKai TW'] + mpl.rcParams['font.sans-serif']
mpl.rcParams['font.sans-serif'] = new_fonts
或是可以調整 site-packages/matplotlib/mpl-data/matplotlibrc 來選定每次的預設字型(沒有好好試過)
seaborn 上的字型
對 seaborn 操作後,matplotlib 字型設定會回到預設值。要再調整過。
Ref:
https://newtoypia.blogspot.com/2018/08/matplotlib-ttc.html
https://scentellegher.github.io/visualization/2018/05/02/custom-fonts-matplotlib.html
https://monkey0105.github.io/2016/10/10/matplotlib-chinese-display/
https://medium.com/@aitmr1234567890/%E8%A7%A3%E6%B1%BApython-3-matplotlib%E8%88%87seaborn%E8%A6%96%E8%A6%BA%E5%8C%96%E5%A5%97%E4%BB%B6%E4%B8%AD%E6%96%87%E9%A1%AF%E7%A4%BA%E5%95%8F%E9%A1%8C-f7b3773a889b