【初心者も完全理解】matplotlibまとめ

matplotlibとは
pythonを用いたグラフ描画ライブラリ。折線グラフやヒストグラム、3次元グラフなどさまざまなグラフをかける。

 

matplotlib、構文が分かりそうで分からない!
初めてmatplotlibを扱うときにこのような感想をもったことあがあるのではないでしょうか。
その原因はズバリ、

 

matplotlibに2つの流儀が存在するから

 

なのです。plt.で始まったり、ax.で始まったり…
この記事では、matplotlibの基本的な構造を理解することで、自由に使いこなせることを目標に解説していきます!
matplotlib使う必要ある?という方へ。
matplotlibの良さは、

  • pythonなどでデータ処理、機械学習をした後すぐに同じ環境でデータを可視化できる
  • データをプロットする時間がexcelなどと比べ、段違いに速い
  • なので膨大な実験データやデータのフィッティングもすぐに描画できる
  • 細かい設定をコードで指定できるので、自由度が高い

などなど。使えるか不安という方も、この記事で必ず使えるように解説します。

 

 

2つの流儀とは

2つの流儀があるため、コードが複雑に感じるという導入をしました。

その2つの流儀とは、

  1. ステートフルインターフェイス (plt.の方)
  2. オブジェクト指向インターフェイス (ax.の方)

というものです。

その違いをざっくり言うと、

①の方は、pyplotというコマンドで順番に操作をしていく (プロットとか軸設定とか)

一方で、②の方は、操作したい箇所をダイレクトに操作できる

なので、細かい設定をたくさんしたり、subplotとしてグラフを多数分割するようなときには、オブジェクト指向の方がわかりやすく、ラクです。

じゃあどっちがいいの?
個人的には、細かい設定がしやすく、現状を把握しやすいオブジェクト指向インターフェイスの方が好きです。
後で紹介しますが、わずかながらコード数も少なくて済みます

 

それでは、オブジェクト指向インターフェイスの方を説明していきます。

 

~coffee break~
オブジェクト指向とは? オブジェクト(データや処理のまとまり)を定義し、そこに命令をすることで目的の操作を達成するようなもの。例えるなら、エアコンを操作するために、リモコン (オブジェクト) を作り、それを操作する。こうすることで、作業が分担され操作性も良くなる。
今回のmatplotlibで言えば、下で説明するFigureやAxesといったオブジェクトを定義し、それに操作をすることで作業が簡単・明確になる。

 

 

 

オブジェクト指向インターフェイス

まず、matplotlibの構造の概念を図で表します。

 

 

Figureオブジェクトという大枠の中に、Axesオブジェクトという枠が張り付いてあり、その中でグラフを描画しています

なので、プログラミングの順番も、まずFigureオブジェクトを生成して、その中にAxesオブジェクトを追加し、グラフをプロットしたり様々な操作をする、といった風になります。

この流れがわかればコードがかなりスッキリして見えるはずです!

それでは、実際にやってみましょう。

 

import matplotlib.pyplot as plt
import numpy as np 

まずはインポートします。今回はnumpyも使うのでnumpyもインポートします。

pltの部分は他の文字列でも良いのですが、慣習としてpltが使われています。

Jupyter Notebookなどを使うときにはインライン表示のために、%matplotlib inline  というコードも入力してください。

次にFigureとAxesを見てみます。

fig = plt.figure(figsize=(3,3), dpi=100, facecolor="skyblue")
ax = fig.add_subplot(111)

 

 

これで水色のFigureの中にAxesを貼ることができました。

plt.plotの中の引数は、figsize(図の大きさ)、dpi(dodts per inches)、facecolor (今回はわかりやすく水色)、linewidth など他にもあります (下表)

これらを設定しないとデフォルトのものが返ってきます。

引数 意味
figsize Figureのサイズ指定
dpi dots per inches
facecolor 図の背景色
linewidth 図の外枠の太さ
edgecolor 図の枠の色
tight_layout Trueにするとオブジェクトの配置が自動調整される

 

fig.add_subplot()の引数はグラフの位置を表します。(2,1,1)の場合、(2行, 1列, 1つ目) を指します。番号の順序は左上から右下です

それではこの中にsin関数を書いてみましょう。

 

fig = plt.figure(figsize=(3,3), dpi=100)
ax = fig.add_subplot(111)
x = np.linspace(-np.pi, np.pi, 100)
y = np.sin(x)
ax.plot(x,y)
plt.show()

 

プロットができれば、あとは見た目の細かい設定をしていきます。

plt.rcParams['xtick.direction'] = 'in' #目盛り内向き 初めに設定しておく
plt.rcParams['ytick.direction'] = 'in' #目盛り内向き 初めに設定しておく
fig = plt.figure(figsize=(4,4), dpi=100)
ax = fig.add_subplot(111)
x = np.linspace(-np.pi, np.pi, 100)
y1 = np.sin(x)
y2 = np.sin(x+1)
ax.plot(x, y1, color="black", linewidth=1.0, linestyle="-", label='sinx') #y1のプロット
ax.plot(x, y2, color="red", linewidth=1.0, linestyle="-", label='sinx') #y2のプロット
ax.set_title('sinx') #タイトル
ax.set_xlim(-3.5,3.5) #xの範囲
ax.set_xlabel(r"$\theta$ [rad]", fontsize=12) #xラベル
ax.set_ylim(-1.4, 1.4) #yの範囲
ax.set_ylabel("y", fontsize=12) #yラベル
ax.legend(loc="best") #凡例
plt.show()

 

plot()の引数でよく使うのは以下の通りです。

引数 意味
label 凡例に表示されるプロットのラベル
color 線の色
linestyle 折れ線の線種
linewidth 折れ線の太さ
alpha 透明度を0~1で指定
marker マーカーの形状 (Noneでマーカーなし)
markersize マーカーのサイズ
markerfacecolor マーカーの色 (mfcでも可)
markeredgewidth マーカーの縁の太さ (mewでも可)
markeredgecolor マーカーの縁の色 (mecでも可)

 

引数は多くあるので当然全て覚える必要はありません。

必要に応じてmatplotlib公式サイトで探すと良いと思います。

また、色の種類とコードは 原色大辞典 をみてみると良いかもしれません。

グラデーションはこちら(matplotlib公式)を参考にしてみてください。

 

2つのsin関数を分割したAxesにプロットしてみます。

plt.rcParams['xtick.direction'] = 'in' #目盛り内向き 初めに設定しておく
plt.rcParams['ytick.direction'] = 'in' #目盛り内向き 初めに設定しておく
fig = plt.figure(figsize=(4,4), dpi=100)
ax1 = fig.add_subplot(211) #ax1をAxesの(2,1)の(1,1)に生成
ax2 = fig.add_subplot(212) #ax2をAxesの(2,1)の(2,1)に生成
x = np.linspace(-np.pi, np.pi, 100)
y1 = np.sin(x)
y2 = np.sin(x+1)
ax1.plot(x, y1, color="black", linewidth=1.0, linestyle="-", label='sinx') #y1のプロット
ax2.plot(x, y2, color="red", linewidth=1.0, linestyle="-", label='sinx') #y2のプロット
plt.show()
ここではAxesを2行1列に分割し、それぞれをax1、ax2と名付けています。
そうすることでそれぞれのAxesに対し命令ができます。
しかし、分割が増えると大変です
そこで、FigureとAxesを同時に生成することでより楽に書くことができます。

 

 

一番おすすめの書き方

FigureとAxesを同時に生成して、上と同様のグラフを書きます。

plt.rcParams['xtick.direction'] = 'in' #目盛り内向き 初めに設定しておく
plt.rcParams['ytick.direction'] = 'in' #目盛り内向き 初めに設定しておく
fig, ax = plt.subplots(2, 1, figsize=(4,4), dpi=100)
x = np.linspace(-np.pi, np.pi, 100)
y1 = np.sin(x)
y2 = np.sin(x+1)
ax[0].plot(x, y1, color="black", linewidth=1.0, linestyle="-", label='sinx') #y1のプロット
ax[1].plot(x, y2, color="red", linewidth=1.0, linestyle="-", label='sinx') #y2のプロット
plt.show()

コード3行目でsubplots()メソッドを用いて最大2次元のAxes配列を生成して、7、8行目でaxの配列を指定しています。

そうすることで、axを位置ごとに定義しなくて済むため、コードが簡潔になります

Axesを分割しないときは、subplots()の引数を空白にすれば大丈夫です。

 

例えば3行3列のAxesの場合は以下のようになります。

plt.rcParams['xtick.direction'] = 'in' #目盛り内向き 初めに設定しておく
plt.rcParams['ytick.direction'] = 'in' #目盛り内向き 初めに設定しておく
fig, ax = plt.subplots(3, 3, figsize=(4,4), tight_layout=True, dpi=100)
x = np.linspace(-np.pi, np.pi, 100)
y1 = np.sin(x)
y2 = np.sin(x+1)
ax[0,1].plot(x, y1, color="black", linewidth=1.0, linestyle="-", label='sinx') #y1のプロット
ax[1,2].plot(x, y2, color="red", linewidth=1.0, linestyle="-", label='sinx') #y2のプロット
plt.show()
この場合、3行3列のAxes配列を生成し、1行2列と2行3列にプロットをしています。

 

ステートフルインターフェイス

先ほどのsin関数をプロットするためのコードは以下のようになります。

plt.rcParams['xtick.direction'] = 'in' #目盛り内向き 初めに設定しておく
plt.rcParams['ytick.direction'] = 'in' #目盛り内向き 初めに設定しておく
x = np.linspace(-np.pi, np.pi, 100)
y1 = np.sin(x)
y2 = np.sin(x+1)
plt.subplot(211)
plt.plot(x, y1, color="black", linewidth=1.0, linestyle="-", label='sinx') #y1のプロット
plt.subplot(212)
plt.plot(x, y2, color="red", linewidth=1.0, linestyle="-", label='sinx') #y2のプロット
plt.show()
このようにplt.を用いて上から順に命令が実行されます。
以上でmatplotlibの基本概念の説明は終了です!

 

 

 

style

plt.style.use()

を用いてプロットのスタイルを変更することができます。

何も指定しなければデフォルトでプロットが作成されます。

例えば先ほどのグラフをプログラミング言語Rの描画パッケージっぽくプロットしてみます。

plt.style.use('ggplot')
plt.rcParams['xtick.direction'] = 'in' #目盛り内向き 初めに設定しておく
plt.rcParams['ytick.direction'] = 'in' #目盛り内向き 初めに設定しておく
fig = plt.figure(figsize=(4,4), dpi=100)
ax = fig.add_subplot(111)
x = np.linspace(-np.pi, np.pi, 100)
y1 = np.sin(x)
y2 = np.sin(x+1)
ax.plot(x, y1, color="black", linewidth=1.0, linestyle="-", label='sinx') #y1のプロット
ax.plot(x, y2, color="red", linewidth=1.0, linestyle="-", label='sinx') #y2のプロット
ax.set_title('sinx') #タイトル
ax.set_xlim(-3.5,3.5) #xの範囲
ax.set_xlabel(r"$\theta$ [rad]", fontsize=12) #xラベル
ax.set_ylim(-1.4, 1.4) #yの範囲
ax.set_ylabel("y", fontsize=12) #yラベル
ax.legend(loc="best") #凡例
plt.show()

 

他にも様々なスタイルがあり、例がmatplotlib公式サイトにあるのでぜひ参考にしてみてください。

 

 

 

画像の保存

コードの一番最後に、

fig.savefig("ファイル名.png", dpi=300)

と追加すれば大丈夫です。Google colabを使うときはパスも設定すると保存場所がわかりやすいと思います。

ファイルの拡張子はpngの他にもpdfなどがあります。

また、dpiで任意の解像度を指定できます。

 

 

 

まとめ

matplotlibには、

  1. オブジェクト指向
  2. 手続き型

の流儀があることがわかりました。

これを理解することで、コードも明快になったのではないでしょうか。

もし説明が不十分な箇所がありましたら、ぜひお問い合わせに一報いただけると幸いです。

Programmingの最新記事8件