2012-01-19 37 views
53

カラーマップを使用してランタイムにスカラー値を指定してmatplotlibのラインの色を設定するにはどうすればいいですか(たとえばjet)?私はここでいくつかのアプローチを試してみました。私は困惑していると思います。 values[]は、スカラーのストートされた配列です。曲線は1次元配列の集合であり、ラベルはテキスト文字列の配列です。各アレイの長さは同じです。カラーマップを使用してmatplotlibのラインの色を設定する

fig = plt.figure() 
ax = fig.add_subplot(111) 
jet = colors.Colormap('jet') 
cNorm = colors.Normalize(vmin=0, vmax=values[-1]) 
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) 
lines = [] 
for idx in range(len(curves)): 
    line = curves[idx] 
    colorVal = scalarMap.to_rgba(values[idx]) 
    retLine, = ax.plot(line, color=colorVal) 
    #retLine.set_color() 
    lines.append(retLine) 
ax.legend(lines, labels, loc='upper right') 
ax.grid() 
plt.show() 

答えて

66

受け取ったエラーは、jetの定義によるものです。 'jet'という名前の基本クラスColormapを作成していますが、これは 'jet'カラーマップのデフォルト定義を取得することとはまったく異なります。この基本クラスは決して直接作成するべきではなく、サブクラスのみをインスタンス化する必要があります。

あなたの例で見つかったことは、Matplotlibのバグのある動作です。このコードを実行すると、より明確なエラーメッセージが生成されるはずです。

これはあなたの例の更新版です。で結果の

import matplotlib.pyplot as plt 
import matplotlib.colors as colors 
import matplotlib.cm as cmx 
import numpy as np 

# define some random data that emulates your indeded code: 
NCURVES = 10 
np.random.seed(101) 
curves = [np.random.random(20) for i in range(NCURVES)] 
values = range(NCURVES) 

fig = plt.figure() 
ax = fig.add_subplot(111) 
# replace the next line 
#jet = colors.Colormap('jet') 
# with 
jet = cm = plt.get_cmap('jet') 
cNorm = colors.Normalize(vmin=0, vmax=values[-1]) 
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) 
print scalarMap.get_clim() 

lines = [] 
for idx in range(len(curves)): 
    line = curves[idx] 
    colorVal = scalarMap.to_rgba(values[idx]) 
    colorText = (
     'color: (%4.2f,%4.2f,%4.2f)'%(colorVal[0],colorVal[1],colorVal[2]) 
     ) 
    retLine, = ax.plot(line, 
         color=colorVal, 
         label=colorText) 
    lines.append(retLine) 
#added this to get the legend to work 
handles,labels = ax.get_legend_handles_labels() 
ax.legend(handles, labels, loc='upper right') 
ax.grid() 
plt.show() 

ScalarMappableを使用して

enter image description here

は私の関連の答えに提示アプローチの改良である: creating over 20 unique legend colors using matplotlib

35

私はwを含めると有益だろうと思ったhat私はnumplのlinspaceとmatplotlibのcm-typeオブジェクトを組み合わせたより簡単な方法と考えています。上記の解決策は古いバージョン用の可能性があります。私はpython 3.4.3、matplotlib 1.4.3、numpy 1.9.3を使用しています。私の解決策は以下の通りです。

import matplotlib.pyplot as plt 

from matplotlib import cm 
from numpy import linspace 

start = 0.0 
stop = 1.0 
number_of_lines= 1000 
cm_subsection = linspace(start, stop, number_of_lines) 

colors = [ cm.jet(x) for x in cm_subsection ] 

for i, color in enumerate(colors): 
    plt.axhline(i, color=color) 

plt.ylabel('Line Number') 
plt.show() 

この結果、以下のようにcm.jetカラーマップ全体に1000個の固有の色の線ができます。このスクリプトを実行すると、個々の行を拡大することができます。

cm.jet between 0.0 and 1.0 with 1000 graduations

は今、私は単に私のスタートを変更し、0.4と0.6に値を停止し、これは20%のみを使用して、その結果、私は私の1000年ラインの色がちょうど600にライン400との間に緑がかった部分をまたがるたいと言います0.4〜0.6の間のcm.jetカラーマップ。

cm.jet between 0.4 and 0.6 with 1000 graduations

ので、1行のサマリーでは、あなたはmatplotlibのからのRGBA色のリストを作成することができます。したがってセンチカラーマップ:この場合、

colors = [ cm.jet(x) for x in linspace(start, stop, number_of_lines) ] 

私は、一般的に呼び出されたマップという名前のジェットを使用していますが、呼び出すことによって、あなたのmatplotlibのバージョンで利用可能なカラーマップの完全なリストを見つけることができます:行の

>>> from matplotlib import cm 
>>> dir(cm) 
+0

これはあなたの 'stop'が1であるためにのみ有効です。 – Eric

+1

もちろん1が最適です。より広い範囲の色が必要な場合は、 'number_of_lines'を増やすだけです。また、バンドの一部の色だけが必要な場合は、必要に応じて 'stop'を減らして' start'を増やします。 – Parousia

+0

簡単な質問:凡例の代わりにカラーバーをプロットに追加するにはどうすればいいですか? –

7

組み合わせをmatplotlibからのスタイル、マーカー、および定性的な色:

import itertools 
import matplotlib as mpl 
import matplotlib.pyplot as plt 
N = 8*4+10 
l_styles = ['-','--','-.',':'] 
m_styles = ['','.','o','^','*'] 
colormap = mpl.cm.Dark2.colors # Qualitative colormap 
for i,(marker,linestyle,color) in zip(range(N),itertools.product(m_styles,l_styles, colormap)): 
    plt.plot([0,1,2],[0,2*i,2*i], color=color, linestyle=linestyle,marker=marker,label=i) 
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.,ncol=4); 

enter image description here

関連する問題