Matplotlib discrete color bar

I am trying to make a discrete color panel for a scatter chart in matplotlib

I have data x, y and for each point the value of the integer tag that I want to represent with a unique color, for example

plt.scatter(x, y, c=tag) 

Usually the tag will be an integer from 0 to 20, but the exact range may vary

So far, I just used the default settings, for example

 plt.colorbar() 

which gives a continuous range of colors. Ideally, I would like to have a set of n discrete colors (n = 20 in this example). Even better would be to get a tag value of 0 to create a gray color and 1-20 to be colorful.

I found several cookbook scenarios, but they are very complex, and I cannot think that they are the right way to solve a seemingly simple problem.

+42
python matplotlib
Feb 08 '13 at 16:29
source share
5 answers

You can easily create your own discrete color score using BoundaryNorm as a normalizer for your spread. A bizarre bit (in my method) makes output 0 gray.

For images, I often use cmap.set_bad () and convert my data into an array with a mask size. It would be a lot easier to make 0 gray, but I could not get this to work with scatter or custom cmap.

Alternatively, you can make your own cmap from scratch or read an existing one and redefine only some specific entries.

 # setup the plot fig, ax = plt.subplots(1,1, figsize=(6,6)) # define the data x = np.random.rand(20) y = np.random.rand(20) tag = np.random.randint(0,20,20) tag[10:12] = 0 # make sure there are some 0 values to showup as grey # define the colormap cmap = plt.cm.jet # extract all colors from the .jet map cmaplist = [cmap(i) for i in range(cmap.N)] # force the first color entry to be grey cmaplist[0] = (.5,.5,.5,1.0) # create the new map cmap = cmap.from_list('Custom cmap', cmaplist, cmap.N) # define the bins and normalize bounds = np.linspace(0,20,21) norm = mpl.colors.BoundaryNorm(bounds, cmap.N) # make the scatter scat = ax.scatter(x,y,c=tag,s=np.random.randint(100,500,20),cmap=cmap, norm=norm) # create a second axes for the colorbar ax2 = fig.add_axes([0.95, 0.1, 0.03, 0.8]) cb = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, norm=norm, spacing='proportional', ticks=bounds, boundaries=bounds, format='%1i') ax.set_title('Well defined discrete colors') ax2.set_ylabel('Very custom cbar [-]', size=12) 

enter image description here

I personally think that with 20 different colors it is a little difficult to read the specific meaning, but this is of course for you.

+54
Feb 08 '13 at 18:57
source share

You can follow this example :

 #!/usr/bin/env python """ Use a pcolor or imshow with a custom colormap to make a contour plot. Since this example was initially written, a proper contour routine was added to matplotlib - see contour_demo.py and http://matplotlib.sf.net/matplotlib.pylab.html#-contour. """ from pylab import * delta = 0.01 x = arange(-3.0, 3.0, delta) y = arange(-3.0, 3.0, delta) X,Y = meshgrid(x, y) Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1) Z = Z2 - Z1 # difference of Gaussians cmap = cm.get_cmap('PiYG', 11) # 11 discrete colors im = imshow(Z, cmap=cmap, interpolation='bilinear', vmax=abs(Z).max(), vmin=-abs(Z).max()) axis('off') colorbar() show() 

which creates the following image:

poormans_contour

+33
Feb 08 '13 at 16:47
source share

To set values ​​above or below the range of the color palette, you will want to use the set_over and set_under in the color palette. If you want to mark a specific value, mask it (i.e. create a masked array) and use the set_bad method. (See the documentation for the colormap base class: http://matplotlib.org/api/colors_api.html#matplotlib.colors.Colormap )

It sounds like you want something like this:

 import matplotlib.pyplot as plt import numpy as np # Generate some data x, y, z = np.random.random((3, 30)) z = z * 20 + 0.1 # Set some values in z to 0... z[:5] = 0 cmap = plt.get_cmap('jet', 20) cmap.set_under('gray') fig, ax = plt.subplots() cax = ax.scatter(x, y, c=z, s=100, cmap=cmap, vmin=0.1, vmax=z.max()) fig.colorbar(cax, extend='min') plt.show() 

enter image description here

+23
Feb 08 '13 at 19:38
source share

The above answers are good, except that they do not have the correct placement of labels on the color bar. I like the labels in the middle of the color, so the number → color display is clearer. You can solve this problem by changing the limits of the matshow call:

 import matplotlib.pyplot as plt import numpy as np def discrete_matshow(data): #get discrete colormap cmap = plt.get_cmap('RdBu', np.max(data)-np.min(data)+1) # set limits .5 outside true range mat = plt.matshow(data,cmap=cmap,vmin = np.min(data)-.5, vmax = np.max(data)+.5) #tell the colorbar to tick at integers cax = plt.colorbar(mat, ticks=np.arange(np.min(data),np.max(data)+1)) #generate data a=np.random.randint(1, 9, size=(10, 10)) discrete_matshow(a) 

example of discrete colorbar

+17
Feb 25 '15 at 22:04
source share

I think you need to take a look at colors.ListedColormap to generate your color palette, or if you just need a static color package working on an application that could help.

0
Feb 08 '13 at 16:50
source share



All Articles