Set Matplotlib colorbar size to match graph Set Matplotlib colorbar size to match graph python python

Set Matplotlib colorbar size to match graph


This combination (and values near to these) seems to "magically" work for me to keep the colorbar scaled to the plot, no matter what size the display.

plt.colorbar(im,fraction=0.046, pad=0.04)

It also does not require sharing the axis which can get the plot out of square.


You can do this easily with a matplotlib AxisDivider.

The example from the linked page also works without using subplots:

import matplotlib.pyplot as pltfrom mpl_toolkits.axes_grid1 import make_axes_locatableimport numpy as npplt.figure()ax = plt.gca()im = ax.imshow(np.arange(100).reshape((10,10)))# create an axes on the right side of ax. The width of cax will be 5%# of ax and the padding between cax and ax will be fixed at 0.05 inch.divider = make_axes_locatable(ax)cax = divider.append_axes("right", size="5%", pad=0.05)plt.colorbar(im, cax=cax)

enter image description here


@bogatron already gave the answer suggested by the matplotlib docs, which produces the right height, but it introduces a different problem.Now the width of the colorbar (as well as the space between colorbar and plot) changes with the width of the plot.In other words, the aspect ratio of the colorbar is not fixed anymore.

To get both the right height and a given aspect ratio, you have to dig a bit deeper into the mysterious axes_grid1 module.

import matplotlib.pyplot as pltfrom mpl_toolkits.axes_grid1 import make_axes_locatable, axes_sizeimport numpy as npaspect = 20pad_fraction = 0.5ax = plt.gca()im = ax.imshow(np.arange(200).reshape((20, 10)))divider = make_axes_locatable(ax)width = axes_size.AxesY(ax, aspect=1./aspect)pad = axes_size.Fraction(pad_fraction, width)cax = divider.append_axes("right", size=width, pad=pad)plt.colorbar(im, cax=cax)

Note that this specifies the width of the colorbar w.r.t. the height of the plot (in contrast to the width of the figure, as it was before).

The spacing between colorbar and plot can now be specified as a fraction of the width of the colorbar, which is IMHO a much more meaningful number than a fraction of the figure width.

image plot with colorbar

UPDATE:

I created an IPython notebook on the topic, where I packed the above code into an easily re-usable function:

import matplotlib.pyplot as pltfrom mpl_toolkits import axes_grid1def add_colorbar(im, aspect=20, pad_fraction=0.5, **kwargs):    """Add a vertical color bar to an image plot."""    divider = axes_grid1.make_axes_locatable(im.axes)    width = axes_grid1.axes_size.AxesY(im.axes, aspect=1./aspect)    pad = axes_grid1.axes_size.Fraction(pad_fraction, width)    current_ax = plt.gca()    cax = divider.append_axes("right", size=width, pad=pad)    plt.sca(current_ax)    return im.axes.figure.colorbar(im, cax=cax, **kwargs)

It can be used like this:

im = plt.imshow(np.arange(200).reshape((20, 10)))add_colorbar(im)