Matplotlib - 将颜色条添加到一系列线图中

Raf*_*ini 57 python matplotlib colorbar

对于变量z的许多不同值,我有两个变量(x,y)的一系列线图.我通常会添加带有这样的图例的线条图:

import matplotlib.pyplot as plt

fig = plt.figure()
ax  = fig.add_subplot(111)
# suppose mydata is a list of tuples containing (xs, ys, z) 
# where xs and ys are lists of x's and y's and z is a number. 
legns = []
for(xs,ys,z) in mydata:
   pl = ax.plot(xs,ys,color = (z,0,0))
   legns.append("z = %f"%(z))
ax.legends(legns) 
plt.show()
Run Code Online (Sandbox Code Playgroud)

但是我有太多的图表,传说将涵盖图表.我宁愿用一个颜色条来表示与颜色对应的z的值.我无法在galery中找到类似的东西,我所有的尝试都处理了colorbar失败.显然我必须在尝试添加颜色条之前创建一组绘图.

是否有捷径可寻?谢谢.

编辑(澄清):

我想做这样的事情:

import matplotlib.pyplot as plt
import matplotlib.cm     as cm

fig = plt.figure()
ax  = fig.add_subplot(111)
mycmap = cm.hot
# suppose mydata is a list of tuples containing (xs, ys, z) 
# where xs and ys are lists of x's and y's and z is a number between 0 and 1
plots = []
for(xs,ys,z) in mydata:
   pl = ax.plot(xs,ys,color = mycmap(z))
   plots.append(pl)
fig.colorbar(plots)
plt.show()
Run Code Online (Sandbox Code Playgroud)

但是这根据Matplotlib参考不起作用,因为无论这意味着什么,图表列表都不是"可映射的".

我使用LineCollection以下方法创建了另一种绘图函数:

def myplot(ax,xs,ys,zs, cmap):
    plot = lc([zip(x,y) for (x,y) in zip(xs,ys)], cmap = cmap)
    plot.set_array(array(zs))
    x0,x1 = amin(xs),amax(xs)
    y0,y1 = amin(ys),amax(ys)
    ax.add_collection(plot)
    ax.set_xlim(x0,x1)
    ax.set_ylim(y0,y1)
    return plot
Run Code Online (Sandbox Code Playgroud)

xs并且ys是x和y坐标列表的列表,并且zs是每条线着色的不同条件的列表.虽然感觉有点像cludge ...我认为会有更简洁的方法来做到这一点.我喜欢这个plt.plot()功能的灵活性.

pel*_*son 105

(我知道这是一个老问题,但是......)Colorbars需要a matplotlib.cm.ScalarMappable,plt.plot产生不是标量可映射的行,因此,为了制作一个颜色条,我们需要制作一个标量可映射的.

好.所以a的构造函数ScalarMappable接受一个cmap和一个norm实例.(规范将数据缩放到0-1范围,你已经使用过的cmaps并取0-1之间的数字并返回一个颜色).所以在你的情况下:

import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(min=0, max=1))
plt.colorbar(sm)
Run Code Online (Sandbox Code Playgroud)

由于您的数据已经在0-1范围内,因此您可以将sm创建简化为:

sm = plt.cm.ScalarMappable(cmap=my_cmap)
Run Code Online (Sandbox Code Playgroud)

希望能帮到别人.

编辑:对于matplotlib v1.2或更高版本,代码变为:

import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(vmin=0, vmax=1))
# fake up the array of the scalar mappable. Urgh...
sm._A = []
plt.colorbar(sm)
Run Code Online (Sandbox Code Playgroud)

编辑:对于matplotlib v1.3或更高版本,代码变为:

import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))
# fake up the array of the scalar mappable. Urgh...
sm._A = []
plt.colorbar(sm)
Run Code Online (Sandbox Code Playgroud)

  • 看起来matplotlib v1.3示例应该进一步调整,目前它会产生警告:"MatplotlibDeprecationWarning:版本1.3中不推荐使用normalize类别名.请改用Normalize." (4认同)
  • 这对我有用:http://stackoverflow.com/a/6601210/125507我刚用linspace而不是z1,因为我正在绘制色图本身,所以数字是任意的.:) (2认同)
  • 谢谢,这节省了我的一天.但是它不能正常工作:我必须用`sm.set_array(Zs)`替换`sm._A = []`,其中`Zs`是一个包含转换为颜色的值的数组. (2认同)

Bor*_*ris 34

这是在使用plt.plot()时执行此操作的一种方法.基本上,你制作一个扔掉的情节并从那里获得颜色条.

import matplotlib as mpl
import matplotlib.pyplot as plt

min, max = (-40, 30)
step = 10

# Setting up a colormap that's a simple transtion
mymap = mpl.colors.LinearSegmentedColormap.from_list('mycolors',['blue','red'])

# Using contourf to provide my colorbar info, then clearing the figure
Z = [[0,0],[0,0]]
levels = range(min,max+step,step)
CS3 = plt.contourf(Z, levels, cmap=mymap)
plt.clf()

# Plotting what I actually want
X=[[1,2],[1,2],[1,2],[1,2]]
Y=[[1,2],[1,3],[1,4],[1,5]]
Z=[-40,-20,0,30]
for x,y,z in zip(X,Y,Z):
    # setting rgb color based on z normalized to my range
    r = (float(z)-min)/(max-min)
    g = 0
    b = 1-r
    plt.plot(x,y,color=(r,g,b))
plt.colorbar(CS3) # using the colorbar info I got from contourf
plt.show()
Run Code Online (Sandbox Code Playgroud)

这有点浪费,但很方便.如果您制作多个绘图也不是很浪费,因为您可以调用plt.colorbar()而无需为其重新生成信息.

在此输入图像描述

  • 这个问题很好的解决方案,但我认为一个更好的解决方案是制作一个标量可映射的实例(请参阅我的回答). (2认同)
  • 是否有任何方法可以使用颜色条在颜色方案中产生*连续*变化,而不是上图中显示的带状,离散? (2认同)

Sha*_*Dou 13

这是一个略显简洁的例子,受到BorisHooked给出的最佳答案的启发(感谢您的好主意!):

1. 离散色条

离散颜色条更复杂,因为生成的颜色图mpl.cm.get_cmap()不是作为colorbar()参数需要的可映射图像.需要生成dummie mappable,如下所示:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)

cmap = mpl.cm.get_cmap('jet', n_lines)

fig, ax = plt.subplots(dpi=100)
# Make dummie mappable
dummie_cax = ax.scatter(c, c, c=c, cmap=cmap)
# Clear axis
ax.cla()
for i, yi in enumerate(y.T):
    ax.plot(x, yi, c=cmap(i))
fig.colorbar(dummie_cax, ticks=c)
plt.show();
Run Code Online (Sandbox Code Playgroud)

这将生成带有离散颜色条的图: 在此输入图像描述


2. 连续色条

连续色条参与较少,因为mpl.cm.ScalarMappable()我们可以获得"图像" colorbar().

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl


n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)

norm = mpl.colors.Normalize(vmin=c.min(), vmax=c.max())
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.jet)
cmap.set_array([])

fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
    ax.plot(x, yi, c=cmap.to_rgba(i + 1))
fig.colorbar(cmap, ticks=c)
plt.show();
Run Code Online (Sandbox Code Playgroud)

这将生成带有连续颜色条的图: 在此输入图像描述

[附注]在这个例子中,我个人不知道为什么cmap.set_array([])有必要(否则我们会收到错误消息).如果有人理解引擎盖下的原则,请评论:)

  • 我花了一段时间才意识到你的 `c=cmap.to_rgba(i + 1)` 在一般情况下应该是 `c=cmap.to_rgba(value)`,其中 `value` 是与应该映射到那个颜色。 (2认同)

Imp*_*est 5

正如这里的其他答案尝试使用虚假图一样,这并不是很好的样式,这是用于

离散色条

离散色条的产生方式与创建连续色条的方式相同,只是具有不同的标准化。在这种情况下,BoundaryNorm应使用a。

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

n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1., n_lines + 1)

cmap = plt.get_cmap("jet", len(c))
norm = matplotlib.colors.BoundaryNorm(np.arange(len(c)+1)+0.5,len(c))
sm = plt.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])  # this line may be ommitted for matplotlib >= 3.1

fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
    ax.plot(x, yi, c=cmap(i))
fig.colorbar(sm, ticks=c)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明