Search code examples
pythonmatplotlibseaborncolorbar

Shrink and anchor matplotlib colorbar


How do I use colorbar attributes such as in this snippet:

import seaborn as sns

uniform_data = np.random.rand(10, 12) # random data
ax = sns.heatmap(uniform_data)

cbar = ax.collections[0].colorbar

plt.show()

To shrink the colorbar and put it to the bottom and anchored to the lower left corner (that is, NOT centered)?

Something like this, but with the colorbar shrunk to, let's say 70% and anchored to the bottom left

enter image description here

I am unsure how to search for the methods as cbar.set_location() is not available.


Solution

  • You could create the colorbar via seaborn, extract its position, adapt it and set it again:

    from matplotlib import pyplot as plt
    import seaborn as sns
    import numpy as np
    
    uniform_data = np.random.rand(10, 12)
    ax = sns.heatmap(uniform_data, cmap='rocket_r', cbar_kws={'orientation': 'horizontal', 'ticks': np.linspace(0, 1, 6)})
    
    cax = ax.collections[0].colorbar.ax  # get the ax of the colorbar
    pos = cax.get_position()  # get the original position
    cax.set_position([pos.x0, pos.y0, pos.width * 0.6, pos.height])  # set a new position
    cax.set_frame_on(True)
    cax.invert_xaxis()  # invert the direction of the colorbar
    for spine in cax.spines.values():  # show the colorbar frame again
         spine.set(visible=True, lw=.8, edgecolor='black')
    plt.show()
    

    change seaborn colorbar position

    Note that you need cbar_kws={'orientation': 'horizontal'} for a horizontal colorbar that by default is aligned with the x-axis.

    After using .set_position, something like plt.tight_layout() won't work anymore.

    About your new questions:

    • cax.invert_xaxis() doesn't invert the colorbar direction

      • Yes it does. You seem to want to reverse the colormap. Matplotlib's convention is to append _r to the colormap name. In this case, seaborn is using the rocket colormap, rocket_r would be the reverse. Note that changing the ticks doesn't work the way you try it, as these are just numeric positions which will be sorted before they are applied.
      • If you want to show 0 and 1 in the colorbar (while the values in the heatmap are e.g. between 0.001 and 0.999, you could use vmin and vmax. E.g. sns.heatmap(..., vmin=0, vmax=1). vmin and vmax are one way to change the mapping between the values and the colors. By default, vmin=data.min() and vmax=data.max().
    • To show the colorbar outline: Add a black frame around a colorbar

    • ax.collections[0].colorbar is a colorbar, which in the latest versions also supports some functions to set ticks

    • ax.collections[0].colorbar.ax is an Axes object (a subplot). Matplotlib creates a small subplot on which the colorbar will be drawn. axs support a huge number of functions to change how the subplot looks or to add new elements. Note that a stackoverflow answer isn't meant to put of full matplotlib tutorial. The standard tutorials could be a starting point.