2012-01-19 15 views
53

Jak ustawić kolor linii w matplotlib przy pomocy wartości skalarnych dostarczonych w czasie wykonywania za pomocą mapy kolorów (np. jet)? Próbowałem tutaj kilku różnych podejść i myślę, że jestem zakłopotany. values[] to starchowa sieć skalarów. krzywe są zbiorem tablic 1-d, a etykiety są tablicą ciągów tekstowych. Każda z macierzy ma tę samą długość.Używanie Colormaps do ustawienia koloru linii w 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() 

Odpowiedz

66

Otrzymany błąd wynika z definicji jet. Tworzysz bazową klasę Colormap o nazwie "jet", ale to bardzo różni się od otrzymania domyślnej definicji mapy kolorów "jet". Ta klasa bazowa nigdy nie powinna być tworzona bezpośrednio, a tylko instancje powinny być tworzone.

To, co znalazłeś na swoim przykładzie, to błędne zachowanie w Matplotlib. Powinien być wyraźniejszy komunikat o błędzie generowany podczas uruchamiania tego kodu.

Jest to zaktualizowana wersja swoim przykładzie:

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

Wynikające w:

enter image description here

Korzystanie z ScalarMappable jest poprawa w stosunku do podejścia przedstawionego w moim powiązanej odpowiedź: creating over 20 unique legend colors using matplotlib

35

Pomyślałem, że korzystne byłoby włączenie w Kapelusz uważam za prostszą metodę wykorzystującą przestrzeń numpy w połączeniu z obiektem typu cmplotlib. Możliwe, że powyższe rozwiązanie dotyczy starszej wersji. Używam python 3.4.3, matplotlib 1.4.3 i numpy 1.9.3., A moje rozwiązanie jest następujące.

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

Daje to 1000 unikatowych kolorowych linii, które obejmują całą CMR cm.jet, jak pokazano poniżej. Jeśli uruchomisz ten skrypt, zobaczysz, że możesz powiększać poszczególne linie.

cm.jet between 0.0 and 1.0 with 1000 graduations

Teraz chcę powiedzieć moi 1000 linia kolory po prostu span zielonkawy część pomiędzy liniami 400 do 600. Po prostu zmienić swój start i stop wartości 0,4 i 0,6, a to skutkuje wykorzystaniem tylko 20% mapa kolorów cm.jet między 0,4 a 0,6.

cm.jet between 0.4 and 0.6 with 1000 graduations

Tak w podsumowaniu jednego wiersza można utworzyć listę kolorów RGBA z pomocą matplotlib.cm colormap odpowiednio:

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

W tym przypadku używam najczęściej wywoływana mapę o nazwie Jet, ale można znaleźć pełną listę colormaps dostępnych w wersji matplotlib powołując:

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

Działa to tylko dlatego, że twój 'stop' to 1 – Eric

+1

Oczywiście 1 to najlepsza wartość. Jeśli chcesz uzyskać większy zakres kolorów, wystarczy zwiększyć 'number_of_lines'. A jeśli chcesz tylko część kolorów w paśmie, zmniejsz "stop" i zwiększ "start" w razie potrzeby. – Parousia

+0

Szybkie pytanie: Jak dodać kolorbar zamiast legendy do fabuły? –

7

Połączenie linii style, markery i kolory jakościowe z 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

Powiązane problemy