「matplotlibはpythonの可視化ライブラリ:作成可能なプロットの種類を具体例で解説」という記事では,pythonのグラフ作成ライブラリの中でも圧倒的に知名度・使用実績の高いmatplotlibについて,どのようなグラフが作成可能かを具体例を通して解説しました.
今回はmatplotlibのグラフの見た目をどのように調節していくかについて,折れ線グラフを例にして解説していきます.
はじめに:matplotlibの初期設定はイケてない
matplotlibはpublication qualityのグラフが作成できるという売り込みですが,実際に使ってみると初期設定では結構やぼったいグラフを出してきます.
pythonを使うようになって以来,私は以前ならExcelで作っていたようなプレゼンテーションや論文用のグラフを,徐々にmatplotlibで作るようになってきました.毎回同じような設定を検索しては忘れるの繰り返しなので,今回の記事では私がよく使う基本的な設定をまとめてみたいと思います.
もちろん初期設定を綺麗にしたうえで統計分析の助けとなるような手法を盛り込んだseabornなどのライブラリも存在しますが,ここではmatplotlibの設定を手動で変えていくことで何ができるのかを理解していきます.ほとんど全てのパーツが調整可能なので,一旦理解してしまえば思いのままにグラフを描けると思います.
初期設定のグラフ
今回は1次の化学反応を30分毎に360分間サンプリングした架空のデータ(x_a, y_a)と,理論値(x, y)を同じグラフ上にプロットしたものを用います.
下のグラフがmatploblibの初期設定通りにプロットしたものです.見てわかるようにこのまま外に出すのは恥ずかしい質ですが,これを題材に徐々にpublication qualityに仕上げていきたいと思います.
import numpy as np import matplotlib.pyplot as plt np.random.seed(1234) x = np.linspace(0, 360, 1000) x_a = np.linspace(0, 360, 12) y = 100*(1 - np.exp(-0.01*x)) y_a = 100*(1 - np.exp(-0.01*x_a)) + np.random.randn(12) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x,y) ax.plot(x_a, y_a, 'o')
カスタマイズ後のグラフ
このエントリーでは色々と設定を変更していくことで,上のグラフを以下のようなものにしていきます.
この品質で外に出して恥ずかしくないかどうかはみなさんの判断次第ですが,初期設定と比べると大分ましになっていることには同意して頂けたらと思います.
それではこれからどこをカスタマイズしていったかを具体的に見ていきましょう.
カスタマイズ方法
カスタマイズの方法としては
- データのプロット方法(マーカーや線の種類)
- 各軸・目盛りやグリッド
- 凡例やタイトル
にわかれます.それぞれ見ていきましょう.
データのプロット方法の設定
ax.plot(x,y, 'k-', lw=1.5, alpha=0.6, label='theory') ax.plot(x_a, y_a, 'o', color='none', markersize=10, markeredgewidth=3, markeredgecolor='blue', alpha=0.8, label='experiment'
まずはデータのプロット方法を変更してきます.データのプロット方法は大きく「線」と「マーカー」に分けられます.それぞれについて説明していきます.
線の設定(太さ・色・透過度)
個々のデータを結ぶ線には,
- 線の種類
- 線の太さ
- 線の色
- 線の透過度
の4つの項目で設定が可能です.
設定項目 | オプション |
---|---|
線の種類 | linestyle (ls) |
線の太さ | linewidth (lw) |
線の色 | color (c) |
透過度 | alpha |
理論値の方を黒の実線(‘k-‘)とし,線の太さを1.5lw=1.5にします.さらに透過度を少し上げてalpha=0.6)て,凡例用にラベルをつけましたlabel=’theory’.
黒の実線の指定は,色・マーカー・線の種類を同時に指定可能な簡易型フォーマット形式を利用しています.
マーカーの設定(種類・色・透過度)
matplotlibで使われているマーカーは実は下の図のようにいくつかのパーツによって構成されています.
もちろん個々のパーツについて細かい設定が可能です.例えば内側の色をなくせば白抜きのマーカーが作成できます.
設定項目 | オプション |
---|---|
マーカー全体の大きさ | markersize |
マーカー外枠の色 | markeredgecolor |
マーカー外枠の幅 | markeredgewidth |
マーカーの内側の色 | color |
マーカーの透過度 | alpha |
今回はマーカーの種類は丸のまま‘o’としますが,色を青に変え,さらに塗りつぶしではなく白抜きの丸へと変更しました.さらに凡例用にラベルをつけましたlabel=’experiment’.
各軸の設定(軸の位置とラベル)
### x-axis setting ax.set_xlim(0,370) ax.set_xticks([60*x for x in np.arange(7)]) ax.set_xticklabels([x for x in np.arange(7)], fontsize=14, color='black') ax.set_xlabel('time (h)', fontsize=14, color='black') ### y-axis setting ax.set_ylim(0,105) ax.set_yticks([0, 25, 50, 75, 100]) ax.set_yticklabels([0, 25, 50, 75, 100], fontsize=14, color='black') ax.set_ylabel('Conversion (%)', fontsize=14, color='black')
x軸の範囲は0分から360分まであれば十分ですが少し余裕を持たせて370までset_xlimとしています.
さらに目盛りの区切りset_xticksは60分ごとのほうがわかりやすいのでそのように設定しています.この設定のままですとティックが目盛りのラベルにも使われますが,ラベルは単位を分ではなく時間にしたかったので,各目盛りに割り振るラベルset_xticklabelsを別個に設定しました.ついでにフォントサイズと色も設定しています.
このように軸の目盛りとラベルを別々に設定することで,最終的なグラフの見た目を柔軟に変更可能になるためとても重要です.
最後にx軸のラベルset_xlabelをフォントサイズと色と共に設定しています.
y軸に関しても同様で,軸の範囲を余裕を持たせて105までにしています.
枠・軸目盛りの設定
### spine setting ax.spines['top'].set_linewidth(0) ax.spines['right'].set_linewidth(0) ax.spines['left'].set_linewidth(2) ax.spines['left'].set_color('gray') ax.spines['bottom'].set_linewidth(2) ax.spines['bottom'].set_color('gray') ### tick setting ax.tick_params(direction='in', length=6, width=2, color='gray')
続いてグラフが描かれる枠と軸目盛りの設定です.枠は上‘top’・下‘bottom’・左‘left’・右‘right’とそれぞれについて設定可能で,今回は左と下だけ残しています.線の太さはset_linewidth()で,線の色はset_color()で設定します.
軸の目盛りは先ほどの設定で各軸について設定した場所に,ヒゲをどのようにつけるかが設定できます.今回は内向きに長さ6幅2で灰色のヒゲをつけています.
グリッドの設定
ax.yaxis.grid(linestyle='--', lw=1, alpha=0.4, color='lightgray') ax.plot(np.linspace(8,370,1000), np.ones(1000)*100, 'w-', lw=2) ax.set_axisbelow(True)
グリッドとは各軸の目盛りを通るグラフ内の区切りになります.有効に使うことができれば聴衆がグラフを理解する大きな助けになりますので,matplotlibでも色々と設定することができます.xy軸全部,x軸に沿った垂直のものだけ,y軸に沿った水平なものだけと細かく設定可能です.
今回の例ではy軸に沿ったものを,太さ1で色が灰色の破線を透過度0.4で描いています(set_yaxis.grid(linestyle=’–‘, lw=1, alpha=0.4, color=’lightgray’)).
このままではy軸が100の部分にもグリッドが描かれてしまってやや不自然になるので,そこに色が白の水平線を無理矢理被せることで隠しています.もう少しうまい方法がありそうです.
最後にグラフのグリッドがプロットの下に隠れるように設定しました.
グラフタイトルの設定(上付き・下付き文字)
ax.set_title(r'$\mathrm{\mathbf{Progress\ of\ 1^{st}\ order\ reaction}}$', fontsize=18, alpha=0.7)
matplotlibのテキストで文字の体裁を整えたい場合はLaTeX記法を使うことになります.LaTeX記法をうまく使うことで「太字」,「斜体」,「上付き文字」,「下付き文字」,の他もちろんきれいな数式も表現可能です.
今回はグラフタイトルは太字にした上で1stを上付きにしたかったのでLaTeX記法を用いています.注意点としては,LaTex表記の中では標準では斜体になってしまうため全ての文章をローマン体にしています(\mathrm{}で囲む).
さらに太字にするためにボールドフォント設定をしています(\mathbf{}で囲む).この囲みの中ではスペースは無視されてしまうので毎回バックスラッシュをつけています.肝心の上付きは ^{} によって実現しています.
凡例の設定(位置とフレーム)
ax.legend(loc=4, frameon=True, facecolor='white', edgecolor='none', fontsize=14, markerscale=0.7)
凡例もマーカーと同様に様々な設定が可能です.今回は以下の6点について設定しています.
設定項目 | コード |
---|---|
グラフ中と比べたマーカーの相対サイズ | markerscale |
ラベルのフォントサイズ | fontsize |
フレーム中に凡例を入れる | frameon |
フレームの色 | facecolor |
フレームの枠の色 | edgecolor |
凡例の位置 | loc |
終わりに
今回はseabornなどのライブラリを使うのではなく,matplotlibの設定を1つ1つ変えていきました.これはmatplotlibは簡単にプロットを作るれるが,いざ実際に自分でカスタマイズして思い通りのグラフを描こうとすると結構時間がかかるということを実感して頂きたかったからでした.
今回学んだようにmatplotlibでは本当に細かく設定を変えることができます.最初はとっつきにくいですが,一回手がなじむとどこをどのようにカスタマイズすればよいかがわかり思い通りのグラフが書けるようになると思います.
今回は1つのグラフを描くことしか扱いませんでしたが,matplotlibではsubplotを駆使することで1つのキャンバスに複数のグラフを並べることも可能です.次回はmatplotlibのオブジェクト指向について学びながら,複数のグラフをグリッド表示していく方法について学んでいきたいと思います.
コメント
中抜きマーカーの指定方法を探しておりました。
わかりやすく説明していただき、ありがとうございました。
早速活用いたします。
黒川様
ご丁寧なコメントありがとうございます。
今後ともよろしくお願いいたします。