質問

変数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の値を示すカラーバーがありたいです。私はギャラリーでそのようなものを見つけることができず、私の試みはすべてカラーバーに対処しました。どうやら、ColorBarを追加しようとする前に、プロットのコレクションを作成する必要があります。

これを行う簡単な方法はありますか?ありがとう。

編集(明確化):

私はこのようなことをしたかった:

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

xsys xおよびy座標のリストのリストと zs 各ラインを色付けするさまざまな条件のリストです。しかし、それは少し極むように感じます...私はこれを行うためのよりきちんとした方法があると思いました。私はの柔軟性が好きです plt.plot() 関数。

役に立ちましたか?

解決

(私はこれが古い質問であることを知っていますが...)カラーバーは matplotlib.cm.ScalarMappable, plt.plot したがって、スカラーマップではないラインを生成するため、カラーバーを作成するために、スカラーをマッピング可能にする必要があります。

Ok。したがって、aのコンストラクター ScalarMappable を取る cmap そしてa norm 実例。 (Normsはデータを0-1の範囲にスケールし、すでに扱っているCMAPSで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)

それが誰かを助けることを願っています。

編集: :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)

編集: :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)

編集: :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)

他のヒント

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()を呼び出すことができるため、複数のプロットを作成する場合はそれほど無駄ではありません。

enter image description here

これは、によって与えられた一番の答えに触発されたわずかに単純な例です ボリスフック (素晴らしいアイデアをありがとう!):

1. 離散カラーバー

colormapが生成するため、離散カラーバーはより複雑です mpl.cm.get_cmap() として必要なマップ可能な画像ではありません colorbar() 口論。以下に示すように、生成する必要があるDummieマッピングは次のとおりです。

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();

これにより、個別のカラーバーでプロットが生成されます。enter image description here


2. 連続カラーバー

連続カラーバーはあまり関与していません 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();

これにより、連続カラーバーでプロットが生成されます。enter image description here

サイドノート この例では、私は個人的に理由がわかりません cmap.set_array([]) 必要です(それ以外の場合はエラーメッセージが表示されます)。誰かがボンネットの下で原則を理解している場合は、コメントしてください:)

ここで他の答えがあるように、ダミープロットを使用してみてください。これは本当に良いスタイルではありません。

離散カラーバー

離散カラーバーは、異なる正規化だけで、連続カラーバーが作成されるのと同じ方法で生成されます。この場合a 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()

enter image description here

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top