Skip to main content

Matplotlib 서브플롯

하나의 Figure 안에 여러 차트를 배치하면 데이터의 다양한 측면을 한눈에 비교할 수 있습니다. plt.subplots()로 균등 분할하거나, GridSpec으로 자유로운 레이아웃을 만들 수 있습니다.

학습 목표

  • plt.subplots로 격자 형태의 서브플롯을 생성할 수 있다
  • GridSpec으로 불균등한 레이아웃을 구성할 수 있다
  • 여러 차트를 조합한 복합 대시보드를 만들 수 있다
  • 고해상도 이미지로 저장할 수 있다

왜 중요한가

EDA에서는 여러 피처의 분포를 동시에 비교하거나, 같은 데이터를 다른 관점(시간별 추이, 분포, 상관관계)에서 한 번에 보여줘야 하는 경우가 많습니다. 복합 차트 구성 능력은 분석 보고서의 품질을 결정합니다.

기본 서브플롯

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(2, 2, figsize=(10, 8))

# 각 서브플롯에 다른 차트
np.random.seed(42)
data = np.random.randn(1000)

axes[0, 0].hist(data, bins=30, color='#4a9eca')
axes[0, 0].set_title('히스토그램')

axes[0, 1].boxplot(data)
axes[0, 1].set_title('박스플롯')

axes[1, 0].plot(np.cumsum(data), color='#4a9e4a')
axes[1, 0].set_title('누적합')

axes[1, 1].scatter(data[:100], data[:100]**2, alpha=0.5, color='#e6a23c')
axes[1, 1].set_title('산점도')

plt.suptitle('데이터 탐색 대시보드', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()

GridSpec

from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(12, 8))
gs = GridSpec(2, 3, figure=fig)

# 첫 행: 큰 차트 하나 + 작은 차트 하나
ax1 = fig.add_subplot(gs[0, :2])  # 첫 행, 0~1열 (넓은 영역)
ax2 = fig.add_subplot(gs[0, 2])   # 첫 행, 2열

# 둘째 행: 3등분
ax3 = fig.add_subplot(gs[1, 0])
ax4 = fig.add_subplot(gs[1, 1])
ax5 = fig.add_subplot(gs[1, 2])

# 차트 그리기
np.random.seed(42)
x = np.linspace(0, 10, 100)
ax1.plot(x, np.sin(x), label='sin', color='#4a9eca')
ax1.plot(x, np.cos(x), label='cos', color='#e6a23c')
ax1.legend()
ax1.set_title('삼각함수 (넓은 영역)')

ax2.bar(['A', 'B', 'C'], [30, 45, 25], color='#4a9e4a')
ax2.set_title('카테고리')

for ax, title in zip([ax3, ax4, ax5], ['분포1', '분포2', '분포3']):
    ax.hist(np.random.randn(500), bins=20, alpha=0.7)
    ax.set_title(title)

plt.tight_layout()
plt.show()

축 공유

# x축 또는 y축 공유
fig, axes = plt.subplots(1, 3, figsize=(12, 4), sharey=True)

for ax, (name, size) in zip(axes, [('A', 500), ('B', 800), ('C', 300)]):
    data = np.random.normal(0, 1, size)
    ax.hist(data, bins=25, alpha=0.7, color='#4a9eca')
    ax.set_title(f'그룹 {name} (n={size})')

axes[0].set_ylabel('빈도')
plt.suptitle('그룹별 분포 비교 (y축 공유)')
plt.tight_layout()
plt.show()

이미지 저장

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot([1, 2, 3], [1, 4, 9])
ax.set_title('결과 차트')

# PNG (래스터)
fig.savefig('result.png', dpi=300, bbox_inches='tight', facecolor='white')

# PDF (벡터 — 논문용)
fig.savefig('result.pdf', bbox_inches='tight')

# SVG (벡터 — 웹용)
fig.savefig('result.svg', bbox_inches='tight')

AI/ML에서의 활용

  • 피처 탐색: 여러 피처의 분포를 서브플롯으로 한 번에 비교합니다
  • 모델 평가: 혼동행렬, ROC 곡선, PR 곡선을 하나의 Figure에 배치합니다
  • 실험 보고서: GridSpec으로 분석 결과를 깔끔한 레이아웃으로 정리합니다
tight_layout()은 사후 조정, constrained_layout=True(Figure 생성 시)는 자동 조정입니다. GridSpec을 많이 사용한다면 constrained_layout이 더 안정적입니다.

체크리스트

  • plt.subplots로 격자 서브플롯을 생성할 수 있다
  • GridSpec으로 자유로운 레이아웃을 구성할 수 있다
  • sharey/sharex로 축을 공유할 수 있다
  • 고해상도(dpi=300) PNG, PDF, SVG로 저장할 수 있다

다음 문서