MacでMatplotlib がエラーが出たりプロットが表示されないときの対応

MacでPythonつかってグラフを書くとき、[Matplotlib](https://matplotlib.org/) をつかいますよね。で定番なのが、

```
$ cat sample.py
```
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import matplotlib
import matplotlib.pyplot as plt
import sys

def main(args):
    plt.plot([1, 2, 3, 4])
    plt.ylabel('some numbers')
    plt.title('日本語タイトル')
    plt.show()

if __name__ == "__main__":
    main(sys.argv)
```
```
$ python sample.py
```
ってやったときに表示される下記のエラー:

>ImportError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. If you are using (Ana)Conda please install python.app and replace the use of 'python' with 'pythonw'. See 'Working with Matplotlib on OSX' in the Matplotlib FAQ for more information.

がありますが、コイツに対処するには、

```
$ echo "backend : Tkagg" >> ~/.matplotlib/matplotlibrc
```
って Matplotlib の設定ファイルに書きなさいよ、っていう定番対応があります。
参考: [Pythonでmatplotlibをimportするとエラーが出る場合の対処策（Mac）](https://qiita.com/Gen6/items/78d83d117ef67e0d53c2)


ところでわたしの環境だけでしょうか、この対応をするとたしかにUIは表示されるのですが、なぜか下記のような真っ白なUIが表示されてしまいます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/73777/59aa433f-fbe1-c38b-733b-e613194f9347.png)


近くにあるMac(5KのiMacと、MacBookPro)はどれもそうなるんですよね。グラフのUIを外部ディスプレイにドラッグしていくとプロットが表示されたり、逆に外部ディスプレイも4Kのディスプレイだとダメだったり、そういえばどちらのMacもRetinaだったり、、どうも4Kまわりでなんかトラブってるんじゃないかな、、と。

近くに4Kじゃない外部ディスプレイがないとMatplotlibがつかえないとこまるので解決方法を探したところ、結論いうと、Tkagg じゃなくて PyQt5 ってのを指定することで(すくなくとも私の環境では)うまくいったので、そのときの作業メモ。


## 環境をつくって試してみる

まっさらな環境を準備してやってみました。

### 今回の環境
ちなみに今回のMacのバージョンです。

```
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.1 (Mojaveです)
BuildVersion:   18B75
$ python --version
Python 3.7.1
```
Pythonはpyenvでもなんでもよいと思いますが、今回は3.7.1がインストールされた環境です。


### 仮想環境を作る
venvをつかって、独立した環境を作成します。

```
$ python3  -m venv ./venv/
$ source ./venv/bin/activate
(venv) $ pip install numpy
(venv) $ pip install matplotlib
```

### 実行してみる(定番エラーになる)

```
(venv) $ python3 sample.py
Traceback (most recent call last):
  File "sample.py", line 5, in <module>
    import matplotlib.pyplot as plt
  File "/Users/masatomix/git/samples/venv/lib/python3.7/site-packages/matplotlib/pyplot.py", line 2374, in <module>
    switch_backend(rcParams["backend"])
  File "/Users/masatomix/git/samples/venv/lib/python3.7/site-packages/matplotlib/pyplot.py", line 207, in switch_backend
    backend_mod = importlib.import_module(backend_name)
  File "/Users/masatomix/.pyenv/versions/3.7.1/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/Users/masatomix/git/samples/venv/lib/python3.7/site-packages/matplotlib/backends/backend_macosx.py", line 14, in <module>
    from matplotlib.backends import _macosx
ImportError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. If you are using (Ana)Conda please install python.app and replace the use of 'python' with 'pythonw'. See 'Working with Matplotlib on OSX' in the Matplotlib FAQ for more information.
(venv) $
```

### 対処してやってみる(真っ白になる)

```
(venv) $ echo "backend : Tkagg" >> ~/.matplotlib/matplotlibrc
(venv) $ python3 sample.py
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/73777/5508ac70-bf8b-b0fd-1cce-656738850726.png)

ちなみにこの時点で `pip freeze` した結果はこちら。

```
(venv) $ pip freeze
cycler==0.10.0
kiwisolver==1.0.1
matplotlib==3.0.2
numpy==1.15.4
pyparsing==2.3.0
python-dateutil==2.7.5
six==1.11.0
```


### 再度対処してやってみる(解決)

```
(venv) $ pip install PyQt5
(venv) $ rm ~/.matplotlib/matplotlibrc
(venv) $ echo "backend : Qt4Agg" >> ~/.matplotlib/matplotlibrc
```

```
(venv) $ python3 sample.py
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/73777/57284f50-d1f4-dc37-9820-31771f0e95ed.png)

表示されました！


## ついでに日本語を表示可能にする
上記の画面キャプチャは日本語が文字化けしちゃってます。この対処ですが、[Pythonの環境構築と使い方（MacOS）](http://bit.ly/2FQWYwa) をみながら日本語フォント「IPAexゴシック」をインストール後

```
(venv) $ echo "font.family: IPAexGothic" >> ~/.matplotlib/matplotlibrc
(venv) $ python3 sample.py
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/73777/e0be59ff-2766-0634-ed6f-7d93d6a29b1d.png)

これで日本語表示OK！

## その他雑多なTIPS

### 設定ファイル(matplotlibrc)が格納されている場所

```
(venv) $ python3 -c "import matplotlib;print(matplotlib.matplotlib_fname())"
/Users/xxx/.matplotlib/matplotlibrc
```
今回の対応で上記ファイルを作成する前は、

```
/Users/xxx/git/samples/venv/lib/python3.7/site-packages/matplotlib/mpl-data/matplotlibrc
```
が返ってました(venvの環境内のファイル)。オリジナルはココのようですね。このファイルはvenvの環境ごとなので、毎回backend変更対応をしたくない場合は、今回のようにホームディレクトリにファイルを作るのがよさそうです。

環境分離って意味だと、毎回venv内のファイルを修正するほうがよいかもしれません。

### いまどんなbackend？

```
(venv) $ python -c "import matplotlib;print(matplotlib.get_backend())"
Qt4Agg
```
初期状態は

```
(venv) $ python -c "import matplotlib;print(matplotlib.get_backend())"
MacOSX
```
でした。


おつかれさまでした。


## 関連リンク
- [Matplotlib](https://matplotlib.org/) 公式 
- [Pyplot tutorial](https://matplotlib.org/tutorials/introductory/pyplot.html#sphx-glr-tutorials-introductory-pyplot-py) 公式のチュートリアル
- [【Mac】Python 3.6.0 で Matplotlib が動かない時にチェックした点](https://www.atnr.net/how-to-work-matplotlib-on-mac/)
- [pyenvとvirtualenvで環境構築した時にmatplotlib.pyplotが使えなかった時の対処法](https://qiita.com/Kodaira_/items/1a3b801c7a5a41c9ce49)
- [Pythonでmatplotlibをimportするとエラーが出る場合の対処策（Mac）](https://qiita.com/Gen6/items/78d83d117ef67e0d53c2)
- [Pythonで理解する統計解析の基礎](https://amzn.to/2zA4kib) 学生の時(もう20年以上前ですが)統計やってておもろいなーって思ってたんですが、Pythonでシミュレーションしてみるととてもわかりやすい