Использование 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