変数zのさまざまな値について、2つの変数(x、y)の一連の折れ線グラフがあります。通常、次のような凡例を使用してラインプロットを追加します。
_import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
# suppose mydata is a list of tuples containing (xs, ys, z)
# where xs and ys are lists of x's and y's and z is a number.
legns = []
for(xs,ys,z) in mydata:
pl = ax.plot(xs,ys,color = (z,0,0))
legns.append("z = %f"%(z))
ax.legends(legns)
plt.show()
_
しかし、グラフが多すぎるため、凡例でグラフをカバーします。むしろ、色に対応するzの値を示すカラーバーが必要です。私はギャラリーでそのようなものを見つけることができず、私のすべての試みはカラーバーを処理しませんでした。カラーバーを追加する前に、プロットのコレクションを作成する必要があるようです。
これを行う簡単な方法はありますか?ありがとう。
編集(説明):
私はこのようなことをしたかった:
_import matplotlib.pyplot as plt
import matplotlib.cm as cm
fig = plt.figure()
ax = fig.add_subplot(111)
mycmap = cm.hot
# suppose mydata is a list of tuples containing (xs, ys, z)
# where xs and ys are lists of x's and y's and z is a number between 0 and 1
plots = []
for(xs,ys,z) in mydata:
pl = ax.plot(xs,ys,color = mycmap(z))
plots.append(pl)
fig.colorbar(plots)
plt.show()
_
しかし、これはMatplotlibのリファレンスでは機能しません。これは、プロットのリストが「マッピング可能」ではないためです。
LineCollection
を使用して代替プロット関数を作成しました。
_def myplot(ax,xs,ys,zs, cmap):
plot = lc([Zip(x,y) for (x,y) in Zip(xs,ys)], cmap = cmap)
plot.set_array(array(zs))
x0,x1 = amin(xs),amax(xs)
y0,y1 = amin(ys),amax(ys)
ax.add_collection(plot)
ax.set_xlim(x0,x1)
ax.set_ylim(y0,y1)
return plot
_
xs
およびys
はxおよびy座標のリストのリストであり、zs
は各行を色付けするためのさまざまな条件のリストです。それはちょっとした手品のように感じます...私はこれを行うにはもっときちんとした方法があると思いました。 plt.plot()
関数の柔軟性が気に入っています。
まだplt.plot()を使用しながらそれを行う1つの方法があります。基本的に、使い捨てのプロットを作成し、そこからカラーバーを取得します。
import matplotlib as mpl
import matplotlib.pyplot as plt
min, max = (-40, 30)
step = 10
# Setting up a colormap that's a simple transtion
mymap = mpl.colors.LinearSegmentedColormap.from_list('mycolors',['blue','red'])
# Using contourf to provide my colorbar info, then clearing the figure
Z = [[0,0],[0,0]]
levels = range(min,max+step,step)
CS3 = plt.contourf(Z, levels, cmap=mymap)
plt.clf()
# Plotting what I actually want
X=[[1,2],[1,2],[1,2],[1,2]]
Y=[[1,2],[1,3],[1,4],[1,5]]
Z=[-40,-20,0,30]
for x,y,z in Zip(X,Y,Z):
# setting rgb color based on z normalized to my range
r = (float(z)-min)/(max-min)
g = 0
b = 1-r
plt.plot(x,y,color=(r,g,b))
plt.colorbar(CS3) # using the colorbar info I got from contourf
plt.show()
少し無駄ですが、便利です。また、複数のプロットを作成する場合も、plt.colorbar()の情報を再生成せずに呼び出すことができるため、あまり無駄ではありません。
(これは古い質問ですが...)カラーバーにはmatplotlib.cm.ScalarMappable
、plt.plot
が必要です。スカラーマッピングできない行を生成するため、カラーバーを作成するには、スカラーをマップ可能にします。
OK。したがって、ScalarMappable
のコンストラクターは、cmap
とnorm
のインスタンスを取ります。 (データを0〜1の範囲にスケーリングし、すでに作業したcmapを0〜1の範囲の数で取り、色を返します)。あなたの場合:
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(min=0, max=1))
plt.colorbar(sm)
データはすでに0〜1の範囲にあるため、sm
の作成を次のように簡略化できます。
sm = plt.cm.ScalarMappable(cmap=my_cmap)
それが誰かを助けることを願っています。
[〜#〜] edit [〜#〜]:matplotlib v1.2以降では、コードは次のようになります。
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(vmin=0, vmax=1))
# fake up the array of the scalar mappable. Urgh...
sm._A = []
plt.colorbar(sm)
[〜#〜] edit [〜#〜]:matplotlib v1.3以降では、コードは次のようになります。
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))
# fake up the array of the scalar mappable. Urgh...
sm._A = []
plt.colorbar(sm)
[〜#〜] edit [〜#〜]:matplotlib v3.1以降の場合、次のように簡略化されます。
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))
plt.colorbar(sm)
Boris および Hooked (素晴らしいアイデアをありがとう!)
mpl.cm.get_cmap()
によって生成されるカラーマップは、colorbar()
引数として必要なマップ可能な画像ではないため、離散カラーバーがより複雑になります。以下に示すように、ダミーのマッピング可能ファイルを生成する必要があります。
_import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)
cmap = mpl.cm.get_cmap('jet', n_lines)
fig, ax = plt.subplots(dpi=100)
# Make dummie mappable
dummie_cax = ax.scatter(c, c, c=c, cmap=cmap)
# Clear axis
ax.cla()
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap(i))
fig.colorbar(dummie_cax, ticks=c)
plt.show();
_
mpl.cm.ScalarMappable()
によりcolorbar()
の「イメージ」を取得できるため、連続カラーバーの関与が少なくなります。
_import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)
norm = mpl.colors.Normalize(vmin=c.min(), vmax=c.max())
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.jet)
cmap.set_array([])
fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap.to_rgba(i + 1))
fig.colorbar(cmap, ticks=c)
plt.show();
_
これにより、連続したカラーバーを持つプロットが生成されます。
[特記事項]この例では、cmap.set_array([])
が必要な理由を個人的に知りません(そうでなければエラーメッセージが表示されます) )。誰かが内部の原則を理解している場合は、コメントしてください:)
ここでの他の答えはダミープロットを使用しようとしますが、これは実際には良いスタイルではありません、ここに一般的なコードがあります
個別のカラーバーは、連続したカラーバーが作成されるのと同じ方法で、異なる正規化で作成されます。この場合、BoundaryNorm
を使用する必要があります。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1., n_lines + 1)
cmap = plt.get_cmap("jet", len(c))
norm = matplotlib.colors.BoundaryNorm(np.arange(len(c)+1)+0.5,len(c))
sm = plt.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([]) # this line may be ommitted for matplotlib >= 3.1
fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap(i))
fig.colorbar(sm, ticks=c)
plt.show()