matplotlib で色を変えて、legend をたくさん表示したい
使い所
matplotlib を使って、グラフをたくさん表示したいが、デフォルトの色の設定だと有限個の色しか出せない。これを簡単に解決する方法を紹介したい。そういう場合、legend もたくさん表示したいことが多いと思うが、昔の matplotlib では難しかったが、今はとても簡単にできるので、おまけでその方法も紹介する。
サンプル
コードを見れば分かる方は、google colab で作成した例を参照ください。
概要
例として、y = arctan((n+1)x) と y = x^n の2つの関数について、n を20個ずらしたグラフを重ね書きする例を紹介する。
colormap のポイント
usercmap = plt.get_cmap('jet')
cNorm = colors.Normalize(vmin=0, vmax=num)
scalarMap = cm.ScalarMappable(norm=cNorm, cmap=usercmap)
これで、colormap で jet を選択し、0 から num(20) 個のデータ数で色分けを宣言して、cm.ScalarMappableで scalarMapを生成する。for loop の中で、
c = scalarMap.to_rgba(i) として、色を選択する。
legendをたくさん表示するためのポイント
plt.legend(bbox_to_anchor=(0., 1.01, 1., 0.01), loc='lower left',ncol=10, mode="expand", borderaxespad=0.,fontsize=8)
bbox_to_anchor=(X座標, Y座標, Xサイズ, Yサイズ)で置き場所を指定し、ncolで折りたたむコラム数を調節する。
サンプルコード
#!/usr/bin/env python
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'serif'
import optparse
from matplotlib.colors import LogNorm
import matplotlib.colors as colors
### plot 1D plot : shifted
F = plt.figure(figsize=(12,8.))
plt.subplots_adjust(wspace=0.3, hspace=0.6)
ax = plt.subplot(2,1,1)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.figtext(0.02,0.02,"[matplotlib legend test]")
plt.xscale('linear')
plt.yscale('linear')
plt.grid(linestyle='dotted',alpha=0.5)
plt.xlabel(r'x-axis (a.u.)')
plt.ylabel(r'y-axis')
x = np.arange(-1,1,0.1)
num=20
y = []
for j in range(num):
y.append(np.arctan(x*(j+1)))
usercmap = plt.get_cmap('jet')
cNorm = colors.Normalize(vmin=0, vmax=num)
scalarMap = cm.ScalarMappable(norm=cNorm, cmap=usercmap)
for i,oney in enumerate(y):
c = scalarMap.to_rgba(i)
plt.errorbar(x, oney, fmt="o-", color = c, alpha = 0.8, linewidth = 1, label=str(i))
plt.legend(bbox_to_anchor=(0., 1.01, 1., 0.01), loc='lower left',ncol=10, mode="expand", borderaxespad=0.,fontsize=8)
ax = plt.subplot(2,1,2)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.xscale('linear')
plt.yscale('linear')
plt.grid(linestyle='dotted',alpha=0.5)
plt.xlabel(r'x-axis (a.u.)')
plt.ylabel(r'y-axis')
x = np.arange(-1,1,0.1)
num=20
y = []
for j in range(num):
y.append(np.power(x,j+1))
usercmap = plt.get_cmap('jet')
cNorm = colors.Normalize(vmin=0, vmax=num)
scalarMap = cm.ScalarMappable(norm=cNorm, cmap=usercmap)
for i,oney in enumerate(y):
c = scalarMap.to_rgba(i)
plt.errorbar(x, oney, fmt="o-", color = c, alpha = 0.8, linewidth = 1, label=str(i))
plt.legend(bbox_to_anchor=(-0.1, 1.0, 1.2, 0.01), loc='lower left',ncol=10, mode="expand", borderaxespad=0.,fontsize=8)
plt.savefig("qiita_legend_sample.png")
plt.show()
生成される図はこちら。
注意事項
このように legend を横に広げてグラフの外に表示するのは簡単になったが、expandというオプションは横方向にのみ対応していて、縦には対応してない(2019.1.8現在)。時間が解決してくれると思うが。