matplotlib と Seaborn の軸の日本語設定


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

- [pythonで美しいグラフ描画 -seabornを使えばデータ分析と可視化が捗る その1 - Qiita](http://qiita.com/hik0107/items/3dc541158fceb3156ee0)
- [pythonで美しいグラフ描画 -seabornを使えばデータ分析と可視化が捗る その2 - Qiita](http://qiita.com/hik0107/items/7233ca334b2a5e1ca924)

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

- [matplotlibで日本語 - Qiita](http://qiita.com/canard0328/items/a859bffc9c9e11368f37)
- [Jupyterで日本語ラベルを使ったグラフを描画する - Qiita](http://qiita.com/hagino3000/items/1b54acc01483ccd0ac72)
- [【Seaborn】日本語を表示する (フォントを変更する) - Qiita](http://qiita.com/keisuke-nakata/items/2309764d21438645f6b9)

で、結局自分の環境は？ と思うことも多々ありますので、確認用のノートブックを nbviewer で表示できるようにしておきました。環境は Docker の [jupyter/datascience-notebook](https://hub.docker.com/r/jupyter/datascience-notebook/) を基本にしており、[IPAフォント](http://ipafont.ipa.go.jp/)を配置してあります。他のフォントやプラットフォームでも原理は一緒です。

- [matplotlib font listing](http://nbviewer.jupyter.org/gist/skitazaki/9d00bb465ce48a8806d1)

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


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

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

```python:モジュールのインポート
import matplotlib.font_manager as fm
import pandas as pd
```

```python:フォントの一覧
fonts = fm.findSystemFonts()
# len(fonts) => 100以上はあるはず
```

```python:データフレームへの詰め込み
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'])
```

```python: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ファイルの展開などは手動で実行しておきましょう。

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

## グラフの描画

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

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

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

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

![graph1.png](https://qiita-image-store.s3.amazonaws.com/0/37996/dbe25ee9-b79b-47f6-fa32-a53087820533.png "graph1.png")


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

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

```python: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](https://qiita-image-store.s3.amazonaws.com/0/37996/4a90a144-afa7-2bf6-7fc3-ac47143bea68.png "graph2.png")


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

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

![graph3.png](https://qiita-image-store.s3.amazonaws.com/0/37996/5b22905a-ed90-acca-21dc-1150e7f87324.png "graph3.png")