astromonerd
astromonerd

Reputation: 937

Discrete pyplot scatter colobar

I am creating a scatterplot with a colorbar

plt.scatter(X, Y, c=Z)
plt.colorbar()
plt.show()
plt.close()

where X and Y are float arrays and Z is an integer array. Even though Z is an integer array (here 1-14), the colorbar displays floats. enter image description here

How can I display a discrete colorbar 1-14?

I found something attempting to answer a similar question here, but I don't understand the answer (containing some complications to make 0 be gray) well enough to apply it.

Upvotes: 4

Views: 8831

Answers (2)

Han Zhengzu
Han Zhengzu

Reputation: 3852

Here is my discrete colorbar for land use type, it seems like your work,because the Z value is also an interger array from 1-14.

My method

creat the colormap and colorbar label manually learned from here

My Code

cMap = ListedColormap(['white', '#8dd3c7','#ffffb3','#bebada',  \               
                       '#b2182b','#80b1d3','#fdb462','#b3de69','#6a3d9a',\
                       '#b2df8a', '#1f78b4', '#ccebc5','#ffed6f'])

## If you want to use the colormap from plt.cm..., you can use(take 'jet' for example) 
cMap = plt.cm.get_cmap("jet",lut=13)  

### here you can change your data in    
lulc = plt.pcolormesh(lulc,cmap = cMap,alpha = 0.7)   

z_range = np.linspace(1,14,14)
list = z_range.astype('S10')

k = -0.05
for i in range(0,13,1):
    k = k + 1/13.0
   ax.annotate(list[i],xycoords='axes fraction',xy=(1.12,k),fontsize = 14, \
               fontstyle = 'italic',zorder =3)

cbar = plt.colorbar(lulc,ticks = [ ])
for label in cbar.ax.yaxis.get_ticklabels()[::-1]:
    label.set_visible(False)    

My result


(source: tietuku.com)

Wish it can help!

Upvotes: 0

Check out the second answer to your linked question. If you discretize your colourmap before calling scatter, it will automatically work as you want it to:

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

n = 14
X = np.random.rand(20)
Y = np.random.rand(20)
Z = np.random.randint(low=0,high=n,size=X.shape)

plt.figure()
plt.scatter(X,Y,c=Z,cmap=cm.hot)
plt.colorbar()

plt.figure()
plt.scatter(X,Y,c=Z,cmap=cm.get_cmap('hot',n))
plt.colorbar()

Results for comparison:

smoothdiscretized

Note that the default colourmap is jet. But only until viridis kicks in starting from version 2.0 as the new (and wonderful) default.

If what's bothering you is that the numbers are floating-point on the colourbar, you can set manual ticks in it, irrespective of the discretization of colours:

plt.figure()
plt.scatter(X,Y,c=Z,cmap=cm.jet)
plt.colorbar(ticks=np.unique(Z))
#or
#plt.colorbar(ticks=range(Z.min(),Z.max()+1))

Result:

integer ticks

Note that since I used a few random-generated points, not every number is present in Z, so unique might not be the best approach (see the missing ticks in the above figure). This is why I also added a solution based on min/max. You can tailor the limits to your needs depending on your actual application.

Upvotes: 4

Related Questions