64
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

matplotlib と Seaborn の軸の日本語設定

Python でとりあえずグラフを描画する場合は matplotlib を使うことが多いと思います。しかし、設定 API がたくさんありすぎてどれを使うべきか迷ったり、デフォルトのカラーパレットがイマイチな印象があります。Seaborn を使うとこれらの課題のいくつかを解決できます。具体例は以下の記事が参考になるでしょう。

純粋な数値演算の場合は縦軸も横軸も数値や日付などになることが多いのですが、データセットによっては日本語を扱うこともあるでしょう。ラベルやテキストに日本語を使うためにはフォント設定が必要になります。この問題にはいくつかの記事が参考になります。

で、結局自分の環境は? と思うことも多々ありますので、確認用のノートブックを nbviewer で表示できるようにしておきました。環境は Docker の jupyter/datascience-notebook を基本にしており、IPAフォントを配置してあります。他のフォントやプラットフォームでも原理は一緒です。

matplotlib.font_manager には FontManagerFontProperties クラスがあります。これらを組み合わせて現在のプラットフォームで有効なフォントの一覧を確認し、対象としたい日本語フォントが有効な場合は Seaborn の set() でグローバルに有効化してしまうのが最短と言えそうです。

有効なフォントの一覧表示

font_manager 経由でフォントの一覧を取得し、データフレームに詰め替えてから条件検索を実行します。

モジュールのインポート
import matplotlib.font_manager as fm
import pandas as pd
フォントの一覧
fonts = fm.findSystemFonts()
# len(fonts) => 100以上はあるはず
データフレームへの詰め込み
l = []
for f in fonts:
    font = fm.FontProperties(fname=f)
    l.append((f, font.get_name(), font.get_family()))
df = pd.DataFrame(l, columns=['path', 'name', 'family'])
IPAフォントが存在することの確認
df[df['path'].apply(lambda s: 'IPA' in s)]

こんな感じの出力を得られるはずです。

index path name family
82 /usr/share/fonts/truetype/IPAfont00303/ipagp.ttf IPAPGothic [sans-serif]
108 /usr/share/fonts/truetype/IPAfont00303/ipamp.ttf IPAPMincho [sans-serif]
138 /usr/share/fonts/truetype/IPAfont00303/ipam.ttf IPAMincho [sans-serif]
236 /usr/share/fonts/truetype/IPAfont00303/ipag.ttf IPAGothic [sans-serif]

なお、事前にフォントファイルを Docker コンテナ内にコピーしてあります。ダウンロードやZIPファイルの展開などは手動で実行しておきましょう。

フォントファイルのコピー
$ docker exec notebook cp -r /dataset/IPAfont00303 /usr/share/fonts/truetype

グラフの描画

matplotlib と Seaborn のそれぞれの API を使ってグラフを描画してみます。

モジュールのインポート
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

縦軸のラベルは ylabel() で設定します。この関数はオプションのキーワード引数として text() と同じものを受け取ります。matplotlib.pyplot.text を確認すると fontdict という辞書で上書きできることが分かります。

縦軸のラベルに日本語フォントを設定
plt.plot([1,2,3,4])
plt.ylabel('数値', fontdict={'family': 'IPAPGothic'})
plt.show()

graph1.png

ylabel()matplotlib.text.Text もキーワード引数として受け取ることができます。これは fontpropertiesrotation を受け取りますので、さらに細かい制御が可能です。
こうしたオーバーロードの設定がややこしい部分であり、さらにmatplotlib.rcParamsを引き継ぐ部分もあります。部分部分でのきめ細やかな設定が可能である反面、とっつきにくい印象は否めません。

次に、Seaborn でグラフを描画します。軸のスタイルは seaborn.axes_style を利用します。この関数は with 文と一緒に使うことも可能です。つまり、グラフごとにスタイルを設定できます。
とは言え、現実的にはひとつのノートブック内で同じスタイルを使うことの方が多いでしょうから seaborn.set を使うことになるでしょう。 font 属性に指定したものを軸の設定にまで伝播してくれます。

set()を呼び出してSeabornで描画
data = pd.DataFrame([1, 2, 3, 4], columns=['数値'])
sns.set(font=['IPAPGothic'])
sns.jointplot(x='数値', y='数値', data=data, xlim=(0, 5), ylim=(0, 5))

graph2.png

なお、良し悪しはあると思いますが、Seaborn の設定は matplotlib の設定も上書きします。同じノートブックで先ほどと同様に、ただしフォント未設定で matplotlib から描画すると、軸の日本語は正常に表示されます。既存のグラフのスタイルを一斉に切り替えたいときには便利かもしれません。

set()呼び出し後にmatplotlibで描画
plt.plot([1,2,3,4])
plt.ylabel('数値')
plt.show()

graph3.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
64
Help us understand the problem. What are the problem?