利用 Colormaps 设置 matplotlib 中的线条颜色

如何在 matplotlib 中使用在运行时提供的标量值(比如 jet)设置线的颜色?我尝试了几种不同的方法,我想我被难住了。values[]是一个标量的存储数组。曲线是一组1-d 数组,标签是一组文本字符串。每个数组的长度相同。

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()
221309 次浏览

您收到的错误是由于您定义 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()

结果:

enter image description here

Using a ScalarMappable is an improvement over the approach presented in my related answer: creating over 20 unique legend colors using matplotlib

我认为使用 numpy 的 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()

This results in 1000 uniquely-colored lines that span the entire cm.jet colormap as pictured below. If you run this script you'll find that you can zoom in on the individual lines.

cm.jet between 0.0 and 1.0 with 1000 graduations

Now say I want my 1000 line colors to just span the greenish portion between lines 400 to 600. I simply change my start and stop values to 0.4 and 0.6 and this results in using only 20% of the cm.jet color map between 0.4 and 0.6.

enter image description here

因此,在一行摘要中,您可以相应地从 matplotlib.cm 颜色图创建一个 rgba 颜色列表:

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

在本例中,我使用了通常调用的 map,名为 jet,但是您可以通过调用:

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

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

你可以做我写从我删除的帐户(禁止新的职位: (有)。它相当简单,看起来不错。

我通常使用这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)

例子三:

船舶横摇 RAO 与池田阻尼对横摇振幅 A44的影响