Drawing Subplots with Complex Layouts in Python matplotlib
Overview
Essentially, grids of subplots can be drawn using plt.subplot(nrows, ncols, index)
or plt.subplots(nrows, ncols)
. This article introduces methods to draw more complex subplot arrangements. For methods on overlaying or truly drawing as one pleases, independent of a grid, see here.
Code
plt.subplot(nrows, ncols, index)
Using plt.subplot
, placing a tuple instead of an integer in the index
position allows for spanning the drawing over multiple grids. The frustrating part here is that index
is neither indexing nor slicing. Thus, the index starts from $1$, not from $0$ (since it’s not Python indexing). Additionally, since it’s not slicing but a tuple, (3,4)
honestly means the subplot from the third to the fourth. An example code arranging three figures, two on the top row and one on the bottom row, is as follows.
import matplotlib.pyplot as plt
import numpy as np
plt.subplot(2, 2, 1) # 좌상단에 막대그래프 그리기
plt.bar(np.arange(10), np.random.randn(10))
plt.subplot(2, 2, 2) # 우상단에 산점도 그리기
plt.scatter(np.random.randn(10), np.random.randn(10))
plt.subplot(2, 2, (3,4)) # 하단에 선그래프 그리기
plt.plot(np.random.randn(10))
plt.show()
gridspec
Using gridspec
allows for actual indexing and slicing, making it more convenient and intuitively compatible with other codes. Code that draws exactly the same figure as above is,
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
gs = gridspec.GridSpec(2, 2) # 그리드스펙 생성
plt.subplot(gs[0]) # 좌상단에 막대그래프 그리기
plt.bar(np.arange(10), np.random.randn(10))
plt.subplot(gs[1]) # 우상단에 산점도 그리기
plt.scatter(np.random.randn(10), np.random.randn(10))
plt.subplot(gs[2:]) # 하단에 선그래프 그리기
plt.plot(np.random.randn(10))
plt.show()
Recipes
Adjusting Horizontal Ratio
gs = gridspec.GridSpec(2, 2, width_ratios=[1,3]) # 그리드스펙 생성, 가로 비율 1:3
plt.subplot(gs[0]) # 좌상단에 막대그래프 그리기
plt.bar(np.arange(10), np.random.randn(10))
plt.subplot(gs[1]) # 우상단에 산점도 그리기
plt.scatter(np.random.randn(10), np.random.randn(10))
plt.subplot(gs[2:]) # 하단에 선그래프 그리기
plt.plot(np.random.randn(10))
Adjusting Vertical Ratio
gs = gridspec.GridSpec(2, 2, height_ratios=[1,2]) # 그리드스펙 생성, 세로 비율 1:2
plt.subplot(gs[0]) # 좌상단에 막대그래프 그리기
plt.bar(np.arange(10), np.random.randn(10))
plt.subplot(gs[1]) # 우상단에 산점도 그리기
plt.scatter(np.random.randn(10), np.random.randn(10))
plt.subplot(gs[2:]) # 하단에 선그래프 그리기
plt.plot(np.random.randn(10))
Layout in the Form of $_{\thinspace \thinspace \square}^{\square \square}$
gs = gridspec.GridSpec(2, 4) # 그리드스펙 생성
plt.subplot(gs[0:2]) # 좌상단에 막대그래프 그리기
plt.bar(np.arange(10), np.random.randn(10))
plt.subplot(gs[2:4]) # 우상단에 산점도 그리기
plt.scatter(np.random.randn(10), np.random.randn(10))
plt.subplot(gs[5:7]) # 하단에 선그래프 그리기
plt.plot(np.random.randn(10))
plt.subplots_adjust(wspace=1)
Environment
- OS: Windows11
- Version: Python 3.9.13, matplotlib==3.6.2, numpy==1.23.5