{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "(chap:matplotlib)=\n", "# `Matplotlib`:図示" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " in English or the language of your choice.\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 説明" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "\n", "# 警告メッセージを非表示\n", "import warnings\n", "warnings.filterwarnings(\"ignore\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Matplotlib`(「マットプロットリブ」と読む)はプロットのための代表的なパッケージであり、ここではその使い方を解説する。プロットには`Matplotlib`のモジュールである`pyplot`を使うことになる。慣例に沿って`plt`としてインポートする。
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`pyplot`モジュールを使ってプロットする場合、主に3つのコードの書き方がる。\n", "\n", "**書き方1**:(オブジェクト指向)\n", "```\n", "fig = plt.figure()\n", "ax = fig.add_subplot()\n", "ax.plot(...)\n", "```\n", "**書き方2**:(オブジェクト指向)\n", "```\n", "fig, ax = plt.subplots()\n", "ax.plot(...)\n", "```\n", "**書き方3**: `Matlab`という有料ソフトのコードに沿った書き方\n", "```\n", "plt.plot(...)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "本サイトでは書き方2に沿って`Matplotlib`の使い方を説明する。一方で,その裏にある考え方を理解するには、書き方1から始めた方が良いと思うので,書き方1の簡単な説明をすることにする。{numref}`fig:4-figure_axes`は,`Matplotlib`が描画する図の階層的な構造を示している。ここで重要なのは「キャンバス」と「軸」の違いである。\n", "\n", "\n", "`Matplotlib`によるプロットは次の図のような構成となっている。\n", "\n", "```{figure} /images/figure_axes_mpl.png\n", "---\n", "scale: 40%\n", "name: fig:4-figure_axes\n", "---\n", "キャンバスと軸の関係\n", "```\n", "\n", "* キャンバスとは表示される**領域**であり,実際には表示されない透明のキャンバ」である。\n", " * 書き方1と書き方2では変数`fig`がキャンバスを表している。\n", " * `figure`や`fig`などの変数名や引数名があれば、キャンバスを指していると理解すれば良いだろう。\n", "* 軸とは1つの図を表示する**区域**である。\n", " * 書き方1と書き方2では変数`ax`が軸を表している。\n", " * `ax`や`axes`などの変数名や引数名があれば、軸を表していると理解すれば良いだろう。\n", " * キャンバス上に複数のグラフを表示する場合は複数の区域を設定する必要がある。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これを踏まえて,書き方1は次のような手順で描画していと解釈できる。\n", "1. キャンバスを用意する。\n", " * それを行なっているのが1行目である。右辺の`plt.figure()`でキャンバスを作成し、それを変数`fig`に割り当てている。\n", "1. キャンバスに軸を追加する。\n", " * これをおこなっているのが2行目である。右辺では、キャンバス`fig`のメソッド`add_subplot()`を使いキャンバスに軸を追加し、それを左辺の変数`ax`に割り当てている。実際に、書き方1の2行のコードを実行すると透明のキャンバス上に軸が表示される。(試してみよう。)\n", " * 作成された軸`ax`にメソッド`plot()`などを使い直線・曲線・点など付け加えたり、タイトルなどの「飾り付け」をおこない作図することになる。\n", " * 1つのキャンバスに複数の軸を作成し,複数の図を表示することが可能となる。\n", "\n", "この説明でわかることは、`Matplotlib`で表示される図は透明のキャンバス上に描かれ装飾された軸ということである。以下の説明では、「図」はキャンバス全体に表示されたものを指す場合もあれば,ある一つの軸に表示されたものを指す場合もああるので,文脈で判断してほしい。\n", "\n", "さて書き方2に話を戻すと、既に察している読者もいるかも知れないが、1行目は書き方1の最初の2行を1行に省略したものである。右辺の`plt.subplots()`は透明のキャンバスと軸の2つをタプルとして返す。最初の要素がキャンバスでありそれを左辺の`fig`に、2つ目の要素が軸であり`ax`に割り当てている。実際、1行目だけを実行すると軸が表示される。後は書き方1同様、`ax`のメソッド`plot()`などを使い軸を飾り付けして作図することになる。\n", "\n", "ちなみに、書き方3は書き方2の3行を1行に省略した形と解釈して良いだろう。本来は`Matlab`(有料)ユーザーの`Python`への移行を促す為に用意された書き方である。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次に`plot()`のデータに関する引数について説明するが,主に2つの設定方法がある。\n", "\n", "**データの引数の書き方1**:\n", "```\n", "plot(<横軸のデータ>, <縦軸のデータ>)\n", "```\n", "**データの引数の書き方2**:変数のラベル名が使える場合(`Pandas`の`DataFrame`)\n", "```\n", "plot(<横軸の変数名>, <縦軸の変数名>, data=<データ名>)\n", "```\n", "\n", "この2つの書き方の簡略形として,横軸の変数を省略することもできる。\n", "```\n", "plot(<縦軸のデータ>)\n", "\n", "plot(<縦軸の変数名>, data=<データ名>)\n", "```\n", "この場合,横軸には`縦軸のデータ`のインデックス番号が使われることになる。手っ取り早く図示したい場合は良いかも知れない。\n", "\n", "以下ではそれぞれの引数の書き方について解説する。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "## データの引数の書き方1" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### `array`を使って" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "プロットするデータを生成しよう。変数`x`に横軸に使うデータを次のように割り当てる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "x = np.linspace(-2, 2, 3)\n", "x" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "3つの要素からなる`array`である。縦軸のデータとして`y0`を用意する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "y0 = x**2\n", "y0" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "同じように`y0`も3つの要素からなる`array`である。プロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot(x, y0, marker='o')" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "2行目に`marker='o'`が追加されているが,「●」を表示するために使っている。このような引数の使い方は後で詳しく説明するので,ここでは気にしないで読み進めて欲しい。\n", "\n", "「●」のマーカーがある点が`x`と`y0`の`array`要素の組み合わせとして表示されている。`plot()`はデフォルトでそれらの点を直線で結んでいる。この場合,データの組み合わせが3点しかないため$y=x^2$の形を明確に表示できていない。言い換えると,データの組み合わせの数を増やすことにより$y=x^2$をより正確に表示されることになる。もう一度,`x`と`y0`のデータを生成しなおす。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "x = np.linspace(-2, 2, 100)\n", "y0 = x**2" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`x`と`y0`にはそれぞれ100の要素があり,これらを使うことにより100のデータの組み合わせが成立することになる。プロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot(x, y0, marker='o')" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "より$y=x^2$の図に近づいたことがわかる。\n", "\n", "(注意点)\n", "* 上の2つの図の上に文字が表示されているが,表示したくない場合は最後に`;`を加えるか次の行に`pass`と書くと表示されなくなる。\n", "* `x`を省いて`ax.plot(y0)`としても同じような図が表示されるが,横軸の値がデータの数に対応することになり,意図した図と異なることになる。\n", "\n", "次に縦軸のデータとして,2つを用意する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "y1 = x+1\n", "y2 = np.exp(x)" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`y0`,`y1`,`y2`を同じ軸にプロットしてみよう。コードは簡単で`ax.plot()`をリピートするだけである。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot(x, y0) \n", "ax.plot(x, y1)\n", "ax.plot(x, y2)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "それぞれの`ax.plot()`を「軸`ax`にデータの組み合わせをプロットする」と読めば理解しやすいと思う。また同じようなコードが続いているので,次のように`for`ループを使うことより短いコードで同じ図を表示することができる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "\n", "for y in [y0, y1, y2]:\n", " ax.plot(x, y) \n", "\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### `DataFrame`を使って" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "まず`DataFrame`を作成しよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "dic = {'X':x, 'Y0':y0, 'Y1':y1, 'Y2':y2} # 辞書の作成\n", "\n", "df0 = pd.DataFrame(dic) # DataFrameの作成\n", "\n", "df0.head()" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "横軸に`X`,縦軸に`Y0`をプロットしてみる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot(df0['X'],df0['Y0'])\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "横軸に`X`,縦軸に`Y0`,`Y1`,`Y2`をプロットしてみる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot(df0['X'],df0['Y0'])\n", "ax.plot(df0['X'],df0['Y1'])\n", "ax.plot(df0['X'],df0['Y2'])\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "引数の書き方1の簡略形として,横軸の変数を省略できることを紹介した。その場合はどうなるかを考えてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot(df0['Y0'])\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "上の図との違いは横軸の値である。この場合,横軸に`df0`の行インデックスが自動的に使われている。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "## データの引数の書き方2" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "次に引数`data`を使う書き方を考えてみる。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 同じ`DataFrame`を使う" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "横軸に`X`,縦軸に`Y0`を指定してプロットしてみる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot('X', 'Y0', data=df0)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "変数`Y1`と`Y2`も同じ軸`ax`にプロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot('X', 'Y0', data=df0)\n", "ax.plot('X', 'Y1', data=df0)\n", "ax.plot('X', 'Y2', data=df0)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "````{note}\n", "この場合,同じようなコードが続いているのでforループを使うと良いだろう。\n", "```\n", "fig, ax = plt.subplots()\n", "for v in ['Y0','Y1','Y2']:\n", " ax.plot('X', v, data=df0)\n", "```\n", "````" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "横軸の`X`を指定せずにプロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot('Y0', data=df0)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "行インデックスが横軸の値として使われている。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 異なる`DataFrame`の変数を図示する" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "別の`DataFrame`を作成する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "dic = {'X':x, 'Y3':-x-1, 'Y4':-x**2}\n", "df1 = pd.DataFrame(dic)\n", "df1.head()" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`X`を横軸として`df0`の`Y0`,`Y3`を横軸として`df1`の`Y3`を同じ図に表示してみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot('X', 'Y0', data=df0)\n", "ax.plot('Y3', 'Y4', data=df1)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "tags": [ "remove-cell" ] }, "source": [ "## その他の引数とメソッド" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "(sec:4-other_methods)=\n", "## その他の引数とメソッド" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "上で説明したコードでは単純なプロットしかできない。一方で様々な引数やメソッドが用意されており,それらを駆使することにより様々な「飾り付け」をすることが可能となる。ここでは主なものを紹介するが,他にも数多く用意されているので`Matplotlib`の[サイト](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html)を参考にしてほしい。また,これらの引数・メソッドは,上述の「データの引数の書き方1」と「データの引数の書き方2」の両方に有効であることも覚えておこう。\n", "\n", "引数・メソッドがもたらす違いを際立たせるために新たな`DataFrame`を使おう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "dic = {'X':[10, 20, 30],\n", " 'Y':[5.0, 30.0, 15.0],\n", " 'Z':[7.0, 2.0, 10.0]}\n", "df2 = pd.DataFrame(dic)\n", "df2.head()" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "以下のプロットでは,横軸の変数を省略する簡略形を使うので,行インデックが横軸に使われるので注意しよう。" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "### `subplots()`の引数" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`subplots()`はキャンバスと軸を設定する`plt`のメソッドとなるが、主に3つの引数を紹介する。\n", "* `figsize`:図の大きさ\n", " * `figsize=(キャンバスの横幅、キャンバスの縦の長さ)`\n", "* `nrows`(デフォルトは`1`):軸の数を指定するために使う引数(「図を並べる」のセクションで説明する)\n", "* `ncols`(デフォルトは`1`):軸の数を指定するために使う引数(「図を並べる」のセクションで説明する)\n", "* `sharex`(デフォルトは`False`):複数の軸がある場合に使う引数(「図を並べる」のセクションで説明する)\n", "* `sharey`(デフォルトは`False`):複数の軸がある場合に使う引数(「図を並べる」のセクションで説明する)\n", "* `constrained_layout`(デフォルトは`False`):複数の軸がある場合に使う引数であり,図の間隔を自動調整する(「図を並べる」のセクションで説明する)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fix, ax = plt.subplots(figsize=(8,4))\n", "ax.plot('X', data=df2)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### `plot()`の基本的な引数" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`plot()`は軸`ax`にデータを描くメソッドだが、引数を使うことによりデータの表示方法を指定できる。詳しくは[このリンク](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html)を参照することにして,ここでは基本的な引数だけを紹介する。\n", "* `linestyle`:線のスタイル(リストにして列の順番で指定する;`-`,`--`,`-.`,`:`などがある)\n", "* `linewidth` or `lw`:線の幅\n", "* `color` or `c`:色([参照サイト](https://matplotlib.org/stable/gallery/color/named_colors.html))\n", " * `r`は赤\n", " * `k`は黒\n", " * `g`はグリーン\n", "* `marker`:観測値のマーカー(`o`,`.`,`>`,`^`などがある; [参照サイト](https://matplotlib.org/stable/api/markers_api.html))\n", "* `markersize`:マーカーの大きさ\n", "* `label`:以下で説明する`ax.legend()`がある場合に有効となる" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fix, ax = plt.subplots()\n", "ax.plot('X'\n", " , data=df2\n", " , linestyle=':'\n", " , linewidth=2\n", " , color='red'\n", " , marker='o'\n", " , markersize=10\n", " , label='X series')\n", "ax.plot('Y'\n", " , data=df2\n", " , linestyle='-'\n", " , linewidth=2\n", " , color='k'\n", " , marker='^'\n", " , markersize=10\n", " , label='X series')\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "引数をいちいち書くのが面倒な場合、次の3つを簡略して一緒に指定できる。\n", "* `linestyle`\n", "* `color`\n", "* `marker`\n", "\n", "例えば、\n", "* `linestyle=':'`\n", "* `color='red'`\n", "* `marker='o'`\n", "\n", "の場合、`:ro`と書くことができる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fix, ax = plt.subplots()\n", "ax.plot('Y', ':ro', data=df2)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "(注意点)\n", "* `:ro`は文字列\n", "* `:`,`r`,`o`の順番を変えても良い。\n", "* `:`や`:o`のように1つもしくは2つだけを指定しても良い。\n", "* `:ro`は`=`を使う引数の前に置く。\n", "\n", "詳細は[参考サイト(英語)](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html)を参照。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### `ax`の基本的なメソッド" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`ax`は透明なキャンバス上にある軸を指しているが、そのメソッドを使うことにより、軸周辺を「飾り付け」することができる。\n", "* `.set_title()`:タイトルを設定する。\n", " * 文字列で指定し、大きさは引数`size`で指定する。\n", "* `.set_xlabel()`:横軸ラベル\n", " * 文字列で指定し、大きさは引数`size`で指定する。\n", "* `.set_ylabel()`:縦軸ラベル\n", " * 文字列で指定し、大きさは引数`size`で指定する。\n", "* `.legend()`:凡例を表示する。\n", " * `plot()`の引数`label`がなければ、データ・フレームの列ラベルが使われる。\n", " * `plot()`の引数`label`があれば、それが使われる。\n", "* `.grid()`:グリッド線が表示される。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.plot('X', data=df2, label='X series')\n", "ax.set_title('A Large Title', size= 30) # タイトルの設定\n", "ax.set_xlabel('Horizontal Axis', size=20) # 横軸ラベルの設定\n", "ax.set_ylabel('Vertical Axis', size=20) # 縦軸ラベルの設定\n", "ax.legend()\n", "ax.grid()\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 図を並べる" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "複数の図を並べたいとしよう。考え方としては、透明のキャンバスに複数の軸を設定し、それぞれの軸を使って作図していけば良いのである。キャンバスは四角なので偶数個の軸が設定できる。例として、次のように軸を配置したいとしよう。\n", "```\n", "+---+---+---+\n", "| 1 | 2 | 3 |\n", "+---+---+---+\n", "| 4 | 5 | 6 |\n", "+---+---+---+\n", "```\n", "2行・3列の配置になっており、左上から軸の番号が振られている。このような場合、`subplots()`の2つの引数が必須であり、別の2つの引数が有用である。\n", "```\n", "subplots(行の数, 列の数, sharex=False, sharey=False, constrained_layout=False)\n", "```\n", "* 行の数(デフォルトは`1`):上の例では`2`\n", "* 列の数(デフォルトは`1`):上の例では`3`\n", "* `sharex`(デフォルトは`False`):`True`にすると、全ての図で横軸が同じになり、不要な横軸の数字などを非表示になる。\n", "* `sharey`(デフォルトは`False`):`Ture`にすると、全ての図で縦軸が同じになり、不要な縦軸の数字などを非表示にする\n", "* `constrained_layout`(デフォルトは`False`):`Ture`にすると、全ての図の間隔を調整して見やすくなる。\n", "\n", "上の例を使うと次のようになる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots(2,3)" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "6つの軸が表示されているが、それらは`ax`に割り当てられている。`ax`を表示してみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "ax" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "``が軸を示しており、それぞれの軸に対応している。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "ax.shape" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "軸は`(2,3)`の`array`に格納されているのが確認できる。従って、それぞれの軸は`array`の要素を抽出することによりアクセスできる。\n", "* `ax[0,0]`:軸1を抽出\n", "* `ax[0,1]`:軸2を抽出\n", "* `ax[0,2]`:軸3を抽出\n", "* `ax[1,0]`:軸4を抽出\n", "* `ax[1,1]`:軸5を抽出\n", "* `ax[1,2]`:軸6を抽出\n", "\n", "これを使い次のように6つのを図示できる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots(2,3,figsize=(8,3))\n", "ax[0,0].plot('X', data=df2)\n", "ax[0,1].plot('Y', data=df2)\n", "ax[0,2].plot('Z', data=df2)\n", "ax[1,0].plot('X', data=df2)\n", "ax[1,1].plot('Y', data=df2)\n", "ax[1,2].plot('Z', data=df2)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "横軸と縦軸を共有するには次のようにする。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots(2,3,figsize=(8,3),sharex=True,sharey=True)\n", "ax[0,0].plot('X', data=df2)\n", "ax[0,1].plot('Y', data=df2)\n", "ax[0,2].plot('Z', data=df2)\n", "ax[1,0].plot('X', data=df2)\n", "ax[1,1].plot('Y', data=df2)\n", "ax[1,2].plot('Z', data=df2)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`ax`のメソッド(例えば、軸のタイトル)はそれぞれ設定することができる。" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "次に、キャンバス全体のタイトルを設定したいとしよう。キャンバスは`fig`に割り当てられているので、そのメソッド`suptitle`を使い表示することができる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots(2, 3, figsize=(8,3),\n", " sharex=True, sharey=True,\n", " constrained_layout=True)\n", "ax[0,0].plot('X', data=df2)\n", "ax[0,0].set_title('ax[0,0]')\n", "\n", "ax[0,1].plot('Y', data=df2)\n", "ax[0,1].set_title('ax[0,1]')\n", "\n", "ax[0,2].plot('Z', data=df2)\n", "ax[0,2].set_title('ax[0,2]')\n", "\n", "ax[1,0].plot('X', data=df2)\n", "ax[1,0].set_title('ax[1,0]')\n", "\n", "ax[1,1].plot('Y', data=df2)\n", "ax[1,1].set_title('ax[1,1]')\n", "\n", "ax[1,2].plot('Z', data=df2)\n", "ax[1,2].set_title('ax[1,2]')\n", "\n", "fig.suptitle(\"Grand Title\", fontsize=20)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 2軸グラフ" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "複数のデータを表示する際、右の縦軸を使いデータを表示したい場合がある。例を使って説明することにする。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax1 = plt.subplots() # (1)\n", "\n", "ax2 = ax1.twinx() # (2)\n", "\n", "ax1.plot('X', data=df2) # (3)\n", "ax2.plot('Z', data=df2) # (4)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "コードの説明\n", "\n", "> 1. キャンバスと軸を作成し、軸を`ax1`に割り当てる。\n", "> 2. `ax1`のメソッド`twinx()`を使い、右の縦軸を準備し`ax2`に割り当てる。\n", "> 3. `ax1`に`X`をプロットする。\n", "> 4. `ax2`に`Z`をプロットする。" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "また上で説明した方法で様々な「飾り付け」をすることができる。ただ、凡例については少し追加的なコードが必要となるので、それについても簡単に以下で説明する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax1 = plt.subplots()\n", "\n", "ax2 = ax1.twinx()\n", "\n", "ax1.plot('X', 'k-o', data=df2, label='X series')\n", "ax2.plot('Z', 'r:', data=df2, label='Z series')\n", "\n", "ax1.set_title('Title', size=20) # (1)\n", "ax1.set_ylabel('X data', size=15) # (2)\n", "ax2.set_ylabel('Z data', size=15) # (3)\n", "\n", "ax1.legend() # (4)\n", "ax2.legend(loc=(0.015,0.81)) # (5)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "コードの説明\n", "\n", "> 1. 軸`ax1`にタイトルを設定しているが、`ax2`でも同じ図となる。\n", "> 2. 軸`ax1`の縦軸(左)のラベルを設定する。\n", "> 3. 軸`ax2`の縦軸(右)のラベルを設定する。\n", "> 4. 軸`ax1`に描いた`X`の凡例を設定する。\n", "> * `legend()`には引数がないので`Matplotlib`が自動で凡例の位置を決める。この場合は図の左上に表示されている。\n", "> 5. 軸`ax2`に描いた`Z`の凡例を設定する。\n", "> * `legend(loc=(0.015,0.8))`には引数`loc`があり、凡例の位置を指定している。`(0.015,0.8)`の数字は図の原点を`(0,0)`とて左の数字はx軸、右の数字はy軸の位置を指定している。もし引数を設定しないと、`X`の凡例を上書きすることになる。`(0.015,0.8)`のような指定方法だけではなく、他の方法もあるので[参照サイト](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html)を参考にして欲しい。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "## 日本語" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "2つ方法を紹介するが、`japanize_matplotlib`を使う方法がより簡単であろう。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### `japanize_matplotlib`" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "使い方は到って簡単で、`Pandas`と同様にインポートするだけである。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "import japanize_matplotlib" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fix, ax = plt.subplots()\n", "ax.plot('X', 'Y', 'r-o', data=df2)\n", "ax.set_title('縦横タイトル', size= 30)\n", "ax.set_xlabel('横軸', size=20)\n", "ax.set_ylabel('縦軸', size=20)\n", "ax.legend()\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### フォントを指定する" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "2つの方法:\n", "1. フォントはインストールせず、PC内にあるフォントを指定する。\n", "1. フォントをインストールする方法" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "方法1の場合、以下で説明に使う変数`jfont`にフォントを指定する。\n", " * Macの場合、例えば`AppleGothic`\n", " * Windowsの場合、例えば`Yu Gothic`\n", " * この方法では一部の日本語が文字化けする場合がある。\n", "\n", "方法2の場合:\n", "* [このサイト](https://ipafont.ipa.go.jp/node193#jp)から次の内の1つをダウンロードする。\n", " * 2書体パック(IPAex明朝(Ver.xxx)、IPAexゴシック(Ver.xxx))\n", " * IPAex明朝 (Ver.xxx)\n", " * IPAexゴシック(Ver.xxx)\n", "* [このサイト](https://ipafont.ipa.go.jp/node72#jp)に従ってインストールする。\n", "* 次の両方もしくは1つがPCにインストールされる\n", " * IPAexMincho(IPAex明朝)\n", " * IPAexGothic(IPAexゴシック)\n", "\n", "上の例を使い、設定方法の例を示す。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "jfont = 'IPAexGothic' # (1)\n", "\n", "fix, ax = plt.subplots()\n", "ax.plot('X', 'Y', 'ro-', data=df2)\n", "ax.set_title('縦横タイトル', size= 30, fontname=jfont) # (2)\n", "ax.set_xlabel('横軸', size=20, fontname=jfont) # (3)\n", "ax.set_ylabel('縦軸', size=20, fontname=jfont) # (4)\n", "ax.legend(prop={'family':jfont, 'size':17}) # (5)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ ">* (1) 使用するフォントを`jfont`に割り当てる。\n", ">* (2) 引数`fontname`で`jfont`を指定する。タイトルのフォントが変更される。\n", ">* (3) 引数`fontname`で`jfont`を指定する。横軸名のフォントが変更される。\n", ">* (4) 引数`fontname`で`jfont`を指定する。縦軸名のフォントが変更される。\n", ">* (5) `legend`は他と設定方法が異なる。\n", " * `prop`はフォントのプロパティを設定する引数であり、辞書で指定する。\n", " * キー`family`に値`jfont`を指定する。凡例のフォントが変更される。\n", " * キー`size`に数値を設定してフォントの大きさが変更される。" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "この例では個別にフォントを設定したが、一括で全てのフォントを変更する方法もあるが説明は割愛する。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "## マクロ経済学の例" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 投資関数" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "実質利子率`r`によって投資がどのように変化するかを考えてみよう。まず投資関数を次のように仮定する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "def investment(y):\n", " return 100/(1+r)**50" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "* `100`:実質利子率が`0`の場合の投資\n", "\n", "実質利子率は次のリストで与えられるとする。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "r_list = np.arange(0.01, 0.11, 0.01)\n", "r_list" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "i_list = [] # 空のリスト\n", "\n", "for r in r_list:\n", " inv = investment(r) # 投資の計算\n", " i_list.append(inv) # リストに追加\n", "\n", "df_inv = pd.DataFrame({'investment':i_list, # DataFrameの作成\n", " 'interest_rate':r_list})" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "最初の5行を表示する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "df_inv.head()" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "プロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fix, ax = plt.subplots()\n", "ax.plot('interest_rate', 'investment', data=df_inv)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "この図に次の「飾り付け」をしてみよう。\n", "* タイトル`投資関数`を追加\n", "* 横軸ラベル`実質利子率`を追加\n", "* 縦軸ラベル`投資`を追加" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 将来価値" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`x`万円を実質年率`r`%の利息を得る金融商品に投資し,`t`年間の将来価値(期首の値)をリストで示す関数は以下で与えられた。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "def calculate_futre_value(x, r, t):\n", " \n", " value_list = [x] # 初期値が入ったリスト\n", " \n", " for year in range(1,t+1): # 1からtまでの期間\n", " x = x*(1+r) # 来期のxの値の計算\n", " value_list.append(x) # リストに追加\n", " \n", " return value_list # リストを返す" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "これを使い,\n", "* `x`=`100`\n", "* `t`=`30`\n", "\n", "の下で実質利子率が次のリストで与えられる値を取る場合の将来価値を図示する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "r_list = [0.01, 0.03, 0.06] # 実質利子率のリスト\n", "dic = {} # 空の辞書\n", "\n", "for r in r_list:\n", " dic['r='+str(r)] = calculate_futre_value(100, r, 30) # 辞書に追加\n", "\n", "df_future = pd.DataFrame(dic) # DataFrameの作成" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`dic['r='+str(r)]`の説明:\n", "* `str(r)`:`r_list`の要素が割り当てられる`r`は浮動小数点型なので関数`str()`を使って文字列型に変換する。\n", "* `'r='+str(r)`:文字列型の`r=`と文字列型の`str(r)`を`+`で結合する。\n", "* `dic['r='+str(r)]`:辞書`dic`にキー・値のペアを作成する。\n", " * キー:`'r='+str(r)`(文字列)\n", " * 値:`calculate_futre_value(100, r, 30)`の返り値" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "最初の5行を表示する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "df_future.head()" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "最後の5行を表示する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "df_future.tail()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fix, ax = plt.subplots()\n", "ax.plot('r=0.01', data=df_future)\n", "ax.plot('r=0.03', data=df_future)\n", "ax.plot('r=0.06', data=df_future)\n", "ax.legend()\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`ax.plot()`が続いているので、`for`ループを使う事を推奨する。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fix, ax = plt.subplots()\n", "\n", "for col in df_future.columns: # (1)\n", " ax.plot(col, data=df_future)\n", "\n", "ax.legend()\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "(1)の`df_future.columns`について説明すると、`.columns`はデータ・フレーム`df_future`の属性であり列ラベルを返す。" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "## その他のプロット" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 種類" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "上で説明した図はライン・プロットと呼ばれる。`Matplotlib`にはその他にも様々なは種類の図を描くことができるが,以下ではライン・プロット以外に[散布図](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html)と[ヒストグラム](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hist.html)について説明する。引数に関しては,上で説明した[ライン・プロットの引数](sec:4-other_methods)と共通のものが多いので別に覚える必要はないが,それぞれ独自の引数もあるので基本的なものだけを取り上げることにする。" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "説明には次のコードで生成する`DataFrame`を使う。列`X`と`Y`には標準正規分布(平均`0`,標準偏差`1`)から生成した100個のランダム変数が含まれている。`Z`には正規分布(平均`2`,標準偏差`1`)から抽出した100個のランダム変数が格納されている。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "df3 = pd.DataFrame({'X':np.random.normal(size=100),\n", " 'Y':np.random.normal(size=100),\n", " 'Z':np.random.normal(loc=2, size=100)})" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 散布図" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "* 基本的には次の構文となる。\n", " ```\n", " fig, ax = plt.subplots()\n", " ax.scatter(<横軸のデータ>, <縦軸のデータ>)\n", " ```\n", "* `DataFrame`を使う場合は次のように書くことも可能である。\n", " ```\n", " fig, ax = plt.subplots()\n", " ax.scatter(<横軸の列ラベル>, <縦軸の列ラベル>, data=<DataFrame>)\n", " ```\n", "\n", "`df1`を使って列`X`と`Y`を使ってプロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.scatter('X', 'Y', data=df3)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "**<基本的な引数>**\n", "\n", "様々な引数があり図に「飾り付け」をすることができるが,主な引数を紹介する。[詳細はこのサイト](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html)を参照。\n", "* `color`:色(リストにして列の順番で指定する; [参照サイト](https://matplotlib.org/3.1.0/gallery/color/named_colors.html))\n", " * `r`又は`red`:赤\n", " * `k`又は`black`:黒\n", " * `g`又は`green`:グリーン\n", "* `marker`:観測値のマーカー(`o`,`.`,`>`,`^`などがある; [参照サイト](https://matplotlib.org/3.2.2/api/markers_api.html))\n", "* `s`:マーカーの大きさ(`markersize`ではない!)\n", "* `fontsize`:横軸・縦軸の数字のフォントサイズの設定\n", "* `label`:凡例の表現を指定\n", " * `ax.legend()`が設定されている場合のみ有効\n", "\n", "実際に引数を指定してみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.scatter('X', 'Y', data=df3,\n", " color = 'black',\n", " marker = 'D',\n", " s = 20,\n", " label= 'Xの凡例')\n", "ax.legend()\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`X`と`Z`の散布図を加えてタイトルなども付け加えてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.scatter('X', 'Y', data=df3,\n", " color = 'black',\n", " marker = 'D',\n", " s = 20,\n", " label= 'Xの凡例')\n", "ax.scatter('X', 'Z', data=df3,\n", " color = 'red',\n", " marker = '1',\n", " s = 80,\n", " label= 'Xの凡例')\n", "ax.legend()\n", "ax.set_title('散布図', size=20)\n", "ax.set_xlabel('Xの値', size=15)\n", "ax.set_ylabel('YとZの値', size=15)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### ヒストグラム" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "* 基本的には次の構文となる。\n", " ```\n", " fig, ax = plt.subplots()\n", " ax.hist(<データ>)\n", " ```\n", "* `DataFrame`を使う場合のように書くことも可能である。\n", " ```\n", " fig, ax = plt.subplots()\n", " ax.scatter(<列ラベル>, data=<DataFrame>)\n", " ```\n", " \n", "`df3`の列`X`を使ってプロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.hist('X', data=df3)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "**<基本的な引数>**\n", "\n", "様々な引数があり図に「飾り付け」をすることができる。詳しくは[このリンク](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hist.html)を参照することにして,ここでは基本的な引数だけを紹介する。\n", "* `bins`:柱の数\n", "* `linewidth`又は`lw`:柱の間隔(デフォルトは`1`)\n", "* `color`:色(リストにして列の順番で指定する; [参照サイト](https://matplotlib.org/3.1.0/gallery/color/named_colors.html))\n", " * `r`又は`red`:赤\n", " * `k`又は`black`:黒\n", " * `g`又は`green`:グリーン\n", "* `edgecolor`又は`ec`:柱の境界線の色\n", "* `alpha`:透明度(`0`から`1.0`; デフォルトは`1`)\n", "* `density`:縦軸を相対度数にする(デフォルトは`False`)\n", " * 全ての柱の**面積**の合計が`1`になるように縦軸が調整される。1つの柱の高さが`1`よりも大きくなる場合もある。\n", "* `label`:凡例の表現を指定\n", " * `ax.legend()`が設定されている場合のみ有効\n", " \n", "上のヒストグラムに引数をしてしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.hist(df3['X'],\n", " color='green',\n", " bins = 20,\n", " ec='white',\n", " lw=3,\n", " density=True)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "次に複数のデータを並べてプロットする場合を考えよう。方法は簡単で,異なるデータをリストとして指定すれば良い。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.hist([df3['X'],df3['Z']],\n", " bins = 20,\n", " color = ['black','red'],\n", " ec='black',\n", " label=['Xの凡例','Yの凡例'])\n", "ax.legend()\n", "ax.set_title('ヒストグラム', size=20)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "上のコードに引数`stacked=True`を加えると,柱を重ねて表示される。試してみよう。また`ax.hist()`を2回使うと,2つのヒストグラムを重ねて表示することができる。この場合,引数`alpha`の値を調整すると良いだろう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.hist(df3['X'],\n", " bins = 20,\n", " color = 'black',\n", " ec='black',\n", " alpha=0.5,\n", " label='Xの凡例')\n", "ax.hist(df3['Z'],\n", " bins = 20,\n", " color = 'red',\n", " ec='black',\n", " alpha=0.5,\n", " label='Zの凡例')\n", "ax.legend()\n", "ax.set_title('ヒストグラム', size=20)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "濃い赤の部分が重なっている部分となる。" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "ヒストグラムは縦軸に度数,横軸に階級を取ったグラフだが,関連する手法にカーネル密度推定と呼ばれるものがある。考え方は簡単で,上のようなヒストグラムのデータに基づき面積が1になるようにスムーズな分布を推定する手法である。残念ながら`Matplotlib`にはカーネル密度推定プロットのメソッドは実装されていない。しかし`DataFrame`のメソッド`plot()`を使えば簡単に描くことが可能である。興味がある読者は[このセクション](sec:5-kernel)を参考にしてはどうだろう。\n" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true, "hidden": true }, "source": [ "### 縦線・横線" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "図に縦線や横線を追加したい場合がある。その場合は,他の図と同じように「軸」に追加していく事になる。次のような書き方となる。\n", "\n", "* 縦線の場合\n", " ```\n", " ax.axvline(<横軸の値>)\n", " ```\n", " ここで`axvline`の`ax`はAXis,`v`はVertical,`line`はLINEのことを表している。\n", "* 横線の場合\n", " ```\n", " ax.axhline(<縦軸の値>)\n", " ```\n", " ここで`axhline`の`ax`はAXis,`h`はHorizontal,`line`はLINEのことを表している。\n", "\n", "ここで`ax`は`.subplots()`で返された「軸」のことである。\n", "\n", "ヒストグラムを使ってプロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.hist(df3['X'], alpha=0.2)\n", "ax.axhline(10)\n", "ax.axvline(0)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "**<基本的な引数>**\n", "\n", "様々な引数があり図に「飾り付け」をすることができる。詳しくは[このリンク](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.axvline.html)と[このリンク](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.axhline.html)を参照することにして,ここでは基本的な引数だけを紹介する。\n", "* `ymin`:`axvline`の縦軸における最小値(`0`~`1`の値; デフォルト`0`)\n", "* `ymax`:`axvline`の縦軸における最大値(`0`~`1`の値; デフォルト`1`)\n", "* `xmin`:`axhline`の横軸における最小値(`0`~`1`の値; デフォルト`0`)\n", "* `xmax`:`axhline`の横軸における最大値(`0`~`1`の値; デフォルト`1`)\n", "* `linestyle`:線のスタイル(リストにして列の順番で指定する;`-``--``-.``:`)\n", "* `linewidth` or `lw`:線の幅\n", "* `color`:色(リストにして列の順番で指定する; [参照サイト](https://matplotlib.org/3.1.0/gallery/color/named_colors.html))\n", " * `r`は赤\n", " * `k`は黒\n", " * `g`はグリーン\n", "* `alpha`:透明度(`0`から`1.0`; デフォルトは`1`)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.hist(df3['X'], alpha=0.2)\n", "ax.axvline(0,\n", " ymin=0.3,\n", " ymax=0.95,\n", " linestyle=':',\n", " linewidth=5,\n", " color='g',\n", " alpha=0.8)\n", "ax.axhline(10,\n", " xmin=0.05,\n", " xmax=0.7,\n", " linestyle='-.',\n", " linewidth=3,\n", " color='k',\n", " alpha=0.5)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "### 棒グラフ" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "まず次のコードでデータを準備しよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "df4 = pd.DataFrame({'country':['A','B','C'],\n", " 'gdp':[100,90,110],\n", " 'con':[50,60,55],\n", " 'inv':[15,10,20],\n", " 'gov':[10,5,30],\n", " 'netex':[25,15,5]})\n", "df4" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "3国のGDPとその構成要素からなる`DataFrame`である。\n", "* `country`:国\n", "* `gdp`:GDP\n", "* `con`:消費\n", "* `inv`:投資\n", "* `gov`:政府支出\n", "* `netex`:純輸出\n", "\n", "この`DataFrame`を使って棒グラフの作成方法を説明するが,次の構文となる。\n", " ```\n", " fig, ax = plt.subplots()\n", " ax.scatter(<横軸の列ラベル>, <縦軸の列ラベル>, data=<DataFrame>)\n", " ```\n", "\n", "まずA国の`gdp`の棒グラフを表示してみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.bar('country','gdp', data=df4)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "**<基本的な引数>**\n", "\n", "詳しい引数についての説明は[このリンク](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar.html)を参照することにして,ここでは基本的な引数だけを紹介する。\n", "* `width`:棒の幅(デフォルトは`0.8`)\n", "* `bottom`:縦軸での棒の基点(デフォルトは`0`)\n", "* `color`:色(リストにして列の順番で指定する; [参照サイト](https://matplotlib.org/3.1.0/gallery/color/named_colors.html))\n", " * `r`又は`red`:赤\n", " * `k`又は`black`:黒\n", " * `g`又は`green`:グリーン\n", "* `edgecolor`又は`ec`:柱の境界線の色\n", "* `linewidth`又は`lw`:柱の境界線の幅\n", "* `alpha`:透明度(`0`から`1.0`; デフォルトは`1`)\n", "* `label`:凡例の表現を指定\n", " * `ax.legend()`と一緒に使う。\n", "\n", "これらの引数を使いプロットしてみよう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.bar('country','gdp', data=df4,\n", " width=0.5,\n", " color='green',\n", " ec='black',\n", " linewidth=5,\n", " alpha=0.5,\n", " label='GDP')\n", "ax.legend()\n", "ax.tick_params(axis='both', labelsize=15)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "`ax.tick_params()`は縦軸と横軸の文字の大きさを調節している。\n", "\n", "次に複数の列データを表示する場合を考えてみよう。まず単に軸にデータを追加する場合を考えてみる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "ax.bar('country','con', data=df4, label='消費')\n", "ax.bar('country','inv', data=df4, label='投資')\n", "ax.legend()\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "縦軸を確認するとわかるが,まず消費(`con`)の棒がプロットされ,それに投資(`ivn`)の棒が重ねてプロットされている。これは引数`base`(縦軸における棒の基点)がデフォルトの`0`に設定されており,消費も投資も`0`から始まっているためである。この点を踏まえ,棒を積み上げる場合を考えよう。その場合,投資の`base`は消費の高さになる必要がある。また政府支出を積み上げる場合は,積み上がった消費の高さが政府支出の基点になる必要がある。純輸出を積み上げる場合も同様に考える必要がある。この点に注意して棒を積み上げるには次のようなコードとなる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "base = df4.iloc[:,2:].cumsum(axis='columns') # (1)\n", "base = base - df4.iloc[:,2:] # (2)\n", "\n", "var_list = df4.columns[2:] # (3)\n", "leg_list = ['消費','投資','政府支出','純輸出'] # (4)\n", "\n", "fig, ax = plt.subplots()\n", "\n", "for v, l in zip(var_list, leg_list):\n", " ax.bar('country', v, data=df4,\n", " label=l,\n", " bottom=base.loc[:,v]) # (5)\n", "\n", "ax.plot('gdp', data=df4, # (6)\n", " color='black', \n", " marker='o',\n", " label='GDP')\n", "ax.legend()\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "(1)〜(2)で棒の基点となる値を`DataFrame`として計算し,それを(5)で使っている。(3)〜(4)行目は`for`ループに使うイタラブルを作成している。また(6)では列`gdp`のライン・プロットを追加している。コードを見るとわかるように,少々複雑である。よりシンプルなコードで同じ図を描きたい場合は,[ここで](sec:5-bar)説明している`DataFrame`のメソッド`plot()`を参考にすると良いだろう。その方法では(1)〜(2)を自動計算するため引数`base`の値を考える必要がない。" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "次に,複数の棒(データ)を横に並べたい場合を考えてみよう。主に次の2つの点でコードが少々複雑になってしまう。\n", "* 引数`width`を使い,棒の横の位置を調整する必要がある。\n", "* 国名`A`,`B`,`C`の位置を調整する必要がある。\n", "\n", "この2点を考慮すると次のコードとなる。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hidden": true }, "outputs": [], "source": [ "idx = df4.index # (1)\n", "wd = 1/5 # (2)\n", "x_ticks = df4.loc[:,'country'] # (3)\n", "\n", "fig, ax = plt.subplots(figsize=(8,4))\n", "\n", "for i, (v, l) in enumerate(zip(var_list, leg_list)):\n", " ax.bar(idx+wd*(i+1), # (4)\n", " v,\n", " data=df4,\n", " label=l,\n", " width=wd) # (5)\n", " \n", "ax.legend()\n", "ax.set_xticks(idx+wd*2.5, # (6)\n", " x_ticks, # (7)\n", " fontsize=15) # (8)\n", "pass" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "簡単にコードを説明する。\n", "* (1) `df4`の行インデック(番号)を`idx`に割り当てる。これを図の横軸に使う。そのままでは国名が表示されないので,(7)で設定することになる。\n", "* (2) 棒の幅を`1/5`として`wd`に割り当てる。\n", "* (3) 国名を`x_ticks`に割り当てる。(7)で使うことになる。\n", "* (4) 棒の横軸の位置を指定する。ループが実行されるごとに表示される棒は`wd`だけ右にシフトすることになる。\n", "* (5) 棒の幅を`wd`にする。\n", "* (6) 横軸の目盛の位置を指定する。\n", "* (7) 横軸の目盛ラベルを国名`x_ticks`とする。\n", "* (8) 目盛ラベルのフォントの大きさを指定する。\n", "\n", "よりシンプルなコードで同じ図を書きたい場合は,[ここで](sec:5-bar)説明している`DataFrame`のメソッド`plot()`を使う方法を利用しても良いだろう。" ] } ], "metadata": { "celltoolbar": "Tags", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" } }, "nbformat": 4, "nbformat_minor": 4 }