Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force same size between matplotlib subplot image axes

Suppose I have the following code to create three side-by-side images:

    n=10
    x = np.random.rand(n,1)
    y = np.random.rand(1,n)
    z = np.random.rand(n,n)

    fig, ax = plt.subplots(1, 3)
    ax[0].imshow(x)
    ax[1].imshow(z)
    ax[2].imshow(y)

However, the axes autoscale so that the vertical axis in the first image is larger than the vertical axis in the second.

enter image description here

Is there a way to programmatically force all image dimensions of size n to look the same in the three plots, regardless of window size? I'm looking for a way to either link the axes or the images so that the vertical axis of the first plot is the same size as the vertical axis of the second plot, and the horizontal axis of the third plot is the same size as the horizontal axis of the second plot, regardless of window size. i.e. something like this: enter image description here

like image 321
dkv Avatar asked May 11 '18 18:05

dkv


People also ask

How do I make all the subplots the same size in Matplotlib?

To change the size of subplots in Matplotlib, use the plt. subplots() method with the figsize parameter (e.g., figsize=(8,6) ) to specify one size for all subplots — unit in inches — and the gridspec_kw parameter (e.g., gridspec_kw={'width_ratios': [2, 1]} ) to specify individual sizes.

How do I reduce the gap between subplots?

We can use the plt. subplots_adjust() method to change the space between Matplotlib subplots. The parameters wspace and hspace specify the space reserved between Matplotlib subplots. They are the fractions of axis width and height, respectively.

How can you plot subplots with different sizes?

Create Different Subplot Sizes in Matplotlib using Gridspec The GridSpec from the gridspec module is used to adjust the geometry of the Subplot grid. We can use different parameters to adjust the shape, size, and number of columns and rows.


1 Answers

I think one easiest way is to use aspect='auto' with ax[1].imshow(z). But this will distort the image in a way that may be not the same as what you've shown in the question. And it may not work for cases where there is no single n. I'm not sure if I got you 100%, but let me try this method. The key idea here are:

  1. Change the aspect ratio of your fig. The exact ratio comes from both your image data and your subplot layout.
  2. Use tight layout to eliminate unnecessary between axes which may offset your graph a little bit.

Here is my example code and figure:

import matplotlib.pyplot as plt
from matplotlib.figure import figaspect
import numpy as np

n = 10
x = np.random.rand(n,1)
y = np.random.rand(1,n)
z = np.random.rand(n,n)

width_max = max(s.shape[0] for s in [x, y, z])
height_max = max(s.shape[1] for s in [x, y, z])

row = 1
col = 3
fig, ax = plt.subplots(row, col)
w, h = figaspect(row*width_max/(col*height_max))
fig.set_size_inches(w, h)

ax[0].imshow(x)
ax[1].imshow(z)
ax[2].imshow(y)

plt.tight_layout()
plt.show()

enter image description here

I hope this solves your real problem. I think this also works for a case like:

x = np.random.rand(3,1)
y = np.random.rand(1,10)
z = np.random.rand(7,6)
like image 97
Y. Luo Avatar answered Oct 28 '22 02:10

Y. Luo