Использование Colormaps для установки цвета линии в matplotlib

Как установить цвет строки в matplotlib со скалярными значениями, указанными во время выполнения, с помощью цветовой карты (скажем jet)? Я попробовал здесь несколько разных подходов, и я думаю, что я в тупике. values[] - это строгий массив скаляров. кривые представляют собой набор 1-мерных массивов, а метки - это массив текстовых строк. Каждый из массивов имеет одинаковую длину.

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

Ответ 1

Ошибка, которую вы получаете, связана с тем, как вы определяете jet. Вы создаете базовый класс Colormap с именем "jet", но это сильно отличается от определения по умолчанию цветовой карты "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()

Результат:

enter image description here

Использование a ScalarMappable является улучшением по сравнению с подходом, представленным в моем ответном ответе: создание более 20 уникальных цветов легенды с использованием matplotlib

Ответ 2

Я подумал, что было бы полезно включить то, что я считаю более простым методом, с использованием numpy linspace в сочетании с объектом cmp-типа matplotlib. Возможно, что вышеупомянутое решение для более старой версии. Я использую 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()

В результате получается 1000 уникально окрашенных линий, которые охватывают всю цветовую карту cm.jet, как показано ниже. Запустив этот скрипт, вы обнаружите, что можете увеличивать отдельные строки.

cm.jet between 0.0 and 1.0 with 1000 graduations

Теперь скажем, что я хочу, чтобы мои 1000 цветов линий просто охватывали зеленоватую часть между строками 400–600. Я просто изменяю свои начальные и конечные значения на 0,4 и 0,6, и это приводит к использованию только 20% цветовой карты cm.jet от 0,4 до 0.6.

enter image description here

Таким образом, в одной строке вы можете создать список цветов rgba из таблицы цветов matplotlib.cm соответственно:

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

В этом случае я использую часто вызываемую карту с именем jet, но вы можете найти полный список цветовых карт, доступных в вашей версии matplotlib, вызвав:

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

Ответ 3

Сочетание стилей линий, маркеров и качественных цветов из 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

ОБНОВЛЕНИЕ: Поддержка не только ListedColormap, но и LinearSegmentedColormap

import itertools
import matplotlib.pyplot as plt
Ncolors = 8
#colormap = plt.cm.Dark2# ListedColormap
colormap = plt.cm.viridis# LinearSegmentedColormap
Ncolors = min(colormap.N,Ncolors)
mapcolors = [colormap(int(x*colormap.N/Ncolors)) for x in range(Ncolors)]
N = Ncolors*4+10
l_styles = ['-','--','-.',':']
m_styles = ['','.','o','^','*']
fig,ax = plt.subplots(gridspec_kw=dict(right=0.6))
for i,(marker,linestyle,color) in zip(range(N),itertools.product(m_styles,l_styles, mapcolors)):
    ax.plot([0,1,2],[0,2*i,2*i], color=color, linestyle=linestyle,marker=marker,label=i)
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.,ncol=3,prop={'size': 8})

enter image description here

Ответ 4

Вы можете сделать, как я написал с моего удаленного аккаунта (бан за новые сообщения :( там было). Это довольно просто и красиво выглядит.

Я обычно использую 3-й из этих 3-х, также я не проверял 1 и 2 версию.

from matplotlib.pyplot import cm
import numpy as np

#variable n should be number of curves to plot (I skipped this earlier thinking that it is obvious when looking at picture - sorry my bad mistake xD): n=len(array_of_curves_to_plot)
#version 1:

color=cm.rainbow(np.linspace(0,1,n))
for i,c in zip(range(n),color):
   ax1.plot(x, y,c=c)

#or version 2: - faster and better:

color=iter(cm.rainbow(np.linspace(0,1,n)))
c=next(color)
plt.plot(x,y,c=c)

#or version 3:

color=iter(cm.rainbow(np.linspace(0,1,n)))
for i in range(n):
   c=next(color)
   ax1.plot(x, y,c=c)

пример 3:

Корабельная РАО Ролл против Икеда демпфирования в функции амплитуды Ролла А44