Pythonのmatplotlibの自分用の備忘録 (2017/03/08作成) をQiitaに持ってきました。一応アップする前に見直しましたが、情報が古いままの箇所もあると思いますので注意して下さい。また、全機能を網羅するつもりはなく、個人的にハマった箇所を中心に書いただけです。
参考ページ
基本の流れ
- 必要なパッケージを入れる
import matplotlib.pyplot as plt import seaborn as sns
- figとaxの生成 (複数の図をまとめて1つの図にする場合があるので、全体をfig、個々の図をaxと呼んで区別している)
上は以下と等価
fig, ax = plt.subplots()
fig = plt.figure() ax = fig.add_subplot()
- メインの図の描画
ax.plot(...)
- 細かい調整
ax.set_xlabel('x')
- 表示
fig.show()
- ファイルへ出力
fig.savefig('tmp.png')
図の種類
matplotlibの図
- 折れ線グラフ
ax.plot(...)
- 散布図
ax.scatter(...)
- 棒グラフ
ax.bar(...)
- 箱ひげ図
ax.boxplot(...)
- ヒストグラム
ax.hist(...)
- ヒートマップ
または
ax.matshow(...)
ax.imshow(...)
- 円グラフ
ax.pie(...)
seabornの図
- 折れ線グラフ
sns.pointplot(...)
- 散布図
sns.scatterplot(...)
- 棒グラフ (連続変数の場合)
sns.barplot(...)
- 棒グラフ (カテゴリカル変数の場合)
sns.countplot(...)
- 箱ひげ図
sns.boxplot(...)
- 蜂群図
sns.swarmplot(...)
- バイオリン図
sns.violinplot(...)
- ヒストグラムとカーネル密度推定 (古いバージョン)
sns.distplot(...)
- ヒストグラムとカーネル密度推定 (新しいバージョン)
sns.displot(...) sns.histplot(...) sns.kdeplot(...)
- ヒートマップ
sns.heatmap(...)
- ヒートマップ (樹形図付き)
sns.clustermap(...)
全体的なスタイル
- 全体的な文字サイズと線の太さを変える (paper < notebook (default) < talk < poster)
文字サイズを調整したい場合
sns.set_context('talk')
一時的に適用したい場合 (withの内側のみ)sns.set_context('talk', font_scale=0.8)
with sns.plotting_context('talk'): # 略
- rcParamsを個別に変更する
または
with plt.rc_context({'lines.linewidth':5}):
with sns.plotting_context(..., rc={'lines.linewidth':5}):
- 描画スタイルを変える (darkgrid, whitegrid, dark, white, ticks)
with sns.axes_style('whitegrid'):
- 使う色の種類を変える
with sns.color_palette('colorblind'):
タイトル
- タイトルを付ける
ax.set_title('title')
- タイトルの文字を大きくする
ax.set_title(..., fontsize=20)
- タイトルと図の間を広げる
ax.set_title(..., pad=10)
- 複数のaxがある場合に全体タイトルを付ける
tight_layoutを使う場合
fig.suptitle('title')
fig.tight_layout(rect=[0,0,1,0.95])
figとax
- figのサイズを指定 (単位はインチ)
pixelで指定したい場合 (dpiは予め適当なfig作ってfig.get_dpi()で調べておく)
fig, ax = plt.subplots(figsize=(8,6))
dpi = 80.0 fig, ax = plt.subplots(figsize=(400/dpi, 300/dpi)) # (中略) fig.savefig('tmp.png', dpi='figure')
- 余白を詰める
または
fig.tight_layout()
fig.subplots_adjust(left=0.05, top=0.95, bottom=0.05, right=0.95)
- ax同士の間を調節する (hはheightで縦方向、wはwidthで横方向)
または
fig.tight_layout(h_pad=0.1, w_pad=0.1)
fig.subplots_adjust(wspace=0.1, hspace=0.1)
- 複数のaxを並べる (サイズが同じ場合)
fig, axes = plt.subplots(nrows=2, ncols=2) ax1 = axes[0,0]
- 複数のaxを並べる (サイズがばらばらの場合、方眼紙を作ってカスタムで配置するイメージ)
fig = plt.figure() gs = fig.add_gridspec(100, 100) ax = fig.add_subplot(gs[:50, :50])
- 複数のaxを一次元配列にする
axes = axes.flatten()
- カスタムサイズのaxを作る (左下を(0,0), 右上を(1,1)として、[left, bottom, width, height] の順)
ax = fig.add_axes([0, 0, 1, 1])
描画範囲
- 描画範囲を指定
ax.set_xlim((0, 100))
- 余白を入れる (データの範囲に対する割合。xlim, ylim指定があると無視される)
ax.margins(0.05)
目盛り
- 目盛りの表示間隔や値を変更
単に間引きたい場合
ax.set_xticks([1,3]) ax.set_xticklabels([10,30])
sns.clustermapで全ての目盛りを表示したい場合xticks = ax.get_xticks() xlabels = ax.get_xticklabels() ax.set_xticks(xticks[::5]) ax.set_xticklabels(xlabels[::5])
sns.clustermap(df, yticklabels=1)
- 目盛りの文字の大きさを変える
ax.tick_params(labelsize=20)
- 目盛りの文字の向きを変える (横書きは0, 縦書きは90, 斜めも可)
ax.set_xticklabels(..., rotation=90)
- 目盛りのラベルを置換
labels = [v.get_text().replace('-',' ') for v in ax.get_xticklabels()] ax.set_xticklabels(labels)
- 目盛りの位置を移動
上は以下と同じ
ax.xaxis.tick_bottom()
ax.tick_params(top=False, bottom=True)
- 目盛り (軸) を0を横切る位置に移動
ax.spines['left'].set_position('zero')
- 軸の先を矢印にする (x_max, y_maxはそれぞれx軸、y軸の最大値)
ax.plot(x_max, 0, marker='>', ms=10, color='k', clip_on=False) ax.plot(0, y_max, marker='^', ms=10, color='k', clip_on=False)
- 目盛りを消す
ax.set_xticks([])
- 目盛りと辺を全部消す
ax.axis('off')
- 目盛りの太さを変える
ax.tick_params(width=3)
- 目盛りの長さを変える
ax.tick_params(length=5)
- 目盛りを外向きにする
ax.tick_params(direction='out')
- 目盛りと文字の間を広げる
ax.tick_params(pad=10)
- 目盛りの表記フォーマットを変更
def fmt(x, pos): return '{:.2e}'.format(x) ax.xaxis.set_major_formatter(plt.FuncFormatter(fmt))
軸の名前
- 軸の名前を付ける
ax.set_xlabel('x')
- 軸の名前の文字の大きさを変える
ax.set_xlabel(..., fontsize=20)
- 軸の名前の位置を移動
ax.yaxis.set_label_position('right')
辺 (枠線)
- 辺を消す
または、以下の方法 (初期設定で上と右を消す、左と下はオプションでTrue指定)
ax.spines['top'].set_visible(False)
sns.despine()
- 辺と目盛りを全部消す (再掲)
ax.axis('off')
- 辺を離して交わらないようにする
または
ax.spines['bottom'].set_position(('outward', 10))
sns.despine(offset=10, trim=True)
- sns.heatmapに枠線を付ける
for spine in ax.spines.values(): spine.set_visible(True) spine.set_linewidth(2)
凡例
- 凡例を表示する (予め各プロットでlabelを指定)
ax.plot(..., label='a') ax.plot(..., label='b') ax.legend()
- 凡例の位置を変える (upper/center/lowerとleft/center/rightの組み合わせ)
ax.legend(loc='upper left')
- 凡例を図の外に移動する
ax.legend(bbox_to_anchor=(1,1), loc='upper left')
- 凡例の枠の太さを調整
leg = ax.legend(...) leg.get_frame().set_linewidth(3)
- 凡例の枠を消す
ax.legend(frameon=False)
- 凡例のマーカーの大きさを調整
ax.legend(markerscale=10)
- 凡例の周囲の余白を調整
ax.legend(borderaxespad=0)
- 凡例のマーカーと文字の間隔を調整
ax.legend(handletextpad=0)
- 凡例の行間を調整
ax.legend(labelspacing=0)
- 凡例を消す (seabornで勝手に出力されてしまう場合など)
ax.legend_.remove()
- 凡例を逆順にする
handles, labels = ax.get_legend_handles_labels() leg = ax.legend(handles[::-1], labels[::-1])
文字や線を追加で書き込む
- 横腺を引く / 縦線を引く
ax.axhline(y=0) ax.axvline(x=0)
- 部分領域を塗りつぶす
ax.axvspan(0, 0.5, alpha=0.5)
- 文字を書く (x座標、y座標、文字)
ax.text(0, 0, 'text', ha='center', va='center')
- 指定座標を左端にするか、中央にするかなどを変える (horizontal alignment, vertical alignment)
ax.text(..., ha='left', va='center')
- 文字の位置を、座標軸の値でなく[0,1]の範囲で指定する
ax.text(..., transform=ax.transAxes)
- 文字に背景色を付ける
t = ax.text(...) t.set_bbox(dict(facecolor='white', alpha=0.5))
- 文字に縁取りを付ける
from matplotlib import patheffects ax.text(..., path_effects=[patheffects.withStroke(linewidth=3, foreground='w')])
- 角が丸い四角形を描く
from matplotlib import patches box = patches.FancyBboxPatch(...) ax.add_patch(box)
- patchesオブジェクトを回転させる (楕円ならオプションで指定可能)
t = mpl.transforms.Affine2D().rotate_deg_around(x, y, theta) + ax.transData box.set_transform(t)
箱ひげ図
- 外れ値を非表示にする
ax.boxplot(..., showfliers=False)
- ひげの先の横棒を消す
ax.boxplot(..., showcaps=False)
- 中央の線の色を変える
ax.boxplot(..., medianprops={'color':'white'})
- 箱の色を変える (colorだと枠線の色も変わるので注意)
ax.boxplot(..., boxprops={'fc':plt.cm.Paired(0)})
ヒートマップ
- 基本
上は以下と等価 (matshowはimshowをorigin='upper', interpolation='nearest', aspect='equal'で呼ぶwrapper関数)
ax.matshow(np.random.randn(200,100), aspect='auto')
ax.imshow(np.random.randn(200,100), aspect='auto', interpolaiton='nearest')
- カラーバーを別のaxに表示
im = ax.matshow(...) cb = fig.colorbar(im, cax=ax2)
- カラーバーの枠の太さを変える
cb.outline.set_linewidth(2)
- カラーバーの枠を消す
cb.outline.set_visible(False)
- sns.heatmapのカラーバーの調節
sns.heatmap(..., ax=ax) cax = ax.collections[0].colorbar.ax cax.tick_params(length=0)
- sns.heatmapでNoneの色を変える
g = sns.heatmap(df, mask=df.isnull()) g.set_facecolor('0.8')
- y軸を逆向きにする
ax.invert_yaxis()
sns.clustermap
- 基本 (予め用意したaxに入れるのでなく、これ自体がfigとaxを作るので注意)
g = sns.clustermap(np.random.randn(200,100))
- figを取得
fig = g.fig
- ヒートマップの部分のaxを取得
ax = g.ax_heatmap
- 樹形図の占める割合を変更
sns.clustermap(..., dendrogram_ratio=(0.1,0.1))