Positioning the colorbar
Edit: Updated for matplotlib
version >= 3.
Three great ways to do this have already been shared in this answer.
The matplotlib documentation advises to use inset_locator
. This would work as follows:
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import numpy as np
rng = np.random.default_rng(1)
fig, ax = plt.subplots(figsize=(4,4))
im = ax.imshow(rng.random((11, 16)))
ax.set_xlabel("x label")
axins = inset_axes(ax,
width="100%",
height="5%",
loc='lower center',
borderpad=-5
)
fig.colorbar(im, cax=axins, orientation="horizontal")
How to shift the colorbar position to right in matplotlib?
Use the pad
attribute.
cbar = plt.colorbar(sc, shrink=0.9, pad = 0.05)
The documentation of make_axes() describes how to use pad
: "pad: 0.05 if vertical, 0.15 if horizontal; fraction of original axes between colorbar and new image axes".
Relocate colorbar
You have to add additional axes (add_axes) to put your colorbar at the desired position:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D, get_test_data
from matplotlib import cm
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
# set up a figure twice as wide as it is tall
fig = plt.figure(figsize=plt.figaspect(0.5))
#===============
# First subplot
#===============
# set up the axes for the first plot
ax = fig.add_subplot(1, 2, 1, projection='3d')
# plot a 3D surface like in the example mplot3d/surface3d_demo
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)
# position of colorbar
# where arg is [left, bottom, width, height]
cax = fig.add_axes([0.15, .87, 0.35, 0.03])
fig.colorbar(surf, orientation='horizontal', cax=cax)
plt.show()
Matplotlib colorbar background and label placement
To your second question: you can use a negative labelpad
value to move the label back towards the ticklabels, like this:
import numpy as np
import matplotlib.pyplot as plt
data = np.linspace(0, 10, num=256).reshape(16,16)
cf = plt.contourf(data, levels=(0, 2.5, 5, 7.5, 10))
cb = plt.colorbar(cf)
cb.set_ticklabels([r'$<10^{0}$', 1, 2, r'$10^{14}$', r'$10^{14}+12345678$'])
cb.set_label(r'$n_e$ in $m^{-3}$', labelpad=-40, y=0.45)
plt.show()
Using the parameter y
, you can additionally move the label up or down for better symmetry.
The argument of labelpad
is given in points (1/72 inch). y
accepts values in [0, 1]
, 0.0
is the lower border and 1.0
the upper.
The result:
Adjust matplotlib colorbar position
Two things:
- The
yshift
you use is rather small, so an effect my not be directly obvious. - Calling
plt.tight_layout()
rearranges the axes, and thus overwrites the position you have set.
So you would probably want to first call plt.tight_layout()
and afterwards change the position.
How to control colorbar position when using subplots in Matplotlib
The reason this happens is that plt.colorbar
creates a new Axes
object, which "steals" space from the lower Axes
(this is the reason making a horizontal colourbar also affects the two original plots).
There are a few ways to work around this; one is to create a Figure
with four Axes
, allocate most of the space to the left ones, and just make one invisible:
import numpy as np
import matplotlib.pyplot as plt
import scipy.signal as scignal
import random
array = np.random.random(10000)
t, f, Sxx = scignal.spectrogram(array,fs=100)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(5, 6), gridspec_kw={'width_ratios': [19, 1]})
(ax1, blank), (ax2, ax_cb) = axes
blank.set_visible(False)
ax1.plot(array)
m = ax2.pcolormesh(Sxx)
fig.colorbar(m, cax=ax_cb)
Position colorbar inside figure
One may use a mpl_toolkits.axes_grid1.inset_locator.inset_axes
to place an axes inside another axes. This axes can be used to host the colorbar. Its position is relative the the parent axes, similar to how legends are placed, using a loc
argument (e.g. loc=3
means lower left). Its width and height can be specified in absolute numbers (inches) or relative to the parent axes (percentage).
cbaxes = inset_axes(ax1, width="30%", height="3%", loc=3)
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.gridspec as gridspec
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
x = np.random.randn(60)
y = np.random.randn(60)
z = [np.random.random() for _ in range(60)]
fig = plt.figure()
gs = gridspec.GridSpec(1, 2)
ax0 = plt.subplot(gs[0, 0])
plt.scatter(x, y, s=20)
ax1 = plt.subplot(gs[0, 1])
cm = plt.cm.get_cmap('RdYlBu_r')
plt.scatter(x, y, s=20 ,c=z, cmap=cm)
fig.tight_layout()
cbaxes = inset_axes(ax1, width="30%", height="3%", loc=3)
plt.colorbar(cax=cbaxes, ticks=[0.,1], orientation='horizontal')
plt.show()
Note that in order to suppress the warning, one might simply call tight_layout
prior to adding the inset axes.
Related Topics
Ruby Equivalent to Python's Help()
Is There a Function That Checks If a Character in a String Is a Letter in the Alphabet? (Swift)
Function Which Returns the Least-Squares Solution to a Linear Matrix Equation
Extract Column Value Based on Another Column Pandas Dataframe
How to Add Title to Subplots in Matplotlib
Create Dynamic Urls in Flask with Url_For()
How to Import CSV Data into Django Models
Which of These Scripting Languages Is More Appropriate for Pen-Testing
Is There Something Like Bpython for Ruby
Learning Ruby from Python; Differences and Similarities
If Monkey Patching Is Permitted in Both Ruby and Python, Why Is It More Controversial in Ruby
Programmatically Extract Data from an Excel Spreadsheet
What Programming Language Features Are Well Suited for Developing a Live Coding Framework
Variable Assignment and Modification (In Python)
Beautifulsoup Not Grabbing Dynamic Content
Displaying Subprocess Output to Stdout and Redirecting It
What Is a "Good" Palette for Divergent Colors in R? (Or: Can Viridis and Magma Be Combined Together)