目次と前回の記事
これまでに作成したモジュール
以下のリンクから、これまでに作成したモジュールを見ることができます。
ルールベースの AI の一覧
ルールベースの AI の一覧については、下記の記事を参照して下さい。
〇×ゲームの GUI
これまでは、作成した 〇×ゲーム を play
メソッドで 遊ぶ際 に、ゲーム盤の表示 と、着手 を行う 座標の入力 を 文字 で行ってきました。以前の記事で説明したように、そのような、文字だけ で 入出力 を行う ユーザインターフェース のことを CUI と呼びます。
CUI は プログラム の 作成 を 比較的簡単 に行うことができるという 利点 がありますが、表示 や 入力 が わかりづらい という 欠点 があります。そこで、今回の記事からしばらくは、ゲーム盤の表示 を 画像 で行い、座標の入力 を、表示された 画像 に対してクリックなどの 操作 で行うという、GUI で 〇×ゲーム を 遊べるよう にします。
GUI のアプリケーションを 作成 するためには、画像を表示 するプログラムを 記述 す 必要 が あります。Python では、画像を表示 するための 様々なモジュール がありますが、本記事では、その中でグラフを描画する際に良く使われる matplotlib を利用することにします。
他 の 画像 や GUI を扱う モジュール に興味がある方は、Python、画像、GUI、モジュール などを キーワード に 検索 してみると良いでしょう。
matplotlib
matplotlib は、静止画 や 動画_ などを 作成 したりすることができる Python の モジュール で、特に、折れ線グラフ、棒グラフ、散布図など、様々なグラフ を 簡単に作成 することが できる ので、Python のモジュールの中で、人気のあるモジュール です。
本記事では、以下のような理由から、matplotlib を利用することにしました。
- Python の モジュール の中でも、最も良く使われる ものの 一つ である
- 今後の記事 で グラフ を 描画 する 機会 がある
- グラフだけでなく、任意の図形 や 文字列 を 描画できる
- アニメーション(動画)を 作る機能 がある
- JupyterLab 上で簡単に 利用できる
下記は matplotlib のサイトのリンクです。
matplotlib のインストール
これまでの記事で利用してきた collections など の モジュール は、Python を インストールした際 に 自動的 に インストール される、組み込みモジュール と呼ばれるものです。
一方、matplotlib など、個人 や 団体 などが 作成 した モジュール を 利用 するためには、そのモジュールを インストール する 必要 が あります。
モジュール を インストール する 方法 には、様々な方法がありますが、本記事では、Anaconda Navigator を 利用 する、下記の方法 を 紹介 します1ので、matplotlib をインストールしていない方は、下記の手順 に従って インストール して下さい。
- Anaconda Navigator を立ち上げる
- 左の Environments を クリック して表示される 仮想環境の一覧 から marubatsu を クリック すると、右に marubatsu の 仮想環境 に インストール されている モジュールの一覧 が 表示 される
- 上のメニュー から「Not installed」を 選択 し、その右の「Search packages」と表示された テキストボックス に「matplotlib」を 入力 する
- 下に matplotlib2 が表示 されるので、その 左のチェックボックス を チェック し、下の「Apply」ボタン を クリック する。
- 「Install packages」という パネルが表示 され、しばらく待つと「Apply 」ボタン がクリックできるようになるので クリック する。
しばらく待つとインストールが完了します。
やり方を知っている方は、Anaconda Powershell Prompt などから conda や pip などのコマンドを利用して matplotlib をインストールして構いません。
matplotlib のインポート
以前の記事で説明したように、Python では、モジュール と パッケージ という 用語 が、同じ意味 で 使われる ことがありますが、厳密 には下記のように 意味が異なります。matplotlib は パッケージ なので、複数のモジュール から 構成 されます。
- モジュール は、Python の プログラムが記述 された ファイル
- パッケージ は、複数 の Python のプログラム である モジュール を まとめたもの
パッケージ の中の 特定のモジュール を インポート する場合は、下記のプログラムのように、パッケージ名 の 後 に 半角 の . (ピリオド)で 区切ってモジュール名 を 記述 します。
import パッケージ名.モジュール名
matplotlib を 利用 する際には、pyplot という モジュール を インポート する 必要 が あります。ただし、pyplot モジュール を 利用 する際に、毎回 pyplot を 記述 するのは 面倒 なので、一般的 には下記のプログラムのように、plt
という 名前 で インポート します。
import matplotlib.pyplot as plt
matplotlib の 他のモジュール に関しては、必要に応じてインポート します。
pyplot モジュールの詳細については、下記のリンク先を参照して下さい。
グラフの描画方法
matplotlib は、グラフを描画 するために 良く使われる ので、最初に、折れ線グラフと散布図の グラフを描画 する 方法 を 紹介 します。
折れ線グラフ は、pyplot の plot
という メソッド を使って 描画 します。下記は、(1, 6)、(2, 2)、(3, 7)、(4, 5)、(5, 9) の 5 つの点 を結ぶ 折れ線グラフ を 描画 するプログラムです。
plot
メソッドに記述する 2 つ の 実引数の意味 は、以下の通りです。
- 折れ線グラフの 頂点 の x 座標 を 要素 として持つ list などの シーケンス型
- 折れ線グラフの 頂点 の y 座標 を 要素 として持つ list などの シーケンス型
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
実行結果
matplotlib では、それぞれの座標 を (1, 6) のように 記述 するの ではなく、それぞれの座標を x 座標 と y 座標 に 分けて記述 する点に 注意 して下さい。
プロット(plot)とは、データ を 図などで表す ことを意味する 英語 です。plot という 単語 には、折れ線グラフ という 意味はない 点に注意して下さい。これは 筆者 の 勝手な想像 なのですが、おそらく、代表的なグラフが、折れ線グラフなので、折れ線グラフを描画するメソッドの名前を plot
にしたのではないかと思います。
pyplot モジュールには、plot
以外 にも、様々なグラフ を 描画 するための メソッド が 用意 されており、グラフ の データを用意 して、それらの メソッド を 呼び出すだけ で、簡単 に グラフを描画 することが できるよう になっています。例えば、散布図 というグラフは、下記のプログラムのように、scatter
という メソッド を呼び出すことで 簡単に描画 することが できます。なお、実引数 に記述した データ は、先程の plot
の例と 同じ です。
plt.scatter([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
実行結果
pyplot モジュールの、グラフを描画 する メソッド の 一覧 と 詳細 ついては、下記のリンク先を参照して下さい。
警告メッセージが出る場合の対象方法
上記 のプログラムを 実行 した際に、下記のような 警告メッセージ が 表示 される 場合 が あります。これは、matplotlib が 利用 する フォント が インストールされていない ことを表します。この 警告メッセージ が 表示されない場合 は、以下の内容 は 無視 して下さい。
findfont: Font family 'IPAexGothic' not found.
上記 のような 警告メッセージ が 表示 される場合は、グラフに 日本語 を 表示 しようとした場合に、下記のプログラムのように 文字化け が 発生 してしまします。なお、2 行目 の plt.title
は、グラフ に タイトルを表示 する メソッド で、実行結果 の 上部 に 表示 される □□□ は、「テスト」という 文字列 が 文字化け したものです。
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.title("テスト")
実行結果
修正箇所
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
+plt.title("テスト")
文字化け が 起きない ようにする 方法 として、フォント を インストール し、matplotlib の 設定を編集 するという 方法 がありますが、少々面倒 なので、別の方法 を 紹介 します。
フォント を インストール する 方法 を行いたい人は、上記の 警告メッセージ を キーワード にして 検索 するとその方法の手順が見つかると思います。
本記事で紹介する方法は、japanize-matplotlib という、matplotlib を 日本語化 する モジュール を インストール するという方法です。なお、このモジュール は、Anaconda Navigator や、conda という コマンド では インストール することが できない ようなので、下記の手順 で pip という コマンド を使って インストール する 必要 が あります。
- スタートメニューから、「Anaconda Powershell Prompt (anaconda3)」を探して 実行 する
-
conda activate marubatsu
を 入力 して、marubatsu の 仮想環境に入る -
pip install japanize-matplotlib
を 入力 して エンターキーを押す
インストール後 に、下記 のプログラムのように、japanize_matplotlib3 を インポートする と、警告メッセージ が 表示されなく なり、日本語の文字 も 表示される ようになります。
import japanize_matplotlib
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.title("テスト")
修正箇所
+import japanize_matplotlib
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.title("テスト")
実行結果
本記事 では、以後 は japanize_matplotlib を インポート しますが、japanize_matplotlib を インストールしない 場合は import japanize_matplotlib
を 記述しない ようにして下さい。
下記は、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 の 一種 である |
紛らわしい ですが、上記の表の plot という 用語 と、折れ線グラフを描画する、pyplot モジュール の plot
メソッド は 異なるもの である点に 注意 して下さい。
本記事では、plot
メソッド の場合は、文字 を 網掛けにする ことで 区別 します。
画像の描画の手順
matplotlib では、以下 のような 手順 で 画像の描画 を行います。
- Figure という、描画する画像 に関する データ を 管理 する オブジェクト を 作成 する
- plot を 管理 する Axes という オブジェクト を 作成 し、Figure に登録 する
- 図形 や 文字列 などを表す Artist を 作成 し、Axes に 登録する
- Figure に 登録 された Artist を 描画 する メソッド を 呼び出し て、画像を描画 する
勘違いされやすい のですが、画像の描画 は、図形や文字列を表す 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 数字 の 単位 は インチ |
[6.4, 4.8] |
facecolor または fc
|
作成 する 画像 の 背景色 | "white" |
下記は、figsize
と facecolor
を 設定 して、先程と同じ折れ線グラフを描画するプログラムです。figsize
の 幅と高さ を 同じ値 に 設定 したため、画像 が 正方形 になります。なお、作成 した Figure を 代入 する 変数の名前 には、fig
という 名前 が 良く使われます。
-
1 行目:画像のサイズ を 3 × 3、背景色 を 水色(lightblue)に 設定 した Figure の オブジェクト を 作成 し、
fig
という 名前 の 変数 に 代入 する
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
修正箇所
+fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
実行結果
本記事では、fig
に代入した Figure のデータを利用しませんが、Figure の メソッドを利用 することで、Figure の 作成後 に、設定 を 変更 することが できます。
なお、figure
メソッドによって 作成 された Figure は、pyplot モジュール が 自動的 に 管理する ので、上記のプログラムのように 変数 に 代入しておかなくても、pyplot の メソッド を 利用 することで 後から取得 することも できます。
また、今回の記事では行いませんが、Figure を 複数作成 することで、複数の画像 を 同時に作成 することも できます。
figure
メソッドの詳細については、下記のリンク先を参照して下さい。
Axes
作成したばかり の Figure には何の データ も 登録されていない ので、下記 のプログラムのように、Figure を 作成するだけ では 何も描画 は 行われません。画像を描画 するためには、少なくとも 1 つの Axes を作成 して、Figure に登録 する 必要 が あります。
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
実行結果
<Figure size 300x300 with 0 Axes>
実行結果 に表示されるメッセージは、作成した Figure が、大きさ が 300 x 300 の 画像 で Axes が 1 つも登録されていない ことを 表します。
Axes とは何か
画像を描画 する際には、Figure が 作成する画像 の どの範囲 に、Figure に 登録したデータ を 描画するか を 決める必要 があります。
このように説明すると、画像全体 に 描画すればよい と 思う人 が 多いのではないか と思いますが、画像全体 に 描画してはいけない 場合が あります。
具体的には、先程のプログラムで描画した下記のグラフを見て下さい。この画像 の中で、グラフのデータ が 描画 される 範囲 は、画像全体 ではなく、背景 が 白い正方形の範囲 に 限定されます。下記の 白い正方形 の 範囲 のように、グラフのデータなどを 実際に描画 する 範囲 の事を plot と呼び、plot を管理 するのが Axes という オブジェクト です。
matplotlib では、基本的には Axes を作成 し、Figure に登録 することではじめて、画像 が 描画される という 仕組み になっています。
Axes の作成と登録
Axes は、下記 のプログラムのように、pyplot の subplot
という メソッドを実行 することで 作成 することが できます。また、作成 した Axes は、pyplot が 管理 する Figure に 自動的に登録 されます。なお、作成 した Axes を 代入 する 変数の名前 には、ax
という 名前 が 良く使われます。
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
ax = plt.subplot()
修正箇所
fig = plt.figure(figsize=[3, 3], facecolor="lightblue")
+ax = plt.subplot()
実行結果
実行結果 からわかるように、Axes を 作成 し、Figure に 登録 することで、画像が描画 されるようになります。なお、Figure には、作成した Axes 以外の データ は 登録されていない ので、plot の 白い正方形 の 部分 には 何も表示されません。なお、上図のように、Axes は Figure に 描画される ものの一つなので、Axes も Artist の 一種 に 分類 されます。
plot
や scatter
などの グラフを描画 する メソッド には、自動的 に Axes を作成 し、Figure に登録 する 機能 が 備わっている ので、それらのメソッドを利用する際には、自分 で Axes を 作成する必要 は ありません。
作成した Axes に 対応 する plot が、画像 の どこに配置されるか については、自動的 に 設定されます が、自分 で 好みの位置 と 大きさ に 設定 することもできます。
subplot
メソッドの詳細については、下記のリンク先を参照して下さい。
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 が 名前の由来 になっています。
今回の記事では使用しませんが、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 に 表示されない場合 が 生じます。
分かりづらいと思った人は、ウィンドウ と、ウィンドウ内の 表示 の 拡大縮小 の 機能 を思い浮かべてみて下さい。例えば、一般的 な ウェブブラウザ は、Ctrl キー を 押しながら、マウス の ホイール を 回転 すると、表示 の 大きさ を 拡大・縮小 することが できます。表示 を 拡大 すると、ウィンドウに 表示 される 範囲 が せまく なり、ウェブページの 一部の内容 が 画面 に 表示されなく なります。
下図は、先程の Axes を 作成 したプログラムの 実行結果 です。図からわかるように、Axes は、初期設定 では、plot の 表示範囲 は、x 座標 と y 座標 が 0 ~ 1 の 範囲 に 設定 されます。なお、数学 の グラフ の軸と 同様 に、横方向 が x 軸 で、縦方向 が y 軸 です。
Axes が 管理 する plot の 表示範囲 は、set_xlim
と set_ylim
メソッドを使って 変更 することが できます。実引数 には、それぞれの 範囲 の 最小値 と 最大値 を記述し、下記 のプログラムのように記述することで、x 座標 と y 座標 の 表示範囲 が -1 ~ 1 になります。
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 に設定する
修正箇所
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 に設定する
実行結果
set_xlim
と set_ylim
メソッドの詳細については、下記のリンク先を参照して下さい。
枠と目盛りの管理
Axes は、plot の 枠 や、枠の外側 の 目盛り なども 管理 するので、Figure を描画 すると、自動的に plot の 枠 や 目盛り も 表示 されます。
グラフを描画 する際には 必須 となる、枠 と 目盛り は、〇×ゲーム の ゲーム盤 を 描画 する際には 邪魔 になります。枠 と 目盛り は、下記のプログラムのように、Axes の axis
メソッドの 実引数 に "off"
を 記述 して 実行 することで 表示しない ように できます。
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
ax.axis("off")
修正箇所
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
+ax.axis("off")
実行結果
実行結果 からわかるように、枠 と 目盛り だけでなく、plot の 白い部分 も 表示されなくなります が、plot の範囲 が 見えなくなっただけ で、plot そのもの は 元の位置 に 存在 しています。従って、枠 と 目盛り を 表示しないよう にしても、下記のプログラムのように、Axes に 登録 した Artist は問題なく 表示されます。
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
ax.axis("off")
修正箇所
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
+plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
ax.axis("off")
実行結果
Figure と Axes の一括作成
上記のプログラムでは、Figure を 作成 してから Axes を 作成 して 登録 しましたが、Figure を使って 画像を描画 するためには、Axes を 作成 して Figure に 登録 する 必要 があるので、その 2 つの処理 を まとめて 行う subplots
という メソッド が 用意 されています。
subplots
メソッドは、下記 の 処理 を行います。
- Figure を 作成 して pyplot モジュールに 登録 する
- Axes を 作成 して、上記で作成した Figure に 登録 する
- 返り値 として、上記で 作成 した Figure と Axes を 要素 として持つ tuple を 返す
また、subplots
メソッドは、下記 のプログラムのように、figure
メソッドと 同じキーワード引数 を使って、Figure の 画像のサイズなど を 設定 することが できます。
下記のプログラムは、先程 のプログラムと 同じ処理 を行うプログラムです。
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 に設定する
修正箇所
-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 に設定する
実行結果
subplot
と subplots
は 名前 は 似ています が、全く異なる処理 を行うメソッドである点に 注意 して下さい。
subplots
メソッドの詳細については、下記のリンク先を参照して下さい。
複数の Axes の設定
本記事 では、しばらくの間 は、Figure に 複数 の Axes の登録 を 行わない ので、興味がない方 はこの部分は 読み飛ばして も 構いません。
subplots
メソッドを利用することで、Figure に、複数 の Axes を 登録 することが できます。その場合は、Figure が 作成 する 画像の中 に、複数 の plot が 作成 され、それぞれ の plot を subplot と呼びます。
それぞれ の subplot は 下記 のような 性質 を 持ちます。
- 異なる Axes によって 管理される
- それぞれの Axes に対して、Artist を 登録 できる
- Axes に 登録 された Artist は、その Axes に 対応 する subplot に対して 描画 される
上記の性質から、subplot を 利用 することで、下記 のプログラムのように、1 つの画像 の中に、異なる 2 つ の グラフ を 並べて描画 することが できる ようになります。
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])
実行結果
上記のプログラムの詳細な説明を行うと長くなるので、今回の記事 では 簡単な説明 に とどめます。興味がある方は、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
メソッドが あります。
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 に、折れ線グラフ と 散布図 の 両方 が、重ねて描画 されます。
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])
修正箇所
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])
実行結果
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 に関する詳細は、下記のリンク先を参照して下さい。
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
を 登録 する
import matplotlib.patches as patches
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
circle = patches.Circle((0, 0), 1)
ax.add_artist(circle)
修正箇所
+import matplotlib.patches as patches
fig, ax = plt.subplots(figsize=[3, 3], facecolor="lightblue")
+circle = patches.Circle((0, 0), 1)
+ax.add_artist(circle)
実行結果
先程説明 したように、Axes の plot の 初期設定 の 表示範囲 は、x 座標 と y 座標 が 0 ~ 1 の 範囲 になっているので、実行結果 のように 円の一部 しか 表示 されません。下記 のプログラムは、円の全体 を 表示 するように 円の半径 と 表示範囲 を 設定 したプログラムです。
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 に設定する
修正箇所
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 に設定する
実行結果
Circle
メソッドに関する詳細は、下記のリンク先を参照して下さい。
枠と塗りつぶしの設定方法
Circle
メソッドによって 作成 される 円 は、上記のように、青 で 塗りつぶされた、枠がない図形 として作成されます。枠 や 塗りつぶし は、Circle
メソッドの 下記 の 仮引数 によって 設定 できます。なお、下記 の 仮引数 は matplotlib の 他の図形 でも 共通 します。
仮引数 | 意味 | 設定できる値 | デフォルト値 |
---|---|---|---|
edgecolor 8または ec
|
枠の色 | 色 または None
|
matplotlib の 設定で変更可能 |
facecolor 8または fc
|
塗りつぶしの色 | 色 または None
|
設定で変更可能 |
color |
枠の色と塗りつぶしの色 | 色 | |
linewidth または lw
|
枠の幅 | float または None
|
設定で変更可能 |
fill |
塗りつぶすかどうか | boolean | True |
下記は、上記の 補足説明 です。色に関してはこの後で説明します。
- 仮引数 が 複数 ある場合は、どちら を 使っても良い
- matplotlib の 設定 は、rcsetup という モジュール で 変更 することが できる
-
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"
などの 英単語 で 指定 する。指定できる単語 については、下記 のリンク先を 参照 すること
-
アルファベット 1 文字 で 指定 する
下記 の 良く使われる色 は、特別 に アルファベット 1 文字 で 指定できる。"black"
と"blue"
は 同じ頭文字 なので、青 は"b"
、黒 は"k"
で 指定 する点に 注意 する事
文字 | 対応する英単語の色 |
---|---|
"b" |
blue |
"g" |
green |
"r" |
red |
"c" |
cyan |
"m" |
magenta |
"y" |
yellow |
"k" |
black |
"w" |
white |
matplotlib での 色の指定方法 の詳細については、下記のリンク先を参照して下さい。
塗りつぶしの色などを設定した円の描画例
下記は、塗りつぶしの色 を 緑 に、枠の色 を 赤 に、枠の太さ を 5 に 設定 して、先程と同じ大きさの 円を描画 するプログラムです。
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 に設定する
修正箇所
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 に設定する
実行結果
線と折れ線の作成と登録
線 と 折れ線 は、path という モジュール の メソッド を使って 作成 することが できます が、先程紹介した pyplot や Axes の plot
メソッドを利用することで、作成と登録 を まとめて行う ことが できる ので、本記事 では plot
メソッドを 利用 することにします。
なお、path モジュールを 利用 することで、plot
メソッドでは 作成できない、曲線 などの 図形 を 作成 することが できる ので、興味がある方は下記のリンク先を参照して下さい。
文字列の作成と登録
文字列 は、text という モジュール の メソッド を使って 作成 することが できます が、pyplot や Axes の text
メソッドを 利用 することで、作成と登録 を まとめて行う ことが できる ので、本記事 では text
メソッドを 利用 することにします。
下記は、text
メソッドの 主な仮引数 です。
仮引数 | 意味 | デフォルト値 |
---|---|---|
x |
描画する文字列の 左下 の x 座標 | なし |
y |
描画する文字列の 左下 の y 座標 | なし |
s |
描画する 文字列 | なし |
color または c
|
描画する文字列の 色 | 設定で変更可能 |
fontsize |
描画する文字列の フォント の サイズ | 設定で変更可能 |
下記 は、先程の 円を描画 するプログラムに、(0, 0) の 座標 に、"text" という 文字列 を、白 で フォントサイズ が 20 の 大きさ で 表示 する 処理 を 追加 したプログラムです。
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)
修正箇所
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)
実行結果
実行結果からわかるように、文字列 の 左下 の 座標 が、(0, 0) になる点に 注意 して下さい。
Axes の text
メソッドの詳細については、下記のリンク先を参照して下さい。
text モジュールに興味がある方は、下記のリンク先を参照して下さい。
Figure の描画
先程、JupyterLab で プログラムを実行 する場合は、Figure を 描画 する 処理 は、JupyterLab の セルの実行後 に、自動的に実行 されるので プログラムの記述 を 省略できる と説明しましたが、セルの実行 が 終了する前 に Figure を描画 したい場合などでは、自分 で その処理 を 記述 する 必要 が あります。
Figure の描画 は、下記 のプログラムのように、pyplot モジュールの show
メソッドの 実行 によって 行います。実行結果 は、show
メソッドを 記述しない場合 と 変わりません。これは、JupterLab の セルの実行後 に 自動的 に 実行される処理 が、plt.show()
だからです。
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.show()
修正箇所
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
+plt.show()
実行結果
show
メソッドが行う処理に関する注意点
JupyterLab の セルを実行後 に plt.show()
が 自動的に実行 されるということは、上記 のプログラムを実行すると、2 回 グラフが 描画されるはず ではないかと 思った人 は いないでしょうか。上記 で グラフ が 2 回描画されない理由 は、show
メソッドを 実行 すると、pyplot に 登録 された Figure が 自動的 に 削除される からです。
Figure が 自動的 に 削除される理由 の 一つ は、グラフなどの 画像 を 描画した後 で、すぐ に 新しい画像 を 描画する場合 が 多い からです。その際に、前に描画 していた 画像のデータ が 残っている と、新しい画像 を 描画 する際に、前の画像 の上に 上書きする ことになってしまいます。また、一度描画 した 画像 を、二度と描画しない 場合は、その 画像のデータ を 取っておく と、コンピュータの メモリ が 無駄 に 消費される という 問題 もあります。
分かりづらいと思いますので、具体例を挙げます。
下記 のプログラムは、show
メソッドを 実行せず に、2 つ の plot
メソッドを 続けて実行 するプログラムです。実行結果 からわかるように、1 つ の 画像 に 複数 の 折れ線グラフ が 描画 されます。このように、show
メソッドを 実行するまでの間 は、同じ Figure に対して 処理 が 続けて行われます。
なお、折れ線グラフ の 色が異なる のは、plot
メソッドが、連続して実行 すると、折れ線グラフの 色を変えて描画 するという 機能を持つ からです。
plt.plot([1, 2, 3, 4, 5], [6, 2, 7, 5, 9])
plt.plot([1, 2, 3, 4, 5], [3, 9, 1, 6, 8])
実行結果
一方、下記 は、JupyterLab の 1 つのセル で、2 つ の グラフを描画 するプログラムです。2 つのグラフ が 描画 される 理由 は 以下 の通りです。
-
2 行目 の
show
メソッド を 実行 することで、1 つ目 の グラフが描画 され、描画後 に、Figure は pyplot の 登録 から 削除 される -
3 行目 で
plot
を 実行 した際に、pyplot に 登録 された Figure は 存在しなく なっているので、新しい Figure が 作成 されて、pyplot に 登録 され、その Figure に 折れ線グラフ を 構成 する 図形 の Artist が 登録 される -
JupyterLab の セル の プログラム が すべて実行 されたので、自動的 に
plt.show()
が 実行 されて 2 つ目 の グラフが描画 される
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])
実行結果
matplotlib では、pyplot の show
メソッドを 実行 して 画像を描画 した 後 で、pyplot モジュールに 登録 した Figure と Artist を すべて削除 します。
JupyterLab の セル で matplotlib の 画像を描画 した 後 で、次のセル で 別の画像 を 描画 すると、新しい画像 が 描画される のは、セルの実行後 に show
メソッドが 実行 された結果、そのセル で 作成 した Figure が削除される からです。
この説明は、意味が分からない人が多いと思います。当面 は この知識 は 必要はない ので、現時点 ではわからない場合は 無理に理解する必要 は ありません。
show
メソッドが行うのは、pyplot が管理する Figure の 一覧 を 空にする という 処理 なので、Figure そのもの を 削除する ことでは ありません。plt.figure
や plt.subplots
で 作成 した Figure を fig
などの 変数 に 代入 にして 取っておく ことで、その Figure を pyplot に 再び登録する ことは 可能 です。
show
メソッドの詳細については、下記のリンク先を参照して下さい。
今回の記事のまとめ
今回の記事では、〇×ゲーム の ゲーム盤 を 画像で表示 するために、matplotlib の 簡単な仕組み と 使い方 について 説明 しました。
〇×ゲーム の ゲーム盤 の 描画 に 必要 な 主な知識 が 説明 できたので、次回の記事 では 実際 に 〇×ゲーム の ゲーム盤 を 描画する ことにします。
本記事で入力したプログラム
以下のリンクから、本記事で入力して実行した JupyterLab のファイルを見ることができます。
今回の記事では marubatsu.py は変更していません。
次回の記事
-
matplotlib-base というモジュールも 表示 されます。matplotlib との 違い は、matplotlib のほうは pyqt という モジュール も インストールされる 点です。pyqt を インストールしたくない理由 が なければ、matplotlib を インストールすればよい でしょう ↩
-
モジュールの名前 は japanize-matplotlib ですが、インポートする際 は
japanize_matplotlib
のように、間 を 半角 の _(アンダーバー)で つなげる必要 が あります ↩ -
matplotlib では、x 軸 と y 軸以外 で 座標を表現 することも できます。例えば、3 次元 の 座標 は、x、y、z の 3 つの軸 を使って 表現 します ↩
-
今回の記事では利用しませんが、x 軸 の ラベル や、plot の タイトルなど も Axes が管理 します ↩
-
同様 に、複数 の Figure が 作成 された場合も、pyplot は そのうち の 1 つ の Figure を 対象 に 処理を行い、その Figure のことを、current Figure と呼びます ↩
-
Axes など、一部 の Artist は、Figure に 直接登録 されます ↩
-
10 進数 で 0 ~ 255 に 相当 します ↩