今回は、簡単なグラフを描きます。この際に必要なパッケージがnumpyです。
コードを読むと分かりますが、matplotlibのほとんどのモジュールにおいて、numpyパッケージがimportされています。このように、matplotlibとnumpyには密接な関係があります。
以降のプログラムリスト中では、次の3つのimport文とplt.show()は適宜、省略しますので、注意してください。なお、plt.show()をplf.savefig(...)に変更すれば、スクリーンに出力する代わりに画像ファイルが作成されます。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
(ここだけをリストに表示)
plt.show() または plt.savefig(出力ファイル名)
逆引きメモ
- フレーム編
- グラフの描き方
2-1. 関数のグラフを書きたい
例えば、次の減衰振動関数を描いてみます。
リスト2-1で描いたのが、図2-1の左図です。numpyのlinspaceは、指定した実数範囲を等間隔に出力するメソッドです。戻り値はndarrayです。
ndarrayは、numpyが定義する配列オブジェクトです。ndarrayには、numpyの様々な工夫が詰まっています。例えば、第5行を見てください。yは関数値を格納したndarrayです。本来ならば、forループなどを使って配列yを計算しなければならないのですが、この1行だけで記述出来ます。numpyを一度使うとやめられなくなる理由の一つです。
x座標とy座標のndarray配列を、Axesクラスのplotメソッドに送るだけでグラフが描けてしまいます。
04 x = np.linspace(0.0, 5.0, 200)
05 y = np.exp(-x) * np.cos(10.0 * x)
06
07 fig, ax = plt.subplots()
08 ax.plot(x, y)
図2-1の左右のグラフは、データ点の細かさの違いです。np.linspaceの第3引数は、作成する配列のサイズです(データ点の数)。これを省略すると、データ点は50個に設定されますので、右図のように折れ線に見えてしまいます。関数の変化の激しさによって、適当な配列サイズを選択してください。
2-2. グラフの軸の範囲を変更したい
リスト2-1では、グラフの範囲(論理範囲)は、matplotlibが自動的に決めてくれます。これは便利なことの一つではありますが、目的によっては自分で決めたいときもあります。
例えば、リスト2-1ではX座標は[0, 5]の範囲ですので、X軸もちょうど[0, 5]で描画したいとします。そのときは、リスト12のように、Axesクラスのset_xlimメソッドで指定します。もし、左辺値をおまかせにして、右辺値を指定したい場合は、第1引数をNoneとすればよろしい。同様に、左辺値だけを指定したい場合は、第2引数をNoneにします(第2引数を省略しても可)。
# (リスト2-1の変更部分)
07 fig, ax = plt.subplots()
08 ax.set_xlim(0.0, 5.0)
09 ax.plot(x, y)
図2-2に描画結果を示します(目盛を枠の内側に描く。リスト15参照)。指定されていないY軸は自動的に決まります。
Y軸の範囲を変更する場合には、X軸の場合と同様。set_ylimメソッドを使います。
# (リスト2-1の変更部分)
07 fig, ax = plt.subplots()
08 ax.set_ylim(-1.0, 1.2)
09 ax.plot(x, y)
X軸とY軸の両方とも範囲を指定する場合には、set_xlimとset_ylimを両方使うより、ax.axisを使う方が便利かも知れません。
# (リスト2-1の変更部分)
07 fig, ax = plt.subplots()
08 ax.axis([0.0, 5.0, -1.0, 1.2])
09 ax.plot(x, y)
2-4. 軸の範囲をおまかせにしたときの値を知りたい
軸の描画範囲をシステムに任せたとき、後でその値を知りたいときがあります(例えば、テキストなどをグラフの中に上書きしたいときなど)。そのときは、ax.get_xlimやax.get_ylimの戻り値を使います。これらのメソッドの戻り値は、両側の値を格納したタプルです。
リスト2-5で、ax.plotを実行したあとに、ax.get_ylimを実行していることに注意してください。描画する際に初めて軸の範囲が決まるためです。
# (リスト2-1の変更部分)
07 fig, ax = plt.subplots()
08 ax.plot(x, y)
09 y1, y2 = ax.get_ylim()
10 print(y1, y2)
2-5. 目盛をグラフ枠の内側に付けたい
図2-1をよく見てもらうと、目盛が枠の外側についていることが分かります。筆者は目盛を枠の内側に付ける習慣のため、これでは困ります。この場合は、ax.tic_paramsで目盛の付け方を指定します。実行結果は、上に示した図2-2です。
tic_paramsでは、direction以外にも様々なパラメータを設定できます(公式サイトへのリンク参照)。
# (リスト2-1の変更部分)
07 fig, ax = plt.subplots()
08 ax.set_xlim(0.0, 5.0)
09 ax.tic_params(direction='in')
10 ax.plot(x, y)
2-6. 複数の関数を描きたい
簡単です。リスト2-7は、3種類の関数を描いたものです。Y座標を格納する配列を3種類用意して(X座標は共有します)、ax.plotを関数の数だけ実行します。グラフの色は自動的に決まります。
04 x = np.linspace(0.0, 5.0, 200)
05 y1 = np.exp(-x) * np.cos(9.95 * x)
06 y2 = np.exp(-x) * np.cos(1.73 * x)
07 y3 = np.exp(-x) * (1 - x)
08
09 fig, ax = plt.subplots()
10
11 ax.set_xlim(0.0, 5.0)
12 ax.plot(x, y1)
13 ax.plot(x, y2)
14 ax.plot(x, y3)
結果を図2-3に示します(リスト2-7に加えて、凡例も追加しています。リスト2-8参照)。
2-7. 凡例を付けたい
リスト2-7にリスト2-8を付け加えます。ax.legendをコールするだけで凡例を付加できます。の第1引数は、各プロットに対応したラベルのリストです。線の色やスタイルを、自動的にラベルに割り付けてくれます。
# (リスト2-7に追加)
15 ax.legend(['ω=10', 'ω=3', 'ω=1'])
2-8. プロットの色はどう決まっているのか?
mpl.rcParams['axes.prop_cycle']で定義されています。図2ー4のように、10色を循環してプロットします。
参考のために、図2-4を描いたプログラムをリスト2-9に示します。axes.prop_cycleという名前のパラメータは、Cyclerという独特のクラスを使っています。そのため、リストに加工してから、legendに渡しています。
05 fig, ax = plt.subplots()
06 x = np.linspace(-1.0, 1.0, 2)
07 cc = mpl.rcParams['axes.prop_cycle']
08
09 ryy = [np.sin(np.pi * x) + 1 - (c + 1)/5.0 for c in range(10)]
10 ax.plot(x, np.transpose(ryy))
11 ax.legend(cc.by_key().__getitem__('color'))
2-9. マーカを使ってプロットしたい
観測データのように特定の座標点に意味がある場合、曲線ではなくマーカでプロットする必要があります(図5)。このときには、リスト2-10の10行目のように、plotの第3引数にマーカの種類を表わす記号を与えます。
なお、リスト2-10では、キーワード引数のcolorとmarkersizeを使って色とサイズを指定しています(後述)。
05 fig, ax = plt.subplots()
06
07 d = np.loadtxt('list2-10.dat')
08 x = d[:,0]
09 y = d[:,1]
10 ax.plot(x, y, 'o', color='r', markersize=8)
2-10. マーカにはどんな種類があるのか?
マーカの種類を表わす記号は、matplotlib.markersで定義されています。
参考のために、図2-6を描いたプログラムをリスト2-11に示します。3行目でimportしているのは、リスト2-9で登場したCyclerクラスです。
03 from cycler import cycler
04
05 fig, ax = plt.subplots()
06
07 x = np.linspace(-1.0, 1.0, 40)
08 cc = cycler(marker=list('.ov^<>8s+x'))
09
10 ryy = [np.sin(np.pi * x) + 1 - (c + 1)/5.0 for c in range(10)]
11 ax.set_prop_cycle(cc + plt.rcParams['axes.prop_cycle'])
12 ax.plot(x, np.transpose(ryy), linestyle='None')
13
14 ax.legend(cc.by_key().__getitem__('marker'))
2-11. 線やマーカの色を指定するには?
ax.plotに対して、colorキーワード変数を指定すると、線やマーカの色を指定できます。色は、matplotlib.colorsモジュールで定義されています。
色を表現するにはいくつかの方法があります。そのうち、よく使うものを表2-1に示します。
表2-1 色の表現方法
方法 | 例 | 備考 |
---|---|---|
RGBを表す16進表現 | color='#4e0550' | RGBA表現も可 |
RGBを表す実数のタプル | color=(0.3, 0.8, 0.4) | 4要素にしてRGBA表現も可 |
昔風の1文字表現 | color='r' | 'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w' |
CSS4で定義された名前 | color='darkorchid' | CSS4の色の名前 |
XKCDサイトで定義された名前 | color='xkcd:vivid blue' | XKCDの色の名前 |
図2-7を描いたプログラムをリスト2-12に示します。
04 fig, ax = qt.subplots()
05
06 names = ('#4e0550', (0.3, 0.8, 0.4), 'r', 'darkorchid', 'xkcd:vivid blue')
07
08 x = np.linspace(-1.0, 1.0, 2)
09 for i in range(len(names)):
10 ax.plot(x, x + 0.2 * (4 - i), color=names[i])
11
12 ax.legend(names)
2-12. マーカのサイズを指定するには?
ax.plotに対して、markersizeキーワード変数(短縮形msも使える)を指定すると、マーカのサイズを指定できます。サイズの単位はポイントです。
03 from cycler import cycler
04
05 fig, ax = plt.subplots()
06
07 sizes = (2, 4, 6, 8, 10, 12)
08 num_sizes = len(sizes)
09
10 x = np.linspace(-1.0, 1.0, 10)
11 cc = cycler(markersize=sizes)
12
13 ryy = [x + 1 - (c + 1)/5.0 for c in range(num_sizes)]
14 ax.set_prop_cycle(cc)
15 ax.plot(x, np.transpose(ryy), 'o', color='b')
16
17 ax.legend(cc.by_key().__getitem__('markersize'))
2-13. ポイントとは何?
ポイント(pt)は長さの単位で、72pt=1インチです。従って、ピクセル(px)との関係はDPIによって変わります。matplotlibでは、figure.dpi=100がデフォルトなので、デフォルトのままでは1px=0.72ptです。figure.dpiを変更すると、ピクセルとポイントの関係は変わります。
(pt値) = 72 / (dpi値) * (px値)
の関係があります。
2-14. plotのキーワード変数にはどんなものがあるの?
詳細は、matplotlibのドキュメント(ax.plot)を見てください。よく使うものを表2-2に示します。
表2-2 ax.plot()のキーワード引数
キーワード | 意味 | 備考 |
---|---|---|
color | 描画色 | 2-11を参照 |
marker | マーカの種類 | 2ー10参照。markerキーワードでマーカを指定した場合、線とマーカが同時に出力される |
markersize | マーカのサイズ | 実数。ポイント単位 |
linestyle | 線の種類 | 線の表現参照。'None'を設定すると線を描かない |
linewidth | 線の太さ | 実数。ポイント単位 |