Python
matplotlib
フォント

matplotlibで日本語

matplotlibで日本語を扱う場合の記事はQiitaにもいくつかあるのですが、まず問題点をまとめてみます。

  1. matplotlibでは既定のフォントがDejaVu Serifになっており、日本語は豆腐になってしまう。

  2. 日本語用フォントの殆どがttcフォントファイルであるが、matplotlibではttcフォントファイルに対応していない。例えば、Windowsの場合だと、MSゴシック、MS明朝、メイリオ、游ゴシックというよく使われているフォントがttcである。

以下、対応方法を自分のメモ書きを兼ねて書いておきます。

1. フォントを準備する

matplotlibは、現時点ではttfフォントファイルとotfフォントファイルに対応しています。利用可能なフォントの一覧は以下で表示できます。

python
>>> import matplotlib.font_manager as fm
>>> fm.findSystemFonts()

適当な日本語フォントがなければ、次から好みのフォントをダウンロードしてインストールします。

フォントのインストール方法としては、それぞれのOSの通常のフォントのインストール方法でインストールします。

なお、フォントをmatplotlib専用としてmatplotlibのインストールディレクトリーにあるfontsディレクトリにインストールすることも可能ですが、matplotlibをバージョンアップすると消える可能性があることと、仮想環境を使っている場合は仮想環境毎にインストールする必要があることが欠点です。

Windows 10 の場合

Windows 10の場合、「遊明朝」がotfフォントファイルなので使うことができます。しかし、明朝系よりはゴシック系のフォントが見やすいので、Notoフォント又はIPAexフォントをダウンロードしてインストールすることを勧めます。インストールは、「コントロールパネル」→「デスクトップのカスタマイズ」→「フォント」で、フォントのコントロールパネルを表示して、そこに解凍したフォントをドラッグドロップすればいいだけです。

Ubuntu の場合

Ubuntuのデスクトップ版では、Notoフォントがデフォルトでインストールされていますが、ttcフォントファイルなので利用することができません。Googleのサイトからダウンロードしたものを使う必要がありますが少し手間がかかるのでIPAフォント又はTakaoフォントを使ったほうがいいかもしれません。

Ubuntu 16.04 の場合には、デフォルトでTakaoフォントがインストールされているのでそれを使います。Takaoフォントは、IPAフォントをベースにしてUbuntu Japanese Teamが開発・保守を行っているものです。Ubuntu 18.04 の場合は、

sudo apt install fonts-ipaexfont

サーバー版では、フォントがインストールされていないので、以下のコマンドでIPAフォントをインストールします。

sudo apt install fonts-ipaexfont

Macの場合

AppleGothicが使えます。好みにより、NotoやIPAフォントをダウンロードしてインストールしてください。

2. 日本語フォントを使う設定をする

やり方は以下の3つ

  • 個別にフォントの設定をする
  • スクリプトの最初でフォント変更の宣言をする
  • 設定ファイルmatplotlibrcを修正して既定のフォントを変更する

それぞれメリット、デメリットがあるので、個別の案件で適当な方法を使ってください。

個別にフォントの設定をする

matplotlibでは、タイトルやラベルを描く毎にフォントを設定することができます。

igfont = {'family':'IPAexGothic'}
plt.title('title',**igfont)
plt.show()

スクリプトの最初でフォント変更の宣言

以下のようにスクリプトの最初でフォント変更の宣言をすることで可能です。

import matplotlib as mpl
font = {"family":"Noto Sans CJK JP"}
mpl.rc('font', **font)

本家マニュアル

matplotlibrcを修正する

既定のフォントファミリーは'sans-serif'、'sans-serif'の既定のフォントはDejaVu Sansに設定されています。それを日本語が表示できるフォントに変更するようにします。
本家マニュアル

Windows10の場合

matplotlibrcがどこにあるかは、以下のコードで調べることができます。

>>> import matplotlib as mpl
>>> mpl.matplotlib_fname()
'D:\\projects\\pyeprog\\env\\Lib\\site-packages\\matplotlib\\mpl-data\\matplotlibrc'

そのファイルを直接修正することも、ホームディレクトリー(C:\Users\(ユーザー名))の.matplotlib ディレクトリーにコピーして修正することも可能です。matplotlibrcが両方にある場合は、ホームディレクトリーの.matplotlib ディレクトリーにある方が優先されます。コピーした場合は、mpl.matplotlib_fname()を再度実行してmatplotlibrcの場所が変更されているか確認しておきます。

修正は、FONTセクションで以下のように、font.sans-serifの先頭に日本語フォント(以下の場合は Noto Serif CJK JP) を追加します。

font.serif      : Noto Serif CJK JP, DejaVu Serif, Bitstream Vera Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
font.sans-serif : Noto Sans CJK JP, DejaVu Sans, Bitstream Vera Sans, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif

Ubuntu 16.04の場合

linuxでもmatplotlibrcがどこにあるかは、同じようにして調べることができます。

python
>>> import matplotlib as mpl
>>> mpl.matplotlib_fname()
'/home/niji/opt/gfsmap/.venv/lib/python3.6/site-packages/matplotlib/mpl-data/matplotlibrc'

そのファイルを直接修正することも、~/.config/matplotlibディレクトリーにコピーして修正することも可能です。コピーした場合は、mpl.matplotlib_fname()を再度実行してmatplotlibrcの場所が変更されているか確認しておきます。

サーバー版ではTkがインストールされていないので、そのそもの問題としてデフォルトのままでグラフを表示させようとするとエラーになります。その場合は matplotlibrc の以下の記述をコメントアウトします。

backend      : TkAgg

既定のフォントの修正は、FONTセクションで以下のように、font.sans-serifの先頭に日本語フォント(以下の場合は TakaoPGothic) を追加します。

font.serif      : TakaoPMincho, DejaVu Serif, Bitstream Vera Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
font.sans-serif : TakaoPGothic, DejaVu Sans, Bitstream Vera Sans, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif

3. キャッシュの削除

フォントを追加したり設定を変更したのにうまく反映されない場合には、キャッシュが影響している場合があります。キャシュファイルは、Windowsの場合はホームディレクトリーの.matplotlibディレクトリーに、Linuxの場合には'~/.cache/matplotlib'ディレクトリーにデフォルトでは作成されています。それを削除してから実行してみてください。キャシュファイルは、再生されるので削除しても問題ありません。

また、以下のPythonスクリプトを実行させてキャッシュを再構築するのも方法です。

matplotlib.font_manager._rebuild()