问题描述
对于变量 z 的多个不同值,我有两个变量 (x,y) 的一系列线图.我通常会添加带有图例的线图,如下所示:
I have a sequence of line plots for two variables (x,y) for a number of different values of a variable z. I would normally add the line plots with legends like this:
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()
但是我的图表太多了,图例会覆盖图表.我宁愿有一个颜色条来指示与颜色对应的 z 值.我在画廊中找不到类似的东西,而且我所有的尝试都无法处理颜色条.显然,在尝试添加颜色条之前,我必须创建一组图.
But I have too many graphs and the legends will cover the graph. I'd rather have a colorbar indicating the value of z corresponding to the color. I can't find anything like that in the galery and all my attempts do deal with the colorbar failed. Apparently I must create a collection of plots before trying to add a colorbar.
有没有简单的方法可以做到这一点?谢谢.
Is there an easy way to do this? Thanks.
编辑(澄清):
我想做这样的事情:
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()
但是根据 Matplotlib 参考,这不起作用,因为无论这意味着什么,绘图列表都不是可映射的".
But this won't work according to the Matplotlib reference because a list of plots is not a "mappable", whatever this means.
我使用 LineCollection
创建了一个替代绘图函数:
I've created an alternative plot function using 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
xs
和 ys
是 x 和 y 坐标列表的列表,而 zs
是为每一行着色的不同条件的列表.虽然感觉有点像杂物......我认为会有更简洁的方法来做到这一点.我喜欢 plt.plot()
函数的灵活性.
xs
and ys
are lists of lists of x and y coordinates and zs
is a list of the different conditions to colorize each line. It feels a bit like a cludge though... I thought that there would be a more neat way to do this. I like the flexibility of the plt.plot()
function.
推荐答案
(我知道这是一个老问题但是...)颜色条需要 matplotlib.cm.ScalarMappable
, plt.plot
生成的线不是标量可映射的,因此,为了制作颜色条,我们需要使标量可映射.
(I know this is an old question but...) Colorbars require a matplotlib.cm.ScalarMappable
, plt.plot
produces lines which are not scalar mappable, therefore, in order to make a colorbar, we are going to need to make a scalar mappable.
好的.所以 ScalarMappable
的构造函数接受一个 cmap
和一个 norm
实例.(规范将数据缩放到 0-1 范围内,您已经使用过的 cmaps 并采用 0-1 之间的数字并返回颜色).所以在你的情况下:
Ok. So the constructor of a ScalarMappable
takes a cmap
and a norm
instance. (norms scale data to the range 0-1, cmaps you have already worked with and take a number between 0-1 and returns a color). So in your case:
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(min=0, max=1))
plt.colorbar(sm)
因为您的数据已经在 0-1 范围内,您可以将 sm
创建简化为:
Because your data is in the range 0-1 already, you can simplify the sm
creation to:
sm = plt.cm.ScalarMappable(cmap=my_cmap)
希望对某人有所帮助.
编辑:对于 matplotlib v1.2 或更高版本,代码变为:
EDIT: For matplotlib v1.2 or greater the code becomes:
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)
编辑:对于 matplotlib v1.3 或更高版本,代码变为:
EDIT: For matplotlib v1.3 or greater the code becomes:
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)
编辑:对于 matplotlib v3.1 或更高版本简化为:
EDIT: For matplotlib v3.1 or greater simplifies to:
import matplotlib.pyplot as plt
sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))
plt.colorbar(sm)
这篇关于Matplotlib - 将颜色条添加到一系列线图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!