A better solution is

from matplotlib.ticker import FuncFormatter

fmt = lambda x, pos: '{:.1%}'.format(x)
cbar = plt.colorbar(format=FuncFormatter(fmt))
Answer from Gen on Stack Overflow
🌐
Matplotlib
matplotlib.org › stable › gallery › ticks › colorbar_tick_labelling_demo.html
Colorbar Tick labelling — Matplotlib 3.11.2 documentation
fig, ax = plt.subplots() data = rng.standard_normal((250, 250)) cax = ax.imshow(data, vmin=-1, vmax=1, cmap='coolwarm') ax.set_title('Gaussian noise with vertical colorbar') # Add colorbar, make sure to specify tick locations to match desired ticklabels cbar = fig.colorbar(cax, ticks=[-1, 0, 1], ...
🌐
Matplotlib
matplotlib.org › 3.4.3 › gallery › ticks_and_spines › colorbar_tick_labelling_demo.html
Colorbar Tick Labelling — Matplotlib 3.4.3 documentation
August 13, 2021 - fig, ax = plt.subplots() data = np.clip(randn(250, 250), -1, 1) cax = ax.imshow(data, cmap=cm.coolwarm) ax.set_title('Gaussian noise with vertical colorbar') # Add colorbar, make sure to specify tick locations to match desired ticklabels cbar = fig.colorbar(cax, ticks=[-1, 0, 1]) ...
🌐
Matplotlib
matplotlib.org › stable › api › colorbar_api.html
matplotlib.colorbar — Matplotlib 3.11.2 documentation
If False the minimum and maximum colorbar extensions will be triangular (the default). If True the extensions will be rectangular. ... If None, ticks are determined automatically from the input. ... If None, ScalarFormatter is used. Format strings, e.g., "%4.2e" or "{x:.2e}", are supported.
🌐
GitHub
github.com › matplotlib › matplotlib › issues › 21378
[ENH]: use new style format strings for colorbar ticks · Issue #21378 · matplotlib/matplotlib
October 18, 2021 - As in update_ticks we pass the colorbar's formatter to the long axis, matplotlib/lib/matplotlib/colorbar.py · Line 801 in 67e1814 · self._long_axis().set_major_formatter(self.formatter) the if statement above may be removed to keep the default logic only in Axis.
Author: matplotlib
🌐
Matplotlib
matplotlib.org › stable › api › _as_gen › matplotlib.pyplot.colorbar.html
matplotlib.pyplot.colorbar — Matplotlib 3.11.2 documentation
If False the minimum and maximum colorbar extensions will be triangular (the default). If True the extensions will be rectangular. ... If None, ticks are determined automatically from the input. ... If None, ScalarFormatter is used. Format strings, e.g., "%4.2e" or "{x:.2e}", are supported.
🌐
Matplotlib
matplotlib.org › 3.1.0 › gallery › ticks_and_spines › colorbar_tick_labelling_demo.html
Colorbar Tick Labelling Demo — Matplotlib 3.1.0 documentation
January 5, 2020 - fig, ax = plt.subplots() data = ... # Add colorbar, make sure to specify tick locations to match desired ticklabels cbar = fig.colorbar(cax, ticks=[-1, 0, 1]) cbar.ax.set_yticklabels(['< -1', '0', '> 1']) # vertically oriented colorbar...
🌐
Matplotlib
matplotlib.org › 3.3.3 › gallery › ticks_and_spines › colorbar_tick_labelling_demo.html
Colorbar Tick Labelling Demo — Matplotlib 3.3.3 documentation
November 12, 2020 - fig, ax = plt.subplots() data = np.clip(randn(250, 250), -1, 1) cax = ax.imshow(data, cmap=cm.coolwarm) ax.set_title('Gaussian noise with vertical colorbar') # Add colorbar, make sure to specify tick locations to match desired ticklabels cbar = fig.colorbar(cax, ticks=[-1, 0, 1]) ...
Find elsewhere
🌐
Matplotlib
matplotlib.org › 3.5.1 › gallery › ticks › colorbar_tick_labelling_demo.html
Colorbar Tick Labelling — Matplotlib 3.5.1 documentation
fig, ax = plt.subplots() data = np.clip(randn(250, 250), -1, 1) cax = ax.imshow(data, cmap=cm.coolwarm) ax.set_title('Gaussian noise with vertical colorbar') # Add colorbar, make sure to specify tick locations to match desired ticklabels cbar = fig.colorbar(cax, ticks=[-1, 0, 1]) ...
🌐
Matplotlib
matplotlib.org › 3.1.1 › api › colorbar_api.html
matplotlib.colorbar — Matplotlib 3.1.2 documentation
However, if the norm only changes values of vmin, vmax or cmap then the old formatter and locator will be preserved. class matplotlib.colorbar.ColorbarBase(ax, cmap=None, norm=None, alpha=None, values=None, boundaries=None, orientation='vertical', ticklocation='auto', extend='neither', spacing='uniform', ticks=None, format=None, drawedges=False, filled=True, extendfrac=None, extendrect=False, label='')[source]¶
🌐
GeeksforGeeks
geeksforgeeks.org › setting-the-number-of-ticks-in-pltcolorbar-in-matplotlib
Setting the Number of Ticks in plt.colorbar in Matplotlib? - GeeksforGeeks
August 8, 2024 - Setting the number of ticks in plt.colorbar in Matplotlib means specifying the positions and labels of the discrete values displayed on the colorbar. This helps to control how the data range is visually represented, making it easier to interpret the color-coded information.
🌐
Matplotlib
matplotlib.org › 3.1.0 › api › colorbar_api.html
matplotlib.colorbar — Matplotlib 3.1.0 documentation
May 18, 2019 - However, if the norm only changes values of vmin, vmax or cmap then the old formatter and locator will be preserved. class matplotlib.colorbar.ColorbarBase(ax, cmap=None, norm=None, alpha=None, values=None, boundaries=None, orientation='vertical', ticklocation='auto', extend='neither', spacing='uniform', ticks=None, format=None, drawedges=False, filled=True, extendfrac=None, extendrect=False, label='')[source]¶
🌐
TutorialsPoint
tutorialspoint.com › matplotlib › matplotlib_colorbars.htm
Matplotlib - Colorbars
The ticks parameter is used to set the ticks, and the format parameter helps format the tick labels on the visible colorbar axes. This example uses the imshow() method to display the data as an image, and places a colorbar horizontally to the ...
Top answer
1 of 2
6

You can keep the same locators as proposed by the colorbar function but change the ticklabels in order to print the formatted date as follows:

# change colobar ticks labels and locators 
cbar.set_ticks([s.colorbar.vmin + t*(s.colorbar.vmax-s.colorbar.vmin) for t in cbar.ax.get_yticks()])
cbar.set_ticklabels([mdates.datetime.datetime.fromtimestamp((s.colorbar.vmin + t*(s.colorbar.vmax-s.colorbar.vmin))/1000000000).strftime('%c') for t in cbar.ax.get_yticks()])
plt.show()

which gives the result below:

If you really want to control tick locations, you can compute the desired values (here for approximately 3 months intervals ~91.25 days):

i,ticks = 0,[s.colorbar.vmin]
while ticks[-1] < s.colorbar.vmax:
   ticks.append(s.colorbar.vmin+i*24*3600*91.25*1e9)
   i = i+1
ticks[-1] = s.colorbar.vmax
cbar.set_ticks(ticks)
cbar.set_ticklabels([mdates.datetime.datetime.fromtimestamp(t/1e9).strftime('%c') for t in ticks])
2 of 2
2

The colormapping machinery of matplotlib has no concepts of "units" like an x or y axis does, so you can do the conversion from date to floats manually before mapping and then set the locator and formatter manually. You can also look into how pandas maps their date object to floats, it may be a bit different than the native matplotlib mapping:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

dates = np.datetime64('2019-11-01') + np.arange(10)*np.timedelta64(1, 'D')
X= np.random.randn(10, 2)

plt.scatter(X[:, 0], X[:, 1], c=mdates.date2num(dates))
cb = plt.colorbar()
loc = mdates.AutoDateLocator()
cb.ax.yaxis.set_major_locator(loc)
cb.ax.yaxis.set_major_formatter(mdates.ConciseDateFormatter(loc))
plt.show()

Top answer
1 of 2
26

You are suffering from an off-by-one error. You have 10 ticklabels spread among 11 colors. You might be able to correct the error by using np.linspace instead of np.arange. Using np.linspace the third argument is the number of values desired. This reduces the amount of mental gymnastics needed to avoid the off-by-one error:

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

def colorbar_index(ncolors, cmap):
    cmap = cmap_discretize(cmap, ncolors)
    mappable = cm.ScalarMappable(cmap=cmap)
    mappable.set_array([])
    mappable.set_clim(-0.5, ncolors+0.5)
    colorbar = plt.colorbar(mappable)
    colorbar.set_ticks(np.linspace(0, ncolors, ncolors))
    colorbar.set_ticklabels(range(ncolors))

def cmap_discretize(cmap, N):
    """Return a discrete colormap from the continuous colormap cmap.

        cmap: colormap instance, eg. cm.jet. 
        N: number of colors.

    Example
        x = resize(arange(100), (5,100))
        djet = cmap_discretize(cm.jet, 5)
        imshow(x, cmap=djet)
    """

    if type(cmap) == str:
        cmap = plt.get_cmap(cmap)
    colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
    colors_rgba = cmap(colors_i)
    indices = np.linspace(0, 1., N+1)
    cdict = {}
    for ki,key in enumerate(('red','green','blue')):
        cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki])
                       for i in xrange(N+1) ]
    # Return colormap object.
    return mcolors.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)

fig, ax = plt.subplots()
A = np.random.random((10,10))*10
cmap = plt.get_cmap('YlGnBu')
ax.imshow(A, interpolation='nearest', cmap=cmap)
colorbar_index(ncolors=11, cmap=cmap)    
plt.show()

2 of 2
19

You can control the placement and the labels by hand. I'll start with a linear cmap generated from cmap_discretize on the page you linked:

import numpy as np
import pylab as plt

# The number of divisions of the cmap we have
k = 10

# Random test data
A = np.random.random((10,10))*k
c = cmap_discretize('jet', k)

# First show without
plt.subplot(121)
plt.imshow(A,interpolation='nearest',cmap=c)
plt.colorbar()

# Now label properly
plt.subplot(122)
plt.imshow(A,interpolation='nearest',cmap=c)

cb = plt.colorbar()
labels = np.arange(0,k,1)
loc    = labels + .5
cb.set_ticks(loc)
cb.set_ticklabels(labels)

plt.show()

🌐
GeeksforGeeks
geeksforgeeks.org › change-the-label-size-and-tick-label-size-of-colorbar-using-matplotlib-in-python
Change the label size and tick label size of colorbar using Matplotlib in Python - GeeksforGeeks
November 5, 2021 - Matplotlib is a powerful library for creating visualizations in Python. One of its features is the ability to add colorbars to plots, which can be customized in various ways. A common requirement is to set the number of ticks on a colorbar, especially when the default number of ticks leads to overla