Matplotlib mixed subplots with plot and pcolor(mesh) to have the same x axis length when colorbar is on

StackOverflow https://stackoverflow.com/questions/23477775

  •  15-07-2023
  •  | 
  •  

Question

I am wondering if it is possible to have a subplot with a mixture of graphs drawn with plot() and figures drawn with pcolormesh() that would have the same x axis length.

I attached 2 images one when the pcolormesh() subplot does not have the colorbar drawn when the x axes are the same length enter image description here and one that has the colorbar when the pcolormesh() subplot is shrunk so that it accommodates the colorbar. enter image description here

I would like to have the colorbar, but it should be extending the length of the whole plot and not shrink the subplot.

Is this possible without sub-classing any of the current classes?

Was it helpful?

Solution

Sure, it's possible!

What's happening is that a new axes is being created for the colorbar, and the space is being taken from the axes that pcolormesh is plotted in. If you don't want this to happen, you can specify an axes object for the colorbar to go in. Alternately, you could just use a horizontal colorbar.

At any rate, let's reproduce your problem with stand-alone data:

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1977)

# Generate some interesting-looking random data...
num = 200
grid = np.random.normal(0, 1, (20, num)).cumsum(axis=1).cumsum(axis=0)
x = np.linspace(0, 360, num)
y1 = np.random.normal(0, 1, num).cumsum()
y2 = np.random.normal(0, 1, num).cumsum()

# Plot on three seperate axes
fig, axes = plt.subplots(nrows=3, sharex=True)
axes[0].plot(x, y1)
axes[1].plot(x, y2)
im = axes[2].imshow(grid, extent=[0, 360, 0, 20], aspect='auto')
fig.colorbar(im)

plt.show()

enter image description here


A quick fix is to just use a horizontal colorbar:

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1977)

# Generate some interesting-looking random data...
num = 200
grid = np.random.normal(0, 1, (20, num)).cumsum(axis=1).cumsum(axis=0)
x = np.linspace(0, 360, num)
y1 = np.random.normal(0, 1, num).cumsum()
y2 = np.random.normal(0, 1, num).cumsum()

# Plot on three seperate axes
fig, axes = plt.subplots(nrows=3, sharex=True)
axes[0].plot(x, y1)
axes[1].plot(x, y2)
im = axes[2].imshow(grid, extent=[0, 360, 0, 20], aspect='auto')
fig.colorbar(im, orientation='horizontal')

plt.show()

enter image description here


Alternately, you can manually add another axes for the colorbar. We'll also adjust things a bit to make more room.

(Side note: Don't use tight_layout after making the extra axes. We're no longer working with a nice grid of subplots once we add the additional one, so tight_layout will not work correctly. It's safe to use it before, though you may want to modify the call to subplots_adjust in that case.)

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1977)

# Generate some interesting-looking random data...
num = 200
grid = np.random.normal(0, 1, (20, num)).cumsum(axis=1).cumsum(axis=0)
x = np.linspace(0, 360, num)
y1 = np.random.normal(0, 1, num).cumsum()
y2 = np.random.normal(0, 1, num).cumsum()

# Plot on three seperate axes
fig, axes = plt.subplots(nrows=3, sharex=True)
axes[0].plot(x, y1)
axes[1].plot(x, y2)
im = axes[2].imshow(grid, extent=[0, 360, 0, 20], aspect='auto')

# Make some room for the colorbar
fig.subplots_adjust(left=0.07, right=0.87)

# Add the colorbar outside...
box = axes[2].get_position()
pad, width = 0.02, 0.02
cax = fig.add_axes([box.xmax + pad, box.ymin, width, box.height])
fig.colorbar(im, cax=cax)

plt.show()

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top