Matplotlib - add colorbar to a sequence of line plots Matplotlib - add colorbar to a sequence of line plots python python

Matplotlib - add colorbar to a sequence of line plots


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

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 pltsm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.normalize(min=0, max=1))plt.colorbar(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)

Hope that helps somebody.

EDIT: For matplotlib v1.2 or greater the code becomes:

import matplotlib.pyplot as pltsm = 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)

EDIT: For matplotlib v1.3 or greater the code becomes:

import matplotlib.pyplot as pltsm = 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)

EDIT: For matplotlib v3.1 or greater simplifies to:

import matplotlib.pyplot as pltsm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1))plt.colorbar(sm)


Here's one way to do it while still using plt.plot(). Basically, you make a throw-away plot and get the colorbar from there.

import matplotlib as mplimport matplotlib.pyplot as pltmin, max = (-40, 30)step = 10# Setting up a colormap that's a simple transtionmymap = mpl.colors.LinearSegmentedColormap.from_list('mycolors',['blue','red'])# Using contourf to provide my colorbar info, then clearing the figureZ = [[0,0],[0,0]]levels = range(min,max+step,step)CS3 = plt.contourf(Z, levels, cmap=mymap)plt.clf()# Plotting what I actually wantX=[[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 contourfplt.show()

It's a little wasteful, but convenient. It's also not very wasteful if you make multiple plots as you can call plt.colorbar() without regenerating the info for it.

enter image description here


Here is a slightly simplied example inspired by the top answer given by Boris and Hooked (Thanks for the great idea!):

1. Discrete colorbar

Discrete colorbar is more involved, because colormap generated by mpl.cm.get_cmap() is not a mappable image needed as a colorbar() argument. A dummie mappable needs to generated as shown below:

import numpy as npimport matplotlib.pyplot as pltimport matplotlib as mpln_lines = 5x = 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 mappabledummie_cax = ax.scatter(c, c, c=c, cmap=cmap)# Clear axisax.cla()for i, yi in enumerate(y.T):    ax.plot(x, yi, c=cmap(i))fig.colorbar(dummie_cax, ticks=c)plt.show();

This will produce a plot with a discrete colorbar:enter image description here


2. Continuous colorbar

Continuous colorbar is less involved, as mpl.cm.ScalarMappable() allows us to obtain an "image" for colorbar().

import numpy as npimport matplotlib.pyplot as pltimport matplotlib as mpln_lines = 5x = 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();

This will produce a plot with a continuous colorbar:enter image description here

[Side note] In this example, I personally don't know why cmap.set_array([]) is necessary (otherwise we'd get error messages). If someone understand the principles under the hood, please comment :)