Pythonを使ってのデータを視覚化するためのライブラリMatplotlibの導入と簡単な使い方は見てきました。
簡単なことならこれでグラフの描画はできますが、実際にはもっと複雑な表現をグラフに施す場面が多いのが現実です。
ここではMatplotlibを使ってデータをグラフで可視化する時の色々なメソッドについて見ていきたいと思います。
オブジェクトとしてグラフを表示する
これまではデータをグラフを単に表示しただけですが、ここからはグラフ自体をオブジェクトとして考えることでグラフ自体に色々な操作や加工をしていきます。それによって、グラフを思ったように表示することができるようになります。
まずはここで扱うデータを次のように用意します。(前の記事と同じデータです)
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
x = np.linspace(0, 10, 11)
y = x ** 2
figure()でオブジェクト化
まず、グラフのオブジェクトを作成し、そのオブジェクトに対してメソッドや属性を指定していくという流れになります。
まずはこのデータを使って簡単に表示してみると次のようなコードになります。
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes.plot(x, y, 'b')
axes.set_xlabel('x軸')
axes.set_ylabel('y軸')
axes.set_title('グラフタイトル')
plt.show()
最初にfigure()を使って、グラフを表示する領域を作ります。これをfigというオブジェクトにして操作して行きます。
この領域にadd_axes()を使ってグラフを表示します。このときの引数は順にグラフの左下を基準にしてx座標、y座標、幅、高さを0から1までの相対的な割合で指定しています。
plot()にデータとグラフの色(ここでは青を意味するb)を指定し、各ラベルに表示する文字列を与えます。(ラベル等についてはあとで扱います)
show()でグラフを表示するとこうなります。
この表示自体は、figure()を使わずにそのままプロットしたものと変わりませんが、figure()を使うことでグラフの配置場所を制御することができ、次のように複数のグラフを簡単に追加することができます。
fig = plt.figure()
axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3])
axes1.plot(x, y, 'b')
axes1.set_xlabel('青x軸')
axes1.set_ylabel('青y軸')
axes1.set_title('青色グラフ')
axes2.plot(y, x, 'r')
axes2.set_xlabel('赤x軸')
axes2.set_ylabel('赤y軸')
axes2.set_title('赤色グラフ')
plt.show()
add_axes()を2つ使って2つのグラフを作っていること以外、先ほどの例とやっていることは同じです。違いを示す為にデータをそれぞれ逆にしています。先ほどのグラフの中にもう1つのグラフデータを位置と大きさを調整して一緒に表示しているコードになります。axes1とaxes2のadd_axes()で指定する位置に注意してグラフを表示しています。
グラフの中にグラフを埋め込むような形で表示されているのがわかります。
このようにfigure()でまずオブジェクト化して、これにメソッドで加えていくことになります。
グラフ表示に関する色々な方法
それでは、figure()でオブジェクト化したグラフを操作していくための、色々な方法、メソッドについて見ていきましょう。
subplots()
subplots()を使えば、一度に複数のグラフ表示領域を作ることができます。
基本的な使い方は次の通りです。
fig, axes = plt.subplots()
axes.plot(x, y, 'blue')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('グラフタイトル')
plt.show()
これは特に何もしていないので、グラフはこれまでと同じ表示になります。ただし、figとaxesにアンパッキングしていることに注目です。あとで見ますが、axesに複数のグラフのデータを入れることになる為です。
これを複数のグラフ表示にするためには、subplots()に行と列の数を次のように指定します。
fig, axes = plt.subplots(nrows=1, ncols=2)
行数が1で列数が2となっています。(数字のみを順に指定しても構いません)
何も指定していないので、空のグラフが2つ表示されています。
ここでaxesを見てみると次のような配列のデータになっているのがわかります。
これはグラフを表示部分が2つあるというような意味の配列と考えればいいでしょう。
これをそれぞれ取り出して、データを入れてみることにします。
for ax in axes:
ax.plot(x, y, 'b')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('グラフ')
fig
それぞれ同じデータを入れてグラフを表示するコードになっています。
実行するとこのようになります。
2つのグラフが表示されました。
tight_layout()
でも、よく見ると右側のグラフのy軸のラベルが左側のグラフに重なってしまって表示がおかしくなっています。
matplotlibは2つのものを重ねて表示するものなので、このようなことが起ります。
これを調整する為に、グラフ描画の際にtight_layout()を使います。
fig, axes = plt.subplots(nrows=1, ncols=2)
for ax in axes:
ax.plot(x, y, 'g')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('間隔のあるグラフ')
fig
plt.tight_layout()
やっていることは先ほどと同じですが、tight_layout()を最後に使っています。
グラフの重なっている部分が調整されているのがわかります。
figsizeとdpi
Matplotlibのfigure()でグラフのオブジェクトを作成する際に、アスペクト比、dpi値を与えることで、グラフ描画のサイズを指定することができます。
figure()にfigsizeおよびdpiキーワード引数を使用して値を渡します。
- figsizeには、図の幅と高さをタプルで指定
- dpiには1インチあたりのドット数(ピクセル/インチ)を指定
次のように指定して使います。
fig = plt.figure(figsize=(8,4), dpi=100)
これまで利用してきたデータで具体的にグラフを描画してみます。
fig, axes = plt.subplots(figsize=(12,3))
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title')
plt.show()
それぞれ実行するとこうなります。
指定したアスペクト比のように横長のグラフになっているのがわかります。
グラフ画像の保存
Matplotlibで描画したグラフは、PNG、JPG、EPS、SVG、PGF、PDFなどの形式で画像データとしてファイルに出力することができます。
グラフをファイルに保存するには、savefig()メソッドにファイル名を指定して次のように使用します。
fig.savefig("graph_name.png")
また、次のようにdpi値を指定していろんなフォーマットで保存することもできます。
fig.savefig("graph_name.png", dpi=200)
画像ファイルが、同じ作業ディレクトリ内に作成されるはずです。
グラフのタイトル、軸ラベル、凡例
グラフは、単にデータを表示するだけでは意味がわかりません。これまでもグラフに記入して来たように、タイトルなどのラベルをつける必要があります。その方法についてまとめておきましょう。
なお、別の記事でも触れましたが、matplotlibをデフォルトで日本語を表示させると文字化けするので日本語化の設定をする必要があります。
タイトル – set_title()
グラフにタイトルをつけるにはset_title()を使って、タイトル名を記入します。
次のようにコードを記入します。
ax.set_title("タイトルを記入")
軸ラベル – set_xlabel(), set_ylabel()
グラフにはx軸、y軸があるのでラベルをつけてグラフの意味をわかりやすいようにする必要があります。それにはset_xlabel()、 set_ylabel()を使ってそれぞれ軸にラベルを記入します。
ax.set_xlabel("x軸のラベルを記入")
ax.set_ylabel("y軸のラベルを記入")
凡例 – legend()
グラフに複数のデータがプロットされた時、それぞれ何のデータのグラフなのかがわかると便利です。それを凡例という形でグラフに表示できます。
その為にはplot()する際に、labelキーワードに凡例の値を渡しておくことで、legend()を使ってグラフ内に表示することができます。
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.plot(x, x**2, label="x**2")
ax.plot(x, x**3, label="x**3")
ax.legend() # ax.legend(loc=0)
plt.show()
2つのplot()に対し、それぞれlabelを使って値の計算式をここでは渡しています。そしてそれをlegend()で呼び出しています。
実行するとこうなります。
ちなみに、legend()のところでコメントアウトしていますが、loc=0を渡しているのと同じ意味で、適当な場所に凡例を配置してくれるようになっています。
この凡例の配置は、次のように位置をそれぞれ指定することもできます。
ax.legend(loc=1) # 左上の角
ax.legend(loc=2) # 右上の角
ax.legend(loc=3) # 左下の角
ax.legend(loc=4) # 右下の角
試しに、loc=4を指定して右下の角の表示してみましょう。
ax.legend(loc=4)
fig
グラフの右下に凡例が表示されているのがわかります。これだとグラフの邪魔なので本来なら左上のloc=1を指定するべきですね。その他の表示の方法もありますが、ここでは触れません。公式ドキュメントを参照のこと。
グラフの線の色、幅、線の種類の設定
Matplotlibには、グラフを描画した時の線の色、線の幅、線の種種をカスタマイズするためのオプションがあります。これによって複数のグラフの線の区別をすることができます。
グラフのカスタマイズの基本
グラフの色や線の種類をカスタマイズする方法の基本的な形は次のようなコードになります。
fig, ax = plt.subplots()
ax.plot(x, x**2, 'b.-')
ax.plot(x, x**3, 'g--')
plt.show()
plot()に、オプションとして色と線の種類を指定しています。ここではbは青、gは緑、色に続けて.-と書くことでドット付きの線、–と書くことで破線となるオプションになります。
指定された色と線の種類で表示されているのがわかります。
グラフの色のパラメータ
グラフの色の指定はblueやbのように色の名前や略をこれまで指定して来ましたが、color引数にパラメータとしてRGB16進数カラーコードで色を指定することもできます。また、alphaキーワード引数を使ってグラフの不透明度を指定することもできます。
fig, ax = plt.subplots()
ax.plot(x, x+1, color="blue", alpha=0.5)
ax.plot(x, x+2, color="#900000")
ax.plot(x, x+3, color="#1BB400")
plt.show()
不透明度、RGB16進数カラーコードを指定しているのがわかります。
指定した色になっていますし、透明度も他のグラフの青と比べると薄くなっているのがわかります。
グラフの線、マーカーのスタイル
グラフの線は色だけでなく幅を変えたり、線の種類を変えたりマーカーをつけたりすることができます。
線幅を変更するには、linewidthまたはlwキーワード引数に値を指定します。。ラインスタイルは、linestyleキーワードまたはlsキーワード引数を使用して設定できます。マーカーはmarkerを使います。
詳細は公式ドキュメントに当たる必要がありますが、主なものを次のコードで表示して見ましょう。
fig, ax = plt.subplots(figsize=(10,5))
ax.plot(x, x+1, color="blue", linewidth=0.25)
ax.plot(x, x+2, color="blue", linewidth=0.50)
ax.plot(x, x+3, color="blue", linewidth=1.00)
ax.plot(x, x+4, color="blue", linewidth=2.00)
ax.plot(x, x+5, color="green", lw=3, linestyle='-')
ax.plot(x, x+6, color="green", lw=3, ls='-.')
ax.plot(x, x+7, color="green", lw=3, ls=':')
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10])
ax.plot(x, x+ 9, color="red", lw=3, ls='-', marker='+')
ax.plot(x, x+10, color="red", lw=3, ls='--', marker='o')
ax.plot(x, x+11, color="red", lw=3, ls='-', marker='s')
ax.plot(x, x+12, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='s', markersize=8,
markerfacecolor="yellow", markeredgewidth=3, markeredgecolor="green")
plt.show()
15本のグラフを描いてみました。
最初の4本は青色の線で、線の幅をそれぞれ変えています。
次の3本は緑色の線で、線の種類は順に線、点と線、破線と指定しています。
次の線は黒色で、ダッシュ線を入れています。set_dashes()にリストでそのパターンを数値で渡しています。この時、グラフ自体をline, として渡してfig, に追加しているという違いがあります。
次の3本は赤色でそれぞれ違うマーカーを入れています。
最後の4本はマーカーのサイズを変更しています。そのうち最後の2つはマーカーの表示を細かく変更しています。
実行するとこう表示されます。
コードの上の部分から順にグラフでは下から描画されていますので、それぞれ一度見ておくのもいいでしょう。
プロット範囲の制御
グラフはいつもそのまま描画することはなく、軸を調整して描画の範囲を指定することがあります。
軸の範囲を設定するにはset_ylim()、set_xlim()にリストで範囲指定します。上の方でも触れましたが軸範囲を自動的に調整する( ‘tight’)もあります。
次のコードで具体的に見てみましょう。
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
axes[0].plot(x, x**2, x, x**3)
axes[0].set_title("デフォルト表示")
axes[1].plot(x, x**2, x, x**3)
axes[1].axis('tight')
axes[1].set_title("tightに表示")
axes[2].plot(x, x**2, x, x**3)
axes[2].set_ylim([0, 60])
axes[2].set_xlim([2, 5])
axes[2].set_title("範囲調整して表示")
plt.show()
subplots()で1行3列のグラフを作っています。それぞれリストのインデックスでグラフの位置を指定し、範囲をそれぞれ指定しています。
tightはちょっとわかりずらいものとなっていますが、右端の範囲が調整されているのはグラフの軸を見ればわかりますね。
その他の特殊なグラフ描画
ここまでグラフの基本的な使い方を見てきましたが、上で扱ったような見慣れたグラフだけでなく、散布図、ヒストグラム、箱ひげ図など、特殊なグラフをプロットすることもできます。
ここでは、特殊なグラフ表示の例としてこの3つを見ておきましょう。
散布図
散布図はこれまで別の投稿でも触れたことがありますが、scatter()を使います。
plt.scatter(x,y)
plt.show()
ヒストグラム
ヒストグラムは度数分布を表すグラフで、hist()にデータを渡して表示できます。
適当なデータをsample()にrange()を使って表示してみます。
from random import sample
data = sample(range(1, 1000), 100)
plt.hist(data)
plt.show()
箱ひげ図
箱ひげ図はデータのばらつきを表現するグラフです。boxplot()にデータを渡して表示させます。
data = [np.random.normal(0, std, 100) for std in range(1, 11)]
plt.boxplot(data,vert=True,patch_artist=True)
plt.show()
vert=Trueで垂直表示、patch_artistで塗りつぶしをしています。
これらのグラフは、実際にはPythonの統計プロットライブラリであるseabornを使用して作成されることが多いでしょう。seabornの方が綺麗なグラフとして表示することができます。これについては別の機会に触れていくことにします。
最後に
Pythonを使ってのデータを視覚化するためのライブラリMatplotlibの導入と簡単な使い方を見てきましたが、実際にはもっと複雑な表現をグラフに施す必要があることが多いです。
ここではMatplotlibを使ってデータをグラフで可視化する時の色々なメソッドについて見てきました。
複数のグラフ表示や、色やマーカーなどのオプション、タイトルの設定、凡例の表示などグラフに必要な情報を加える方法を扱いました。
グラフ表示にはPythonの統計プロットライブラリseabornを使用して作成されることが多いので、これはまた別の機会で触れていきます。