Pythonで〇×ゲームのAIを一から作成する　その65　matplotlib による画像の描画の基本

# 目次と前回の記事

https://qiita.com/ysgeso/items/2381dd4e3283cbed49a0

https://qiita.com/ysgeso/items/10d1d01192c014173e4b

## これまでに作成したモジュール

以下のリンクから、これまでに作成したモジュールを見ることができます。

https://github.com/ysgeso/marubatsu/blob/master/065/marubatsu.py

https://github.com/ysgeso/marubatsu/blob/master/065/ai.py

## ルールベースの AI の一覧

ルールベースの AI の一覧については、下記の記事を参照して下さい。

https://qiita.com/ysgeso/items/10d1d01192c014173e4b

# 〇×ゲームの GUI

これまでは、作成した __〇×ゲーム__ を __`play`__ メソッドで __遊ぶ際__ に、__ゲーム盤の表示__ と、__着手__ を行う __座標の入力__ を __文字__ で行ってきました。[以前の記事](https://qiita.com/ysgeso/items/1b7b1abe942e2d10c0b4#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)で説明したように、そのような、__文字だけ__ で __入出力__ を行う __ユーザインターフェース__ のことを __CUI__ と呼びます。

__CUI__ は __プログラム__ の __作成__ を __比較的簡単__ に行うことができるという __利点__ がありますが、__表示__ や __入力__ が __わかりづらい__ という __欠点__ があります。そこで、今回の記事からしばらくは、__ゲーム盤の表示__ を __画像__ で行い、__座標の入力__ を、表示された __画像__ に対してクリックなどの __操作__ で行うという、__GUI__ で __〇×ゲーム__ を __遊べるよう__ にします。

__GUI__ のアプリケーションを __作成__ するためには、__画像を表示__ するプログラムを __記述__ す __必要__ が __あります__。__Python__ では、__画像を表示__ するための __様々なモジュール__ がありますが、本記事では、その中でグラフを描画する際に良く使われる __matplotlib__ を利用することにします。

:::note
__他__ の __画像__ や __GUI__ を扱う __モジュール__ に興味がある方は、__Python__、__画像__、__GUI__、__モジュール__ などを __キーワード__ に __検索__ してみると良いでしょう。
:::

# matplotlib

__matplotlib__ は、__静止画__ や __動画___ などを __作成__ したりすることができる Python の __モジュール__ で、特に、折れ線グラフ、棒グラフ、散布図など、__様々なグラフ__ を __簡単に作成__ することが __できる__ ので、Python のモジュールの中で、__人気のあるモジュール__ です。

本記事では、以下のような理由から、__matplotlib__ を利用することにしました。

* __Python__ の __モジュール__ の中でも、__最も良く使われる__ ものの __一つ__ である
* __今後の記事__ で __グラフ__ を __描画__ する __機会__ がある
* グラフだけでなく、__任意の図形__ や __文字列__ を __描画できる__ 
* __アニメーション__（動画）を __作る機能__ がある
* __JupyterLab__ 上で簡単に __利用できる__

下記は matplotlib のサイトのリンクです。

https://matplotlib.org/

## matplotlib のインストール

これまでの記事で利用してきた __collections など__ の __モジュール__ は、__Python__ を __インストールした際__ に __自動的__ に __インストール__ される、__組み込みモジュール__ と呼ばれるものです。

一方、__matplotlib__ など、__個人__ や __団体__ などが __作成__ した __モジュール__ を __利用__ するためには、そのモジュールを __インストール__ する __必要__ が __あります__。

__モジュール__ を __インストール__ する __方法__ には、様々な方法がありますが、本記事では、__Anaconda Navigator__ を __利用__ する、__下記の方法__ を __紹介__ します[^1]ので、matplotlib をインストールしていない方は、__下記の手順__ に従って __インストール__ して下さい。

1. __Anaconda Navigator__ を立ち上げる
2. 左の __Environments__ を __クリック__ して表示される __仮想環境の一覧__ から __marubatsu__ を __クリック__ すると、右に __marubatsu__ の __仮想環境__ に __インストール__ されている __モジュールの一覧__ が __表示__ される
3. __上のメニュー__ から「__Not installed__」を __選択__ し、その右の「__Search packages__」と表示された __テキストボックス__ に「__matplotlib__」を __入力__ する
4. 下に __matplotlib[^2] が表示__ されるので、その __左のチェックボックス__ を __チェック__ し、下の「__Apply__」__ボタン__ を __クリック__ する。    
5. 「__Install packages__」という __パネルが表示__ され、しばらく待つと「__Apply__ 」__ボタン__ がクリックできるようになるので __クリック__ する。 

しばらく待つとインストールが完了します。

:::note
やり方を知っている方は、Anaconda Powershell Prompt などから conda や pip などのコマンドを利用して matplotlib をインストールして構いません。
:::

## matplotlib のインポート

[以前の記事](https://qiita.com/ysgeso/items/44c65c4bbec49cff7d77#%E4%BB%AE%E6%83%B3%E7%92%B0%E5%A2%83%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B)で説明したように、Python では、__モジュール__ と __パッケージ__ という __用語__ が、__同じ意味__ で __使われる__ ことがありますが、__厳密__ には下記のように __意味が異なります__。__matplotlib__ は __パッケージ__ なので、__複数のモジュール__ から __構成__ されます。

* __モジュール__ は、__Python__ の __プログラムが記述__ された __ファイル__
* __パッケージ__ は、__複数__ の __Python のプログラム__ である __モジュール__ を __まとめたもの__

__パッケージ__ の中の __特定のモジュール__ を __インポート__ する場合は、下記のプログラムのように、__パッケージ名__ の __後__ に __半角__ の __.__ （ピリオド）で __区切ってモジュール名__ を __記述__ します。

```python
import パッケージ名.モジュール名
```

__matplotlib__ を __利用__ する際には、__pyplot__ という __モジュール__ を __インポート__ する __必要__ が __あります__。ただし、__pyplot モジュール__ を __利用__ する際に、毎回 __pyplot__ を __記述__ するのは __面倒__ なので、__一般的__ には下記のプログラムのように、__`plt`__ という __名前__ で __インポート__ します。

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

__matplotlib__ の __他のモジュール__ に関しては、__必要に応じてインポート__ します。

__pyplot__ モジュールの詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/pyplot_summary.html#

## グラフの描画方法

__matplotlib__ は、__グラフを描画__ するために __良く使われる__ ので、最初に、折れ線グラフと散布図の __グラフを描画__ する __方法__ を __紹介__ します。

__折れ線グラフ__ は、__pyplot__ の __`plot`__ という __メソッド__ を使って __描画__ します。下記は、__(1, 6)__、__(2, 2)__、__(3, 7)__、__(4, 5)__、__(5, 9)__ の __5 つの点__ を結ぶ __折れ線グラフ__ を __描画__ するプログラムです。

__`plot`__ メソッドに記述する __2 つ__ の __実引数の意味__ は、以下の通りです。

* 折れ線グラフの __頂点__ の __x 座標__ を __要素__ として持つ __list__ などの __シーケンス型__
* 折れ線グラフの __頂点__ の __y 座標__ を __要素__ として持つ __list__ などの __シーケンス型__

```python
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
```

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/d326ea64-93c0-bddf-0608-5ae09a6b049c.png" width="250">

:::note
__matplotlib__ では、__それぞれの座標__ を __(1, 6)__ のように __記述__ するの __ではなく__、それぞれの座標を __x 座標__ と __y 座標__ に __分けて記述__ する点に __注意__ して下さい。
:::

:::note
__プロット__（plot）とは、__データ__ を __図などで表す__ ことを意味する __英語__ です。__plot__ という __単語__ には、__折れ線グラフ__ という __意味はない__ 点に注意して下さい。これは __筆者__ の __勝手な想像__ なのですが、おそらく、代表的なグラフが、折れ線グラフなので、折れ線グラフを描画するメソッドの名前を `plot` にしたのではないかと思います。
:::

__pyplot__ モジュールには、__`plot` 以外__ にも、__様々なグラフ__ を __描画__ するための __メソッド__ が __用意__ されており、__グラフ__ の __データを用意__ して、それらの __メソッド__ を __呼び出すだけ__ で、__簡単__ に __グラフを描画__ することが __できるよう__ になっています。例えば、__散布図__ というグラフは、下記のプログラムのように、__`scatter`__ という __メソッド__ を呼び出すことで __簡単に描画__ することが __できます__。なお、__実引数__ に記述した __データ__ は、先程の __`plot`__ の例と __同じ__ です。

```python
plt.scatter([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
```

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/fcff1bfb-b378-cfe4-3ca4-74b4b17c99ed.png" width="250">

__pyplot__ モジュールの、__グラフを描画__ する __メソッド__ の __一覧__ と __詳細__ ついては、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/pyplot_summary.html#adding-data-to-the-plot

### 警告メッセージが出る場合の対象方法

__上記__ のプログラムを __実行__ した際に、下記のような __警告メッセージ__ が __表示__ される __場合__ が __あります__。これは、__matplotlib__ が __利用__ する __フォント__ が __インストールされていない__ ことを表します。この __警告メッセージ__ が __表示されない場合__ は、__以下の内容__ は __無視__ して下さい。

```
findfont: Font family 'IPAexGothic' not found.
```

__上記__ のような __警告メッセージ__ が __表示__ される場合は、グラフに __日本語__ を __表示__ しようとした場合に、下記のプログラムのように __文字化け__ が __発生__ してしまします。なお、__2 行目__ の __`plt.title`__ は、__グラフ__ に __タイトルを表示__ する __メソッド__ で、__実行結果__ の __上部__ に __表示__ される __□□□__ は、「__テスト__」という __文字列__ が __文字化け__ したものです。

```python
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.title("テスト")
```

実行結果

<details><summary><strong>修正箇所</strong></summary>

```diff_python
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
+plt.title("テスト")
```
</details>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/572743a5-db3e-3065-f391-3e0cc2eea274.png" width="250">

__文字化け__ が __起きない__ ようにする __方法__ として、__フォント__ を __インストール__ し、__matplotlib__ の __設定を編集__ するという __方法__ がありますが、__少々面倒__ なので、__別の方法__ を __紹介__ します。

:::note
__フォント__ を __インストール__ する __方法__ を行いたい人は、上記の __警告メッセージ__ を __キーワード__ にして __検索__ するとその方法の手順が見つかると思います。
:::

本記事で紹介する方法は、__japanize-matplotlib__ という、__matplotlib__ を __日本語化__ する __モジュール__ を __インストール__ するという方法です。なお、__このモジュール__ は、__Anaconda Navigator__ や、__conda__ という __コマンド__ では __インストール__ することが __できない__ ようなので、__下記の手順__ で __pip__ という __コマンド__ を使って __インストール__ する __必要__ が __あります__。

1. スタートメニューから、「__Anaconda Powershell Prompt (anaconda3)__」を探して __実行__ する
2. __`conda activate marubatsu`__ を __入力__ して、__marubatsu__ の __仮想環境に入る__
3. __`pip install japanize-matplotlib`__ を __入力__ して __エンターキーを押す__

__インストール後__ に、__下記__ のプログラムのように、__japanize_matplotlib__[^3] を __インポートする__ と、__警告メッセージ__ が __表示されなく__ なり、__日本語の文字__ も __表示される__ ようになります。

```python
import japanize_matplotlib

plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.title("テスト")
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
+import japanize_matplotlib

plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.title("テスト")
```
</details>


実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/e44707b4-146c-7436-efd3-342e3a7a55d0.png" width="250">

__本記事__ では、__以後__ は __japanize_matplotlib__ を __インポート__ しますが、__japanize_matplotlib__ を __インストールしない__ 場合は __`import japanize_matplotlib`__ を __記述しない__ ようにして下さい。

下記は、__japanize‐matplotlib__ のサイトのリンクです。

https://pypi.org/project/japanize-matplotlib/

# matplotlib の仕組み

__matplotlib__ で __グラフを描画__ する場合は、先程のプログラムのように、__描画__ する __グラフの種類__ に __対応__ する __pyplot__ の __メソッドの使い方__ を __学べば良い__ のですが、__〇×ゲーム__ の __ゲーム盤__ は、__グラフを描画__ する __メソッドだけ__ では __描画できません__。

__本記事__ では、__matplotlib__ の __簡単な仕組み__ について __説明__ し、__matplotlib__ を __使って__、__図形__ や __文字列__ を __組み合わせる__ ことで、__〇×ゲーム__ の __ゲーム盤の画像__ を __描画する方法__ について __説明__ します。従って、__matplotlib__ の __入門ページ__ などで __紹介__ される、__グラフを描画__ するための __様々な機能__ については、__今回の記事__ では __説明しません__。

なお、__今後の記事__ で __matplotlib__ で __グラフを描画__ する __機会__ は __あります__ ので、__matplotlib__ で __グラフを描画__ する __方法__ に関しては、__その際に紹介__ します。

なお、__matplotlib__ は非常に __豊富な機能__ を __持つ__ ので、__本記事だけ__ で __すべて__ の __仕組み__ や __使い方__ を __説明__ することは __不可能__ です。__興味がある方__ は、__matplotlib__ を __説明__ する __インターネットの記事__ や __書籍__ などが豊富にあるので、それらを __参考にすると良い__ でしょう。

## matplotlib の用語と簡単な仕組み

下記は、__matplotlib__ の __仕組み__ を __理解__ するために __特に重要__ となる __用語__ です。それぞれの意味についてはこの後で説明します。

| 用語 | 意味 |
|:--|:--|
| __Figure__  | __matplotlib__ で __描画する画像__ に関する __データ__ を __管理__ する __オブジェクト__  |
| __plot__、__subplot__ | __Figure__ が __表す__ する __画像の中__ で、__Figure__ に __登録したデータ__ を __実際に描画__ する __範囲__ を表す __用語__。__Axes__ によって __管理される__。__複数__ の __plot が存在__ する場合は、__一つ一つ__ の __plot__ を __subplot__ と __呼ぶ__
| __Axes__  | __plot__（または __subplot__）を __管理__ する __オブジェクト__。__plot の中__ の __座標__ を __x 軸__ と __y 軸__[^4]などを使って __管理__ する __機能__ などを持つ  |
| __Artist__  | __画像__ に __表示__ する __図形__ や __文字列__ などを表す __オブジェクト__。__Axes__ を __含め__、__画像__ に __描画__ される __データ__ は __すべて Artist__ の __一種__ である  |

:::note warn
__紛らわしい__ ですが、上記の表の __plot__ という __用語__ と、折れ線グラフを描画する、__pyplot__ モジュール の __`plot` メソッド__ は __異なるもの__ である点に __注意__ して下さい。

本記事では、__`plot` メソッド__ の場合は、__文字__ を __網掛けにする__ ことで __区別__ します。
:::

### 画像の描画の手順

__matplotlib__ では、__以下__ のような __手順__ で __画像の描画__ を行います。

1. __Figure__ という、__描画する画像__ に関する __データ__ を __管理__ する __オブジェクト__ を __作成__ する
2. __plot__ を __管理__ する __Axes__ という __オブジェクト__ を __作成__ し、__Figure に登録__ する
3. __図形__ や __文字列__ などを表す __Artist__ を __作成__ し、__Axes__ に __登録する__
4. __Figure__ に __登録__ された __Artist__ を __描画__ する __メソッド__ を __呼び出し__ て、__画像を描画__ する

:::note
__勘違いされやすい__ のですが、__画像の描画__ は、図形や文字列を表す __Artist__ を __作成__ し、__Axes__ に __登録した時点__ では __行われず__、上記の __手順 4__ で __まとめて行われます__。その理由は、__Artist__ を __作成して登録するたび__ に __描画を更新__ するという __処理__ は __効率が悪く__、Figure に登録された Artist を __まとめて描画__ したほうが __効率が良い__ からです。

ただし、__そのこと__ を __理解していなくても__、ほとんどの場合は、グラフや図形などの描画を行う __プログラムの記述__ には __影響はない__ ので、このことの __意味が分からなくても__、__当面__ は __気にしなくても構いません__。
:::

__先程紹介__ した、__pyplot__ の __`plot`__ や __`scatter`__ 等の __グラフを描画__ する __メソッド__ は、__上記__ の __手順 1 ~ 3__ を __まとめて行う機能を持つ__ ので、よくある __定型的なグラフ__ であれば、__上記の手順__ を __意識する必要__ は __ありません__。しかし、__凝ったグラフ__ を __描画したい場合__ や、__〇×ゲーム__ の __ゲーム盤__ のような、__グラフを描画__ する __メソッドだけ__ で __描画できない__ ような __画像__ を描画したい場合は、__上記の手順__ について __理解__ する __必要__ が __あります__。

なお、__JupyterLab__ で __プログラムを実行__ する場合は、上記の __4 番目の手順__ は、__JupyterLab__ の __セルを実行後__ に、__自動的に実行__ されるので __プログラムの記述__ を __省略できます__。先程のプログラムで、__`plot`__ メソッドを __実行しただけ__ で __グラフ__ が __描画された__ のは __そのため__ です。

おそらく上記の説明では、意味が分からない人が多いと思いますので、それぞれの手順を具体例を挙げながら説明します。

## Figure の作成

__Figure__ は __matplotlib__ で __描画する画像__ に関する __データ__ を __管理__ する __オブジェクト__ のことで、__matplotlib__ では、__描画する画像ごと__ に __Figure を作成__ する __必要__ が __あります__。

__`plot`__ や __`scatter`__ などの、__グラフを描画__ する __メソッド__ には、__自動的__ に __Figure__ を __作成する機能__ が __備わっている__ ので、__それらのメソッド__ を __利用する場合__ は、__自分__ で __Figure__ を __作成する必要__ は __ありません__。ただし、__自動的に作成__ された __Figure__ は、__あらかじめ決められ__ た __設定__ で __作成される__ ので、__自分好み__ の __設定__ の __Figure__ を __作成したい__ 場合は、__自分__ で __Figure__ を __作成する必要__ が __あります__。

__自分__ で __Figure__ を __作成__ する場合は、__pyplot__ モジュールの __`figure`__ メソッドを __利用__ します。__`figure`__ メソッドは __返り値__ として、__作成__ した __Figure__ の __オブジェクト__ を __返します__。

下記は、__`figure`__ メソッドの __主な仮引数__ とその __意味__ です。__下記__ の __仮引数__ は、__デフォルト引数__ になっているので、下記の表では __デフォルト値__ を __表記__ しました。また、__matplotlib__ では、__色__ を __様々な方法__ で __設定__ できますが、__その中__ に、下記の表のデフォルト値のように、色を __英単語で設定__ するという __方法__ があります。他の設定方法についてこの後で紹介します。

| 仮引数 | 意味 | デフォルト値 |
|:--|:--|:--|
| __`figsize`__  | __作成__ する __画像__ の __幅__ と __高さ__ を __要素__ として持つ __list__<br>__数字__ の __単位__ は __インチ__   | __`[6.4, 4.8]`__ |
| __`facecolor`__<br>または __`fc`__  | __作成__ する __画像__ の __背景色__  | __`"white"`__ |

下記は、__`figsize`__ と __`facecolor`__ を __設定__ して、先程と同じ折れ線グラフを描画するプログラムです。__`figsize`__ の __幅と高さ__ を __同じ値__ に __設定__ したため、__画像__ が __正方形__ になります。なお、__作成__ した __Figure__ を __代入__ する __変数の名前__ には、__`fig`__ という __名前__ が __良く使われます__。

* __1 行目__：__画像のサイズ__ を __3 × 3__、__背景色__ を __水色__（lightblue）に __設定__ した __Figure__ の __オブジェクト__ を __作成__ し、__`fig`__ という __名前__ の __変数__ に __代入__ する

```python
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
+fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
```
</details>

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/4067a316-1c3f-9fe7-efba-6c0c21adeb67.png" width="150">

:::note
本記事では、__`fig`__ に代入した Figure のデータを利用しませんが、__Figure__ の __メソッドを利用__ することで、__Figure__ の __作成後__ に、__設定__ を __変更__ することが __できます__。
:::

なお、__`figure`__ メソッドによって __作成__ された __Figure__ は、__pyplot モジュール__ が __自動的__ に __管理する__ ので、上記のプログラムのように __変数__ に __代入しておかなくても__、__pyplot__ の __メソッド__ を __利用__ することで __後から取得__ することも __できます__。

また、今回の記事では行いませんが、__Figure__ を __複数作成__ することで、__複数の画像__ を __同時に作成__ することも __できます__。

__`figure`__ メソッドの詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.figure.html

## Axes

__作成したばかり__ の __Figure__ には何の __データ__ も __登録されていない__ ので、__下記__ のプログラムのように、__Figure__ を __作成するだけ__ では __何も描画__ は __行われません__。__画像を描画__ するためには、少なくとも 1 つの __Axes を作成__ して、__Figure に登録__ する __必要__ が __あります__。

```python
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
```

実行結果

```
<Figure size 300x300 with 0 Axes>
```

:::note
__実行結果__ に表示されるメッセージは、作成した __Figure__ が、__大きさ__ が __300 x 300__ の __画像__ で __Axes__ が __1 つも登録されていない__ ことを __表します__。
:::

### Axes とは何か

__画像を描画__ する際には、__Figure__ が __作成する画像__ の __どの範囲__ に、__Figure__ に __登録したデータ__ を __描画するか__ を __決める必要__ があります。

このように説明すると、__画像全体__ に __描画すればよい__ と __思う人__ が __多いのではないか__ と思いますが、__画像全体__ に __描画してはいけない__ 場合が __あります__。

具体的には、先程のプログラムで描画した下記のグラフを見て下さい。__この画像__ の中で、__グラフのデータ__ が __描画__ される __範囲__ は、__画像全体__ ではなく、__背景__ が __白い正方形の範囲__ に __限定されます__。下記の __白い正方形__ の __範囲__ のように、グラフのデータなどを __実際に描画__ する __範囲__ の事を __plot__ と呼び、__plot を管理__ するのが __Axes__ という __オブジェクト__ です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/4067a316-1c3f-9fe7-efba-6c0c21adeb67.png" width="150">

__matplotlib__ では、基本的には __Axes を作成__ し、__Figure に登録__ することではじめて、__画像__ が __描画される__ という __仕組み__ になっています。

### Axes の作成と登録

__Axes__ は、__下記__ のプログラムのように、__pyplot__ の __`subplot`__ という __メソッドを実行__ することで __作成__ することが __できます__。また、__作成__ した __Axes__ は、__pyplot__ が __管理__ する __Figure__ に __自動的に登録__ されます。なお、__作成__ した __Axes__ を __代入__ する __変数の名前__ には、__`ax`__ という __名前__ が __良く使われます__。

```python
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
ax = plt.subplot()
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
+ax = plt.subplot()
```
</details>


実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/0513d790-d358-5961-4b1a-2a3f193c43bc.png" width="150">

__実行結果__ からわかるように、__Axes__ を __作成__ し、__Figure__ に __登録__ することで、__画像が描画__ されるようになります。なお、__Figure__ には、作成した Axes 以外の __データ__ は __登録されていない__ ので、__plot__ の __白い正方形__ の __部分__ には __何も表示されません__。なお、上図のように、__Axes__ は __Figure__ に __描画される__ ものの一つなので、__Axes__ も __Artist__ の __一種__ に __分類__ されます。

:::note
__`plot`__ や __`scatter`__ などの __グラフを描画__ する __メソッド__ には、__自動的__ に __Axes を作成__ し、__Figure に登録__ する __機能__ が __備わっている__ ので、それらのメソッドを利用する際には、__自分__ で __Axes__ を __作成する必要__ は __ありません__。
:::

:::note
作成した __Axes__ に __対応__ する __plot__ が、__画像__ の __どこに配置されるか__ については、__自動的__ に __設定されます__ が、__自分__ で __好みの位置__ と __大きさ__ に __設定__ することもできます。
:::

__`subplot`__ メソッドの詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplot.html

### Axes の他の役割

__Axes__ には、__plot を管理__ する __以外__ にも __以下__ のような __重要な役割__ があります。

* plot の __内部の座標__ を __x 座標__ と __y 座標__ などで __管理__ する
* __Artist__ を、__Axes__ が __管理__ する __座標__ を使って __登録__ する 
* plot に __表示__ する __座標の範囲__ を __管理__ する
* plot の __枠__ と __外側__ に __表示__ する __目盛り__ など[^5]の __Artist__ を管理する

それぞれについて、詳しく __説明__ します。

#### plot の内部の座標の管理

__Figure__ に __登録__ した __図形__ や __文字列__ などを __描画__ するためには、__図形__ や __文字列__ の __位置__ や __大きさ__ を __指定する必要__ が __あります__ が、そのためには、__位置__ や __大きさ__ の __基準__ となる __座標__ が __必要__ になります。__2 次元__ の __画像__ の場合は、__一般的__ に __x 軸__ と __y 軸__ を使って __座標__ や __大きさ__ を __表現__ しますが、__matplotlib__ では __それら__ を __Axes__ という __オブジェクト__ で __管理__ します。

具体的には、__Axes__ は __plot__ の __内部の座標__ を __x 軸__ と __y 軸__ による __座標__ で __管理__ します。このように、__Axes__ は __複数の軸__ を __管理__ することから、__軸__ を表す __単語__ である __axis__ の __複数形__ の __axes__ が __名前の由来__ になっています。

:::note
今回の記事では使用しませんが、__Axis__ という、__一つの軸__ を表す __Artist__ があります。__名前__ が Axes と似て __紛らわしい__ ので、__混同しないよう__ に __注意__ して下さい
:::

#### Artist の登録

__Figure__ そのものは、__画像__ の __内部__ の __座標を管理__ する __機能__ を __持たない__ ので、__Figure__ に __図形__ や __文字列__ などの __Artist を登録__ する際には、__座標を管理__ する __機能を持つ__、__Axes に__ 対して __Artist__ を __登録__ します。また、__Axes__ に対して __登録__ された __Artist__ は、その __Axes__ の __plot の中__ に __描画__ されます。従って、__Figure__ に __登録__ する __Artist__ は、下記の __階層構造__ になります。

* __Figure__ に __Axes を登録__ する
* __Axes__ に __Artist を登録__ する

__具体的__ な __プログラムの例__ については、__Artist__ の __作成と登録__ の __説明__ の所で行います。

#### plot に描画する表示範囲の管理

__plot__ は __有限の大きさ__ を持つ __長方形__ なので、__plot__ が __描画__ する __座標の範囲__ も __有限__ になります。そのため、__Axes__ は、__plot__ に __描画__ する __座標の範囲__ を __管理__ する __機能__ を持ちます。

__plot__ に __描画__ する __座標の範囲__ を __変える__ と、__描画__ される __Artist__ の __大きさ__ が __変わったり__、__Artist__ の __一部__ または __すべて__ が __plot__ に __表示されない場合__ が __生じます__。

:::note
分かりづらいと思った人は、__ウィンドウ__ と、ウィンドウ内の __表示__ の __拡大縮小__ の __機能__ を思い浮かべてみて下さい。例えば、__一般的__ な __ウェブブラウザ__ は、__Ctrl キー__ を __押しながら__、__マウス__ の __ホイール__ を __回転__ すると、__表示__ の __大きさ__ を __拡大・縮小__ することが __できます__。__表示__ を __拡大__ すると、ウィンドウに __表示__ される __範囲__ が __せまく__ なり、ウェブページの __一部の内容__ が __画面__ に __表示されなく__ なります。
:::

下図は、先程の __Axes__ を __作成__ したプログラムの __実行結果__ です。図からわかるように、__Axes__ は、__初期設定__ では、__plot__ の __表示範囲__ は、__x 座標__ と __y 座標__ が __0 ~ 1__ の __範囲__ に __設定__ されます。なお、__数学__ の __グラフ__ の軸と __同様__ に、__横方向__ が __x 軸__ で、__縦方向__ が __y 軸__ です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/0513d790-d358-5961-4b1a-2a3f193c43bc.png" width="150">


__Axes__ が __管理__ する __plot__ の __表示範囲__ は、__`set_xlim`__ と __`set_ylim`__ メソッドを使って __変更__ することが __できます__。__実引数__ には、それぞれの __範囲__ の __最小値__ と __最大値__ を記述し、__下記__ のプログラムのように記述することで、__x 座標__ と __y 座標__ の __表示範囲__ が __-1 ~ 1__ になります。

```python
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
ax = plt.subplot()
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
ax = plt.subplot()
+ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
+ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```
</details>

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/700e9bd4-90ab-9d46-c1d2-ec75cb2c3b47.png" width="150">

:::note
__`plot`__ や __`scatter`__ などの __グラフを描画__ する __メソッド__ には、下記の __`plot`__ メソッドによって __作成されたグラフ__ からわかるように、__Axes__ の __表示範囲__ を、__グラフ__ の __データ__ から __自動的に設定__ する __機能__ が __備わっています__。そのため、それらのメソッドを利用する際には、__自分__ で __Axes__ の __表示範囲__ を __設定する必要__ は __ありません__。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/4067a316-1c3f-9fe7-efba-6c0c21adeb67.png" width="150">
:::

__`set_xlim`__ と __`set_ylim`__ メソッドの詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html

https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_ylim.html

#### 枠と目盛りの管理

__Axes__ は、__plot__ の __枠__ や、__枠の外側__ の __目盛り__ なども __管理__ するので、__Figure を描画__ すると、自動的に __plot__ の __枠__ や __目盛り__ も __表示__ されます。

__グラフを描画__ する際には __必須__ となる、__枠__ と __目盛り__ は、__〇×ゲーム__ の __ゲーム盤__ を __描画__ する際には __邪魔__ になります。__枠__ と __目盛り__ は、下記のプログラムのように、__Axes__ の __`axis`__ メソッドの __実引数__ に __`"off"`__ を __記述__ して __実行__ することで __表示しない__ ように __できます__。

```python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
ax.axis("off")
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
+ax.axis("off")
```
</details>


実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/2b83aef6-bc16-1975-70b0-1a0bbfe108d8.png" width="150">

__実行結果__ からわかるように、__枠__ と __目盛り__ だけでなく、__plot__ の __白い部分__ も __表示されなくなります__ が、__plot の範囲__ が __見えなくなっただけ__ で、__plot そのもの__ は __元の位置__ に __存在__ しています。従って、__枠__ と __目盛り__ を __表示しないよう__ にしても、下記のプログラムのように、__Axes__ に __登録__ した __Artist__ は問題なく __表示されます__。

```python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
ax.axis("off")
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
+plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
ax.axis("off")
```
</details>


実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/8f4e8dec-87bc-3f6a-a286-b1829c8534f1.png" width="150">

### Figure と Axes の一括作成

上記のプログラムでは、__Figure__ を __作成__ してから __Axes__ を __作成__ して __登録__ しましたが、__Figure__ を使って __画像を描画__ するためには、__Axes__ を __作成__ して __Figure__ に __登録__ する __必要__ があるので、その __2 つの処理__ を __まとめて__ 行う __`subplots`__ という __メソッド__ が __用意__ されています。

__`subplots`__ メソッドは、__下記__ の __処理__ を行います。

* __Figure__ を __作成__ して __pyplot__ モジュールに __登録__ する
* __Axes__ を __作成__ して、上記で作成した __Figure__ に __登録__ する
* __返り値__ として、上記で __作成__ した __Figure__ と __Axes__ を __要素__ として持つ __tuple__ を __返す__

また、__`subplots`__ メソッドは、__下記__ のプログラムのように、__`figure`__ メソッドと __同じキーワード引数__ を使って、__Figure__ の __画像のサイズなど__ を __設定__ することが __できます__。

下記のプログラムは、__先程__ のプログラムと __同じ処理__ を行うプログラムです。

```python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
-fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
-ax = plt.subplot()
+fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```
</details>


実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/700e9bd4-90ab-9d46-c1d2-ec75cb2c3b47.png" width="150">

:::note warn
__`subplot`__ と __`subplots`__ は __名前__ は __似ています__ が、__全く異なる処理__ を行うメソッドである点に __注意__ して下さい。
:::

__`subplots`__ メソッドの詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots.html

### 複数の Axes の設定

__本記事__ では、__しばらくの間__ は、__Figure__ に __複数__ の __Axes の登録__ を __行わない__ ので、__興味がない方__ はこの部分は __読み飛ばして__ も __構いません__。

__`subplots`__ メソッドを利用することで、__Figure__ に、__複数__ の __Axes__ を __登録__ することが __できます__。その場合は、__Figure__ が __作成__ する __画像の中__ に、__複数__ の __plot__ が __作成__ され、__それぞれ__ の __plot__ を __subplot__ と呼びます。

__それぞれ__ の __subplot__ は __下記__ のような __性質__ を __持ちます__。

* __異なる Axes__ によって __管理される__
* それぞれの __Axes__ に対して、__Artist__ を __登録__ できる
* __Axes__ に __登録__ された __Artist__ は、__その Axes__ に __対応__ する __subplot__ に対して __描画__ される

上記の性質から、__subplot__ を __利用__ することで、__下記__ のプログラムのように、__1 つの画像__ の中に、__異なる 2 つ__ の __グラフ__ を __並べて描画__ することが __できる__ ようになります。

```python
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=[6, 3], facecolor="lightblue")
ax1.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
ax2.scatter([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
```

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/a3097b06-22a9-d71c-1449-0c743c7982ad.png" width="300">

上記のプログラムの詳細な説明を行うと長くなるので、__今回の記事__ では __簡単な説明__ に __とどめます__。興味がある方は、`subplots` で検索して調べてみて下さい。なお、今後の記事で上記のような画像を実際に作成する必要が生じた際に詳しく説明します。

__上記__ のプログラムでは、__1 行目__ で __`subplots`__ を使って、__画像の中__ に __subplot__ を __横に 2 つ並べた__、__2 つ__ の __Axes__ を __作成__ しています。また、__作成__ した __2 つ__ の __Axes__ は、__`ax1`__ と __`ax2`__ という __2 つの変数__ に __代入__ しています。なお、__2 つのグラフ__ を __並べて表示__ できるように、__画像__ の __横幅__ を __縦幅の倍__ に __設定__ しました。

__2、3 行目__ では、__それぞれ__ の __Axes__ に対して、__別々__ に __`plot`__ と __`scatter`__ メソッドを使って __折れ線グラフ__ と __散布図__ を __描画__ しています。その結果、__実行結果__ のように、__2 つのグラフ__ を __並べた画像__ を __作成__ することが __できます__。

### pyplot のメソッドと Axes のメソッド

今回の記事の最初では、__折れ線グラフ__ を __描画__ する際に、__pyplot__ の __`plot`__ メソッドを __利用__ しましたが、上記のプログラムのように、__Axes__ にも __`plot`__ メソッドが __あります__。

:::note warn
__`plot` 以外__ にも、__多くのメソッド__ が __pyplot__ と __Axes__ で __共通__ し、__Figure__ に __1 つ__ しか __Axes__ を __登録__ しない __場合__ は、__基本的__ に __どちら__ を使っても __かまいません__。

ただし、__一部の__ メソッドは、__名前が異なったり__、__片方__ にしか __存在しない__ 場合があるので、そのような __メソッド__ を __利用する場合__ は __使い分ける必要__ があります。例えば先程紹介した __`set_xlim`__ という __Axes__ のメソッドは、__pyplot__ では __対応__ する __メソッド__ は __`xlim`__ という __名前__ で、__微妙__ に __行う処理__ が __異なります__。また、この後で説明する、__Artist を登録__ する __メソッド__ は、__pyplot__ には __ありません__。

__本記事__ では __基本的__ には、__Axes__ の __メソッドを利用__ することにします。
:::

matplotlib を使ったことがある人の中でも、この __2 つ__ の __`plot`__ メソッドの __違い__ が __分かりづらい__ と __思っている__ 人が __いるのではないか__ と思いますので、__簡単に説明__ します。

先程も説明しましたが、__本記事__ では、__しばらくの間__ は、__Figure__ に __複数__ の __Axes の登録__ を __行わない__ ので、__興味がない方__ はこの部分は __読み飛ばして__ も __構いません__。

__結論__ からいうと、__pyplot__ の __`plot`__ メソッドは、__Axes__ の __`plot` メソッド__ を __呼び出す__ という __処理__ を行っています。また、__Figure__ に __Axes__ を __1 つ__ しか __登録__ しない場合は、__どちらの `plot`__ メソッドを呼び出しても __全く同じ処理__ が __行われます__。


__2 つ__ の __`plot`__ メソッドの __違い__ は、__Figure__ に __Axes__ が __複数登録__ されている場合に __生じます__。

例えば、__先程の例__ のように、__Figure__ に __`ax1`__ と __`ax2`__ という __2 つ__ の __Axes__ が __登録されている場合__ の事を考えてみて下さい。この場合は、__`ax1`__ や __`ax2`__ に対して __`plot`__ メソッドを __呼び出す__ ことで、__2 つ__ の __Axes__ の中から __1 つを選択__ して __折れ線グラフ__ を __描画できます__。

一方、__pyplot__ の __`plot`__ を __利用__ した場合は、下記のプログラムのように、__Figure__ に __登録__ されているうちの __1 つの Axes__ の __subplot__ に __対して__ のみ __グラフを描画__ します。__実行結果__ からわかるように、__右__ の __subplot__ に、__折れ線グラフ__ と __散布図__ の __両方__ が、__重ねて描画__ されます。

```python
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=[6, 3], facecolor="lightblue")
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.scatter([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=[6, 3], facecolor="lightblue")
-ax1.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
+plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
-ax2.scatter([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
+plt.scatter([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
```
</details>


実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/d87734a7-c9c3-f222-d04f-702eedc64873.png" width="300">



__pyplot__ は、__Figure__ に __複数の Axes__ が __登録__ されている __場合__ は、__そのうち__ の __1 つ__ を __対象__ として __処理を行う__ という __仕組み__ になっており、__その Axes__ を、__current Axes__ と呼びます[^6]。

__current Axes__ は、__`subplot`__ メソッドなどを __利用__ することで __切り替える__ ことが __できます__ が、個人的には __複数__ の __Axes を利用__ する場合は、__pyplot__ ではなく、__Axes__ の __メソッド__ を __利用したほうが良い__ と __思います__。

__Axes__ が __1 つ__ の場合は、__pyplot__ の __メソッド__ を __利用__ したほうが __簡単__ に __プログラム__ を __記述__ できますが、先程説明したように、__一部のメソッド__ は、__名前が異なったり__、__Axes にしか存在しない__ 場合があるので、__本記事__ では、__基本的__ には __Axes のメソッド__ を __利用__ します。


## Artist

__matplotlib__ では、__画像__ に __表示__ する __図形__ や __文字列__ などを表す __オブジェクト__ のことを __Artist__ と呼びます。先ほど紹介した、__Axes__ も、__画像に描画__ されるため __Artist の一種__ です。

__Artist__ は __Axes__ が __管理__ する __plot__ に __描画される__ ので、__Axes に登録__ する __必要__ が __あります__[^7]。

__matplotlib__ には、__Artist__ の __種類ごと__ に、__様々なモジュール__ が __用意__ されています。__下記__ は __主なモジュール__ の __一覧__ です。なお、__本記事__ では、主に __patches__ を __利用__ します。

| モジュール名 | Artist の種類 |
|:--|:--|
| __pathces__  | 長方形や円などの図形  |
| __lines__ | 線に関する図形 |
| __text__  | 文字列  |
| __legend__ | 凡例 |
| __table__ | 表 |

__Artist__ と __pathes__ に関する詳細は、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/artist_api.html

https://matplotlib.org/stable/api/patches_api.html

:::note
__`plot`__ や __`scatter`__ などの、__グラフを描画__ するための __メソッド__ は、__グラフ__ を __構成__ する __図形__ の __Artist__ を __作成__ し、__Axes__ に __登録する__ という __処理__ を __行っています__。
:::

### 円の作成と登録

__本記事__ では、__〇×ゲーム__ の __ゲーム盤__ を __描画__ するために __必要__ な __Artist__ の __説明__ を行います。__他の図形__ に __興味がある方__ は、__matplotlib__ と __patchs__ を __キーワード__ に __検索__ して下さい。

__〇×ゲーム__ の __ゲーム盤__ では、__〇 のマーク__ を表す __円__ の __図形__ を __描画__ する __必要がある__ ので、__円__ の __Artist__ を __作成__ し、__Axes__ に __登録する方法__ を __説明__ します。

__円__ は、__patches__ モジュールの __`Circle`__ メソッドを使って __作成__ します。下記は __`Circle`__ メソッドの __仮引数__ です。__`xy`__ はデフォルト引数ではないので、__必ず記述__ する __必要があります__。

| 仮引数 | 意味 | デフォルト値 |
|:--|:--|:--|
| __xy__  | 円の __中心の座標 (x, y)__ を表す __シーケンス型__  | なし |
| __radius__  | 円の __半径__  | __`5`__ |

作成した __Artist__ は、__Axes__ の __`add_artist`__ メソッドを使って __Axes__ に __登録__ します。

下記は、__中心の座標__ が __(0, 0)__ で、__半径__ が __1__ の __円__ を __作成__ して __登録__ するプログラムです。

* __1 行目__：__matplotlib__ の __patches__ モジュールを __`patches`__ という __名前__ で __インポート__ する
* __4 行目__：__中心の座標__ が __(0, 0)__、__半径__ が __1__ の __円__ の __Artist__ を __作成__ し、__`circle`__ に __代入__ する
* __5 行目__：__`ax`__ に __代入__ された __Axes__ に __`circle`__ を __登録__ する

```python
import matplotlib.patches as patches

fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
circle = patches.Circle((0, 0), 1)
ax.add_artist(circle)
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
+import matplotlib.patches as patches

fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
+circle = patches.Circle((0, 0), 1)
+ax.add_artist(circle)
```
</details>

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/09bedad6-5edd-8d1f-80af-f7fca043e881.png" width="150">

__先程説明__ したように、__Axes__ の __plot__ の __初期設定__ の __表示範囲__ は、__x 座標__ と __y 座標__ が __0 ~ 1__ の __範囲__ になっているので、__実行結果__ のように __円の一部__ しか __表示__ されません。__下記__ のプログラムは、__円の全体__ を __表示__ するように __円の半径__ と __表示範囲__ を __設定__ したプログラムです。

```python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
circle = patches.Circle((0, 0), 0.8)
ax.add_artist(circle)
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
-circle = patches.Circle((0, 0), 1)
+circle = patches.Circle((0, 0), 0.8)
ax.add_artist(circle)
+ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
+ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```
</details>

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/684bc97c-134b-ae9c-1431-d0a1d5cc1014.png" width="150">

__`Circle`__ メソッドに関する詳細は、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Circle.html#matplotlib.patches.Circle

### 枠と塗りつぶしの設定方法

__`Circle`__ メソッドによって __作成__ される __円__ は、上記のように、__青__ で __塗りつぶされた__、__枠がない図形__ として作成されます。__枠__ や __塗りつぶし__ は、__`Circle`__ メソッドの __下記__ の __仮引数__ によって __設定__ できます。なお、__下記__ の __仮引数__ は __matplotlib__ の __他の図形__ でも __共通__ します。

| 仮引数 | 意味 | 設定できる値 | デフォルト値 |
|:--|:--|:--|:--|
| __`edgecolor`__[^8]<br>または __`ec`__  | 枠の色  | 色 または __`None`__ | matplotlib の<br>設定で変更可能 | 
| __`facecolor`__[^8]<br>または __`fc`__  | 塗りつぶしの色  | 色 または __`None`__ | 設定で変更可能 | 
| __`color`__ | 枠の色と塗りつぶしの色  | 色 | |
| __`linewidth`__<br>または __`lw`__  | 枠の幅  | float または __`None`__ | 設定で変更可能 |
| __`fill`__ | 塗りつぶすかどうか | boolean | __`True`__ |

下記は、上記の __補足説明__ です。色に関してはこの後で説明します。

* __仮引数__ が __複数__ ある場合は、__どちら__ を __使っても良い__
* __matplotlib__ の __設定__ は、__[rcsetup](https://matplotlib.org/stable/api/rcsetup_api.html)__ という __モジュール__ で __変更__ することが __できる__
* __`edgecolor`__ や __`facecolor`__ と、__`color`__ が __同時に設定__ された場合は、__`edgecolor`__ や __`facecolor`__ が __優先__ される
* __`edgecolor`__ などに __`None`__ を __設定__ すると、__対応__ するものは __描画されない__
* __`facecolor`__ が __設定__ されていても、__`fill`__ が __`False`__ の場合は __塗りつぶされない__
* __`edgecolor`__ が __設定__ されていても、__`linewidth`__ が __`0`__ や __`None`__ の場合は __枠__ は __描画されない__

### 色の設定方法

__matplotlib__ では、__色__ を、主に __下記__ のような __方法__ で指定できます。この中で __良く使われる__ のは、__アルファベット 1 文字__ で色を __指定する方法__ です。

なお、__コンピュータ__ では、__色__ を、__赤__（red）、__緑__（green）、__青__（blue）の __明るさ__ で __表現__ し、その __表現方法__ を __3 つの色__ の __頭文字__ をとって __一般的__ に __RGB__ と __表記__ します。

* __RGB__ を __tuple__ で __指定__ する
__`(1.0, 0.5, 0.2)`__ のように、__RGB__ の __明るさ__ を __0 ~ 1__ の __範囲__ の __tuple__ で __指定__ できる

* __RGB__ を __16 進数__ で __指定__ する
__`"#RRGGBB"`__ という __形式__ の __文字列__ で __RGB__ を __指定__ する。__それぞれの色__ の __明るさ__ は、__2 桁__ の __16 進数__ で __00 ~ FF__ の __範囲__[^9] で __指定__ する。例えば __赤__ は __`"#FF0000"`__ のように __記述__ する

* __英単語__ で __指定__ する
__`"red"`__、__`"green"`__ などの __英単語__ で __指定__ する。__指定できる単語__ については、__下記__ のリンク先を __参照__ すること

https://ja.wikipedia.org/wiki/X11%E3%81%AE%E8%89%B2%E5%90%8D%E7%A7%B0

* __アルファベット 1 文字__ で __指定__ する
__下記__ の __良く使われる色__ は、__特別__ に __アルファベット 1 文字__ で __指定できる__。__`"black"`__ と __`"blue"`__ は __同じ頭文字__ なので、__青__ は __`"b"`__、__黒__ は __`"k"`__ で __指定__ する点に __注意__ する事

| 文字 | 対応する英単語の色 |
|:--|:--|
| __`"b"`__  | blue  |
| __`"g"`__  | green  |
|__`"r"`__|red|
|__`"c"`__|cyan|
|__`"m"`__|magenta|
|__`"y"`__|yellow|
|__`"k"`__|black|
|__`"w"`__|white|

__matplotlib__ での __色の指定方法__ の詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/users/explain/colors/colors.html#sphx-glr-users-explain-colors-colors-py

### 塗りつぶしの色などを設定した円の描画例

下記は、__塗りつぶしの色__ を __緑__ に、__枠の色__ を __赤__ に、__枠の太さ__ を __5__ に __設定__ して、先程と同じ大きさの __円を描画__ するプログラムです。

```python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
circle = patches.Circle((0, 0), 0.8, fc="green", ec="red", lw=5)
ax.add_artist(circle)
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
-circle = patches.Circle((0, 0), 0.8)
+circle = patches.Circle((0, 0), 0.8, fc="green", ec="red", lw=5)
ax.add_artist(circle)
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
```
</details>

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/5ef15014-6f8b-b075-7efd-00e367d1bff7.png" width="150">

### 線と折れ線の作成と登録

__線__ と __折れ線__ は、__path__ という __モジュール__ の __メソッド__ を使って __作成__ することが __できます__ が、先程紹介した __pyplot__ や __Axes__ の __`plot`__ メソッドを利用することで、__作成と登録__ を __まとめて行う__ ことが __できる__ ので、__本記事__ では __`plot`__ メソッドを __利用__ することにします。

なお、__path__ モジュールを __利用__ することで、__`plot`__ メソッドでは __作成できない__、__曲線__ などの __図形__ を __作成__ することが __できる__ ので、興味がある方は下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/path_api.html

### 文字列の作成と登録

__文字列__ は、__text__ という __モジュール__ の __メソッド__ を使って __作成__ することが __できます__ が、__pyplot__ や __Axes__ の __`text`__ メソッドを __利用__ することで、__作成と登録__ を __まとめて行う__ ことが __できる__ ので、__本記事__ では __`text`__ メソッドを __利用__ することにします。

下記は、__`text`__ メソッドの __主な仮引数__ です。

| 仮引数 | 意味 | デフォルト値 |
|:--|:--|:--|
| __`x`__  | 描画する文字列の __左下__ の __x 座標__  | なし |
| __`y`__  | 描画する文字列の __左下__ の __y 座標__  | なし |
| __`s`__  | 描画する __文字列__  | なし |
| __`color`__<br>または __`c`__ | 描画する文字列の __色__ | 設定で変更可能 |
| __`fontsize`__ | 描画する文字列の __フォント__ の __サイズ__ | 設定で変更可能 |

__下記__ は、先程の __円を描画__ するプログラムに、__(0, 0)__ の __座標__ に、__"text"__ という __文字列__ を、__白__ で __フォントサイズ__ が __20__ の __大きさ__ で __表示__ する __処理__ を __追加__ したプログラムです。

```python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
circle = patches.Circle((0, 0), 0.8, fc="green", ec="red", linewidth=5)
ax.add_artist(circle)
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
ax.text(0, 0, "text", c="w", fontsize=20)
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
circle = patches.Circle((0, 0), 0.8, fc="green", ec="red", linewidth=5)
ax.add_artist(circle)
ax.set_xlim(-1, 1) # x 座標の範囲を -1 ~ 1 に設定する
ax.set_ylim(-1, 1) # y 座標の範囲を -1 ~ 1 に設定する
+ax.text(0, 0, "text", c="w", fontsize=20)
```
</details>


実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/d0811e2e-c25d-d459-70e4-9ddbfa2d7f06.png" width="150">

実行結果からわかるように、__文字列__ の __左下__ の __座標__ が、__(0, 0)__ になる点に __注意__ して下さい。

__Axes__ の __`text`__ メソッドの詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.text.html#matplotlib.axes.Axes.text

text モジュールに興味がある方は、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/text_api.html#

## Figure の描画

先程、__JupyterLab__ で __プログラムを実行__ する場合は、__Figure__ を __描画__ する __処理__ は、__JupyterLab__ の __セルの実行後__ に、__自動的に実行__ されるので __プログラムの記述__ を __省略できる__ と説明しましたが、__セルの実行__ が __終了する前__ に __Figure を描画__ したい場合などでは、__自分__ で __その処理__ を __記述__ する __必要__ が __あります__。

__Figure の描画__ は、__下記__ のプログラムのように、__pyplot__ モジュールの __`show`__ メソッドの __実行__ によって __行います__。__実行結果__ は、__`show`__ メソッドを __記述しない場合__ と __変わりません__。これは、__JupterLab__ の __セルの実行後__ に __自動的__ に __実行される処理__ が、__`plt.show()`__ だからです。

```python
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.show()
```

<details><summary><strong>修正箇所</strong></summary>

```diff_python
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
+plt.show()
```
</details>

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/e44707b4-146c-7436-efd3-342e3a7a55d0.png" width="250">

### `show` メソッドが行う処理に関する注意点

__JupyterLab__ の __セルを実行後__ に __`plt.show()`__ が __自動的に実行__ されるということは、__上記__ のプログラムを実行すると、__2 回__ グラフが __描画されるはず__ ではないかと __思った人__ は __いないでしょうか__。__上記__ で __グラフ__ が __2 回描画されない理由__ は、__`show`__ メソッドを __実行__ すると、__pyplot__ に __登録__ された __Figure__ が __自動的__ に __削除される__ からです。

__Figure__ が __自動的__ に __削除される理由__ の __一つ__ は、グラフなどの __画像__ を __描画した後__ で、__すぐ__ に __新しい画像__ を __描画する場合__ が __多い__ からです。その際に、__前に描画__ していた __画像のデータ__ が __残っている__ と、__新しい画像__ を __描画__ する際に、__前の画像__ の上に __上書きする__ ことになってしまいます。また、__一度描画__ した __画像__ を、__二度と描画しない__ 場合は、その __画像のデータ__ を __取っておく__ と、コンピュータの __メモリ__ が __無駄__ に __消費される__ という __問題__ もあります。

分かりづらいと思いますので、具体例を挙げます。

__下記__ のプログラムは、__`show`__ メソッドを __実行せず__ に、__2 つ__ の __`plot`__ メソッドを __続けて実行__ するプログラムです。__実行結果__ からわかるように、__1 つ__ の __画像__ に __複数__ の __折れ線グラフ__ が __描画__ されます。このように、__`show`__ メソッドを __実行するまでの間__ は、__同じ Figure__ に対して __処理__ が __続けて行われます__。

なお、__折れ線グラフ__ の __色が異なる__ のは、__`plot`__ メソッドが、__連続して実行__ すると、折れ線グラフの __色を変えて描画__ するという __機能を持つ__ からです。

```python
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.plot([1, 2, 3, 4, 5], [3, 9, 1, 6, 8])
```

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/d9651b98-eac5-dc60-dda0-33b59b948b73.png" width="250">

一方、__下記__ は、__JupyterLab__ の __1 つのセル__ で、__2 つ__ の __グラフを描画__ するプログラムです。__2 つのグラフ__ が __描画__ される __理由__ は __以下__ の通りです。

* __2 行目__ の __`show` メソッド__ を __実行__ することで、__1 つ目__ の __グラフが描画__ され、__描画後__ に、__Figure__ は __pyplot__ の __登録__ から __削除__ される
* __3 行目__ で __`plot`__ を __実行__ した際に、__pyplot__ に __登録__ された __Figure__ は __存在しなく__ なっているので、__新しい Figure__ が __作成__ されて、__pyplot__ に __登録__ され、__その Figure__ に __折れ線グラフ__ を __構成__ する __図形__ の __Artist__ が __登録__ される
* __JupyterLab__ の __セル__ の __プログラム__ が __すべて実行__ されたので、__自動的__ に __`plt.show()`__ が __実行__ されて __2 つ目__ の __グラフが描画__ される

```python
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.show()
plt.plot([1, 2, 3, 4, 5], [3, 9, 1, 6, 8])
```

実行結果

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/e44707b4-146c-7436-efd3-342e3a7a55d0.png" width="250"><br>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524802/69215c98-944b-c714-db82-f2d42c7aad24.png" width="250">

:::note warn
__matplotlib__ では、__pyplot__ の __`show`__ メソッドを __実行__ して __画像を描画__ した __後__ で、__pyplot__ モジュールに __登録__ した __Figure__ と __Artist__ を __すべて削除__ します。
:::

:::note
__JupyterLab__ の __セル__ で __matplotlib__ の __画像を描画__ した __後__ で、__次のセル__ で __別の画像__ を __描画__ すると、__新しい画像__ が __描画される__ のは、__セルの実行後__ に __`show`__ メソッドが __実行__ された結果、__そのセル__ で __作成__ した __Figure が削除される__ からです。
:::

:::note
この説明は、意味が分からない人が多いと思います。__当面__ は __この知識__ は __必要はない__ ので、__現時点__ ではわからない場合は __無理に理解する必要__ は __ありません__。

__`show`__ メソッドが行うのは、__pyplot__ が管理する __Figure__ の __一覧__ を __空にする__ という __処理__ なので、__Figure そのもの__ を __削除する__ ことでは __ありません__。__`plt.figure`__ や __`plt.subplots`__ で __作成__ した __Figure__ を __`fig`__ などの __変数__ に __代入__ にして __取っておく__ ことで、__その Figure__ を __pyplot__ に __再び登録する__ ことは __可能__ です。
:::

__`show`__ メソッドの詳細については、下記のリンク先を参照して下さい。

https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.show.html

# 今回の記事のまとめ

今回の記事では、__〇×ゲーム__ の __ゲーム盤__ を __画像で表示__ するために、__matplotlib__ の __簡単な仕組み__ と __使い方__ について __説明__ しました。

__〇×ゲーム__ の __ゲーム盤__ の __描画__ に __必要__ な __主な知識__ が __説明__ できたので、__次回の記事__ では __実際__ に __〇×ゲーム__ の __ゲーム盤__ を __描画する__ ことにします。

# 本記事で入力したプログラム

以下のリンクから、本記事で入力して実行した JupyterLab のファイルを見ることができます。

https://github.com/ysgeso/marubatsu/blob/master/065/marubatsu.ipynb

今回の記事では marubatsu.py は変更していません。

# 次回の記事

https://qiita.com/ysgeso/items/442db53b5b7e22c1000c

[^1]:[以前の記事](https://qiita.com/ysgeso/items/44c65c4bbec49cff7d77#ipykernel-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95)で __ipykernel__ を __インストール__ した __方法と同じ__ 方法です
[^2]:__matplotlib-base__ というモジュールも __表示__ されます。__matplotlib__ との __違い__ は、__matplotlib__ のほうは __pyqt__ という __モジュール__ も __インストールされる__ 点です。__pyqt__ を __インストールしたくない理由__ が __なければ__、__matplotlib__ を __インストールすればよい__ でしょう
[^3]:__モジュールの名前__ は __japanize-matplotlib__ ですが、__インポートする際__ は __`japanize_matplotlib`__ のように、__間__ を __半角__ の _（アンダーバー）で __つなげる必要__ が __あります__
[^4]:__matplotlib__ では、__x 軸__ と __y 軸以外__ で __座標を表現__ することも __できます__。例えば、__3 次元__ の __座標__ は、__x__、__y__、__z__ の __3 つの軸__ を使って __表現__ します
[^5]:今回の記事では利用しませんが、__x 軸__ の __ラベル__ や、__plot__ の __タイトルなど__ も __Axes が管理__ します
[^6]:__同様__ に、__複数__ の __Figure__ が __作成__ された場合も、__pyplot__ は __そのうち__ の __1 つ__ の __Figure__ を __対象__ に __処理を行い__、__その Figure__ のことを、__current Figure__ と呼びます
[^7]:__Axes__ など、__一部__ の __Artist__ は、__Figure__ に __直接登録__ されます
[^8]:__edge__ は __図形__ の __辺__ を、__face__ は __図形__ の __面__ を表す英単語です
[^9]:__10 進数__ で __0 ~ 255__ に __相当__ します