파이썬 matplotlib에서 복잡한 레이아웃의 서브플랏 그리는 방법
개요
기본적으로 plt.subplot(nrows, ncols, index)
이나 plt.subplots(nrows, ncols)
로 격자 형태의 서브플랏을 그릴 수 있다. 본 글에서는 조금 더 복잡한 형태의 서브플랏을 그리는 방법을 소개한다. 격자에 의존하지 않고 겹쳐그리거나 진짜 내 마음대로 그리는 방법은 여기을 참고하라.
코드
plt.subplot(nrows, ncols, index)
plt.subplot
을 쓰는데, index
자리에 정수가 아니라 tuple을 넣으면 여러 격자에 걸쳐서 그림을 그릴 수 있다. 개열받는 점은 여기서 index
가 인덱싱도 슬라이싱도 아니라는 점이다. 따라서 (파이썬 인덱싱이 아니므로) 인덱스는 $0$이 아닌 $1$부터 시작한다. 또한 슬라이싱이 아니라 튜플이기 때문에 (3,4)
는 정직하게 세번째부터 네번째까지의 subplot을 의미한다. 예시로 세 장의 그림을 윗줄에는 2장, 아랫줄에는 1장으로 배치하는 코드는 아래와 같다.
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
gridspec
를 쓰면 위와는 달리 실제로 인덱싱과 슬라이싱을 사용할 수 있기 때문에 좀 더 편하며, 다른 코드들과도 직관적으로 잘 어울리게 코딩할 수 있다. 위와 정확히 같은 그림을 그리는 코드는,
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()
레시피
가로 비율 조절
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))
세로 비율 조절
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))
$_{\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)
환경
- OS: Windows11
- Version: Python 3.9.13, matplotlib==3.6.2, numpy==1.23.5