NeutronStar
NeutronStar

Reputation: 2157

How to fully customize subplot size

I want to have two subplots in a matplotlib figure that are sized and positioned relative to each other like the example below (for stylistic reasons). All the examples I've seen for customizing subplot placement and sizes still tile and fill the entire figure footprint. What can I do to get the rightmost plot positioned with some whitespace like below?

enter image description here

Upvotes: 2

Views: 2830

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339765

Imagine some (virtual) grid on which the subplots are placed.

enter image description here

The grid has 3 rows and 2 columns. The first subplot covers all three rows and the first column. The second subplot covers only the second row of the second column. The ratios between the row and column sizes are not necessarily equal.

import matplotlib.pyplot as plt
import matplotlib.gridspec

gs = matplotlib.gridspec.GridSpec(3,2, width_ratios=[1,1.4], 
                                       height_ratios=[1,3,1])

fig = plt.figure()
ax1 = fig.add_subplot(gs[:,0])
ax2 = fig.add_subplot(gs[1,1])

plt.show()

enter image description here

Additionally, you may set different values to the hspace and wspace parameters.

A good overview is given in the GridSpec tutorial.


Because it was mentionned in the comments: If absolute positionning in units of inches may be desired, I would recommend directly adding an axes in the desired size,

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
w,h = fig.get_size_inches()
div = np.array([w,h,w,h])

# define axes in by rectangle [left, bottom, width, height], numbers in inches
ax1 = fig.add_axes(np.array([.7, .7, 1.8, 3.4])/div)
ax2 = fig.add_axes(np.array([3, 1.4, 3, 2])/div)

plt.show()

Upvotes: 9

aorr
aorr

Reputation: 966

This answer is similar to this answer, but tacks on an approach for layout control in inches rather than fractional units.

It helps if you grid it out with gridspec, and then populate the grid using the desired spans of the ratios or columns. For a lot of the figures, I need them to fit on the page well, so I use this pattern to give me grid control down to a 10th of an inch.

import matplotlib.pyplot as plt
from matplotlib import gridspec

fig = plt.figure(figsize=(7, 5)) # 7 inches wide, 5 inches tall
row = int(fig.get_figheight() * 10)
col = int(fig.get_figwidth() * 10)
gsfig = gridspec.GridSpec(
    row, col, 
    left=0, right=1, bottom=0,
    top=1, wspace=0, hspace=0)

gs1 = gsfig[:, 0:30] 
# these spans are in tenths of an inch, so left-right 
# spans from col 0 to column 30 (or 3 inches)

ax1 = fig.add_subplot(gs1)

gs1 = gsfig[20:40, 35:70] # again these spans are in tenths of an inch
ax1 = fig.add_subplot(gs1)

gridspec layout with one-tenth inch grid

Upvotes: 1

Related Questions