Aligning x-axis with sharex using subplots and colorbar with matplotlib

matplotlib subplots
matplotlib subplot size ratio
matplotlib two plots same x axis
matplotlib subplot not aligned
matplotlib multiple axes
axessubplot
matplotlib subplot title
python subplot different x axis

I'm trying to create a set of subplots with a shared x axis using pyplot. This is all fine and dandy when the graphs are simple and all the x-axes align fine. However when I include a subplot that includes a colorbar, this compresses the width of that particular subplot to include the colorbar, resulting in the subplots no longer sharing the x-axis.

I've searched the web with no success with this. I've tried several different methods, but the simplest example I include below. I plot the exact same data in each subplot, but plot one with a colorbar. You can see the data no longer align along the x-axis.

Thanks in advance for your help!


import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
import pandas as pd

x = np.linspace(0, 10, num=100)
y = x ** 2 + 10 * np.random.randn(100)


f, (ax1, ax2) = plt.subplots(2,1,sharex=True,figsize=(8,12))

im1 = ax1.scatter(x, y, c=y, cmap='magma')
divider = make_axes_locatable(ax1)
cax = divider.append_axes("right", size="5%", pad=.05)

plt.colorbar(im1, cax=cax)

im2 = ax2.plot(x, y,'.')

plt.show()

This is one hacky way to do it.

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
import pandas as pd

x = np.linspace(0, 10, num=100)
y = x ** 2 + 10 * np.random.randn(100)


f, (ax1, ax2) = plt.subplots(2,1,sharex=True,figsize=(8,12))

im1 = ax1.scatter(x, y, c=y, cmap='magma')
divider = make_axes_locatable(ax1)
cax = divider.append_axes("right", size="5%", pad=.05)

plt.colorbar(im1, cax=cax)

im2 = ax2.plot(x, y,'.')
divider2 = make_axes_locatable(ax2)
cax2 = divider2.append_axes("right", size="5%", pad=.05)
cax2.remove()
plt.show()

results in

matplotlib.pyplot.subplots, When subplots have a shared x-axis along a column, only the x tick labels of the using the variable ax for single a Axes fig, ax = plt.subplots() # using the  'col': each subplot column will share an x- or y-axis. When subplots have a shared x-axis along a column, only the x tick labels of the bottom subplot are created. Similarly, when subplots have a shared y-axis along a row, only the y tick labels of the first column subplot are created. To later turn other subplots' ticklabels on, use tick_params.

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, num=100)
y = x ** 2 + 10 * np.random.randn(100)

f, (ax1, ax2) = plt.subplots(2,1,sharex=True,figsize=(8,12),
        constrained_layout=True)
im1 = ax1.scatter(x, y, c=y, cmap='magma')
f.colorbar(im1, ax=ax1)
im2 = ax2.plot(x, y,'.')

matplotlib.pyplot.subplots, When subplots have a shared x-axis along a column, only the x tick labels of axes, and accesses them through the returned array fig, axes = plt.subplots(2, 2, Align y-labels ../. Controlling the position and size of colorbars with Inset Axes. Minimal example: [x,y,z] = peaks(50); figure; subplot(5,1,1:4); pcolor(x,y,z); shading flat; colorbar; subplot(5,1,5); plot(x(end/2,:), z(end/2,:)); In this example I

You can account for the needed with of the colorbar already when you create the subplots. Instead of using the divider, generate four subplots with different widths using gridspec_kw. You can then delete the unneeded cax for the second subplot:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, num=100)
y = x ** 2 + 10 * np.random.randn(100)



##creating four subplots with unequally divided widths:
f, axes = plt.subplots(
    2,2, sharex='col', figsize=(8,12),
    gridspec_kw = {'width_ratios' : (10,1)},
)
ax1,ax2 = axes[:,0]

##remove unneeded Axes instance:
axes[1,1].remove()

im1 = ax1.scatter(x, y, c=y, cmap='magma')
plt.colorbar(im1, cax=axes[0,1])

im2 = ax2.plot(x, y,'.')

f.savefig('sharex_colorbar.png')

The result looks like this:

As an alternative to deleting the unneded subplot instances, you can also first generate the gridspec explicitly and generate only the needed subplots. This might be more suitable if you have many plots:

from matplotlib.gridspec import GridSpec
gs = GridSpec(nrows=2, ncols=2, width_ratios = (10,1))
f = plt.figure(figsize=(8,12))

ax1 = f.add_subplot(gs[0,0])
ax2 = f.add_subplot(gs[1,0],sharex=ax1)
cax = f.add_subplot(gs[0,1])

im1 = ax1.scatter(x, y, c=y, cmap='magma')
plt.colorbar(im1, cax=cax)

matplotlib.figure.Figure, Share the x or y axis with sharex and/or sharey. Align the ylabels of subplots in the same subplot column if label alignment is being done automatically (i.e. the  I'm trying to align multiple colorbars with subplots generated with either gridspec or fig.add_subplots. I'd like to add the colorbar with fig.add_axes in matplotlib (v2.02), because it allows detailed alignment control. However, I need to get the figure position in order to do the alignment.

Problems of using sharex options with lines plots and colormesh , The use of the colorbar, however, totally messed up the posit Paste your code here # # import matplotlib.pyplot as plt import numpy as np plt.close('all') fig,axes =plt.subplots(2,1,sharex=True) ax = axes[0] x = np.linspace(0, 100, 100) ax.plot(x ) data This breaks the alignment of the two Axes objects. Just place the colorbar in its own axis and use subplots_adjust to make room for it.. As a quick example: import numpy as np import matplotlib.pyplot as plt fig, axes = plt.subplots(nrows=2, ncols=2) for ax in axes.flat: im = ax.imshow(np.random.random((10,10)), vmin=0, vmax=1) fig.subplots_adjust(right=0.8) cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7]) fig.colorbar(im, cax=cbar_ax) plt.show()

Multiple Subplots, In this section we'll explore four routines for creating subplots in Matplotlib. 65 % of the height of the figure) and the x and y extents to 0.2 (that is, the size of the axes is Aligned columns or rows of subplots are a common-enough need that Note that by specifying sharex and sharey , we've automatically removed inner   However if for any reason, you need to share axes after they have been created (actually, using a different library which creates some subplots, like here, or sharing an inset axes might be a reason), there would still be a solution: Using . ax1.get_shared_x_axes().join(ax1, ax2) creates a link between the two axes, ax1 and ax2. In contrast to

4. Visualization with Matplotlib, In [ 4 ]: import numpy as np x = np . linspace ( 0 , 10 , 100 ) fig = plt . figure () plt . plot ( x For all Matplotlib plots, we start by creating a figure and an axes. The colorbar makes it clear that the black regions are “peaks,” while the red regions are “valleys.” In [ 6 ]: fig , ax = plt . subplots ( 2 , 3 , sharex = 'col' , sharey = 'row' ). You can use sharex or sharey to align the horizontal or vertical axis. fig , ( ax1 , ax2 ) = plt . subplots ( 2 , sharex = True ) fig . suptitle ( 'Aligning x-axis using sharex' ) ax1 . plot ( x , y ) ax2 . plot ( x + 1 , - y )

Comments
  • Possible duplicate of matplotlib sharex with colorbar not working
  • Possible duplicate of Align subplot with colorbar
  • I actually love the simplicity of this one, and I have more confidence that the measurements will be accurate.