Matplotlib - add colorbar to string sequence

I have a string sequence for two variables (x, y) for a number of different values โ€‹โ€‹of the variable z. Usually I add lines with such legends:

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 and y 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() 

But I have too many graphs, and legends will cover the graph. I would prefer the color bar to indicate the z value corresponding to the color. I can not find anything like this in the gallery, and all my attempts to cope with the color panel failed. Apparently, I should create a collection of plots before trying to add a color panel.

Is there an easy way to do this? Thank.

EDIT (clarification):

I wanted to do something like this:

 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 and y 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() 

But this will not work according to the Matplotlib link, because the list of graphs is not โ€œdisplayedโ€, whatever that means.

I created an alternative chart 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 and ys are lists of x and y coordinate lists, and zs is a list of different conditions for coloring each line. It feels a bit like masonry, though ... I thought there would be a tidier way to do this. I like the flexibility of the plt.plot() function.

+55
python matplotlib colorbar
Dec 01 2018-11-12T00:
source share
4 answers

Here is one way to do this while still using plt.plot (). Basically, you make a discarded plot and get a color panel from there.

 import matplotlib as mpl import matplotlib.pyplot as plt min, max = (-40, 30) step = 10 # Setting up a colormap that 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() 

It's a bit wasteful, but comfortable. It is also not very wasteful if you make several graphs, since you can call plt.colorbar () without restoring information for it.

enter image description here

+33
Dec 02 '11 at 10:17
source share
โ€” -

(I know this is an old question, but ...) For color bars, matplotlib.cm.ScalarMappable is required, plt.plot creates lines that are not displayed scalarly, so we need a scalar map to create the color bar.

Good. Thus, the ScalarMappable constructor accepts a cmap and an instance of norm . (Norms scale the data to 0-1, cmaps that you already worked with, take a number from 0 to 1 and return 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) 

Since your data is already in the range 0-1, you can simplify the creation of sm to:

 sm = plt.cm.ScalarMappable(cmap=my_cmap) 

Hope this helps someone.

EDIT : For matplotlib v1.2 or higher, 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) 

EDIT : For matplotlib v1.3 or higher, 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) 

EDIT : For Matplotlib v3.1 or higher simplifies:

 import matplotlib.pyplot as plt sm = plt.cm.ScalarMappable(cmap=my_cmap, norm=plt.Normalize(vmin=0, vmax=1)) plt.colorbar(sm) 
+102
Jul 19 '12 at 10:14
source share

Here's a slightly simplified example, inspired by the best answer given by Boris and Hooked (thanks for a great idea!):

1. Discrete color bar

The discrete color bar is more complex because mpl.cm.get_cmap() generated by mpl.cm.get_cmap() is not a display image, which is required as an argument to colorbar() . You need to generate the layout as shown below:

 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(yT): ax.plot(x, yi, c=cmap(i)) fig.colorbar(dummie_cax, ticks=c) plt.show(); 

This will create a graph with a discrete color scale: enter image description here




2. Continuous color bar

The continuous color bar is less involved, since mpl.cm.ScalarMappable() allows us to get an โ€œimageโ€ for 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(yT): ax.plot(x, yi, c=cmap.to_rgba(i + 1)) fig.colorbar(cmap, ticks=c) plt.show(); 

This will create a graph with a continuous color bar: enter image description here

[Note] In this example, I personally do not know why cmap.set_array([]) needed (otherwise we would receive error messages). If someone understands the principles under the hood, please comment :)

+12
Mar 09 '18 at 0:42
source share

Like the other answers here, try using dummy graphics, which is not a very good style, here is the general code for

Discrete color bar

A discrete color bar is created in the same way as a continuous color bar, but with a different normalization. In this case, use BoundaryNorm .

 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(yT): ax.plot(x, yi, c=cmap(i)) fig.colorbar(sm, ticks=c) plt.show() 

enter image description here

+5
Mar 19 '18 at 23:59
source share



All Articles