matplotlibの描画の基本 - figやらaxesやらがよくわからなくなった人向け

matplotlibは、figureやsubplotなどなどがどう働いているのかが分かりにくい。
そこで、ここでは、matplotlibの描画の構造について説明する。

これ以降、matplotlib.pyplotをpltとしてimportしているとする。

```python
import matplotlib.pyplot as plt
```

## plt.figure()
plt.figure()が最初に出てくることが多い。figure()はFigureインスタンスを作成する。
Figureインスタンスは、描画全体の領域を確保する。
引数では以下を指定できる。

- figsize: (width, height)のタプルを渡す。単位はインチ。
- dpi: 1インチあたりのドット数。
- facecolor: 背景色
- edgecolor: 枠線の色

plt.figure()では描画領域の確保だけなので、グラフは何も描画されない。

## fig.add_subplot()
plt.figure()にグラフを描画するためにsubplotを追加する必要がある。
subplotの追加は、add_subplotメソッドを使用する。

```python
fig = plt.figure()
fig.add_subplot(111)
```

これで以下のように軸などのグラフの描画領域が追加される。

![subplot111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7058/0baba330-7bca-c669-6b8a-1f3a3d237e1b.png)

111の意味は、1行目1列の1番目という意味で、subplot(1,1,1)でも同じである。
subplotはAxesオブジェクトを返す。
Axesは、グラフの描画、軸のメモリ、ラベルの設定などを請け負う。

add_subplotは基本的に上書きとなる。以下は、どういう構成化わかりすくするために、わざと上書きしたもの。

```python
fig = plt.figure()
fig.add_subplot(1, 1, 1)
fig.add_subplot(3, 3, 1)   # 3x3の1つめ(左上)
fig.add_subplot(3, 3, 3)   # 3x3の3つめ(右上)
fig.add_subplot(3, 3, 8)   # 3x3の8つめ(真ん中下)
```

![overdraw_graphs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7058/74292ccf-0003-12ee-ce0c-beb191fcf53b.png)


## plt.subplot()
plt.subplot()はadd_subplotと同様に、引数に行数列数及び何番目かを指定できる。
add_subplotとの違いは、現在の描画領域(fig = figure()のこと)に追加するメソッドであるということ。
あまりないと思うが、figure()を何個も立ち上げてるときに、どれを操作しているかわかりにくくなる。

```python
plt.subplot(3,3,1)
plt.subplot(3,3,3)
plt.subplot(3,3,5)
plt.subplot(3,3,9)
```

![subplots.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7058/eab67907-aa14-1977-7df4-9a8504e5e356.png)


subplotはsubplot以前に描画していたfigureとかぶった場合、前のfigureを消す性質を持っている。

```python
plt.plot([1,2,3])
plt.subplot(211)   # このタイミングで plt.plot([1,2,3]) は消されてしまう。
plt.plot(range(12))
plt.subplot(212)
```

## plt.subplots()
plt.subplot()と似たものとしてplt.subplots()もある。
返り値はfigとAxesまたはAxesオブジェクトの配列。

plt.subplots()は実は、fig = figure()をした後、fig.add_subplot(111)した場合と同じである。
subplots()も、add_subplotの場合と同様にAxesオブジェクトを返す。

```python
fig = plt.figure()
plt.add_subplot(111)
```

plt.subplots()の引数に行数列数を与えることで、複数のAxesオブジェクトを生成できる。

```python
fig, axes= plt.subplots(2,2)   # axesはAxesオブジェクトの2x2の配列
axes[0][0].plot([1,2,3])
axes[1][0].plot([4,5,4,5])
```

上記スクリプトの出力結果は以下のようになる。

![2x2subplots.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7058/e2615c09-993f-6d75-5a3c-ac4ef9c68123.png)


## Axes
Axesオブジェクトは、実際のデータの描画の役割を持っている。
Axesオブジェクトに対して描画するデータを与えたり、set_xlabel、set_ylabel、set_titleで
ラベルやタイトルの設定をできる。
また、同じAxesオブジェクトにplotを重ねることもできる。

```python
ax1 = plt.subplot(2,2,1)   # 4x4の1番目
ax4 = plt.subplot(2,2,4)   # 4x4の4番目
ax1.plot([1,2,3,4])   # 1番目に描画
ax1.plot([2,3,2,3])   # 1番目に追加描画
ax1.set_xlabel('foo')   # 1番目にxラベルを追加
ax1.set_ylabel('bar')   # 1番目にyラベルを追加
ax4.plot([5,10,20,10])   # 4番目に描画
ax4.set_title('baz')   # 4番目にタイトルを追加
```

![axes_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7058/e823fe8e-e439-7357-0b68-c041daf06763.png)

## plt.title()、plt.xlabel()、plt.ylabel()
グラフを1つずつ描画しているときは、plt.title()、plt.xlabel()、plt.ylabel()をよく使うのだが、
結局これは何かというと、ax = subplot(111)にたいして、ax.set_title()、ax.set_xlabel()、ax.set_ylabel()
とやっていることと同じとなる。

## plt.gcf()
figureをたくさん立ち上げているとどのfigureにいるかわからなくなることがある。
現在のfigureを確認するためにはplt.gcf()を使う。gcfはget current figureの略。
以下の例ではそれぞれplt.gcf()の出力結果が変わることが分かる。

```python
fig1 = plt.figure()
print(plt.gcf().number)   # => 1
fig2 = plt.figure()
print(plt.gcf().number)   # => 2
plt.close()
print(plt.gcf().number)   # => 1
```

## plt.gca()
plt.gcf()と似た関数でplt.gca()がある。
これは、現在のAxesオブジェクトを返す。
ax = subplot(111)でやらずにあとからAxesオブジェクトを変数に定義できる。

```python
plt.subplot(111)
ax = plt.gca()
```