Matplotlib을 활용한 고급 그래프 레이아웃 기법

그래프 객체 설정

Matplotlib에서 그래프의 기본 크기는 6.4×4.8인치이며, 이는 약 16.3cm × 12.2cm에 해당합니다. plt.figure(figsize=(width, height))를 사용하면 원하는 크기로 캔버스를 생성할 수 있습니다. 여기서 figsize는 인치 단위의 튜플로 지정합니다.

해상도 조절

기본 해상도(dpi)는 100으로 설정되어 있으며, 이를 변경하려면 다음 코드를 사용할 수 있습니다:

import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 300

또는 저장 시점에 별도로 DPI를 지정할 수도 있습니다:

plt.savefig('output.png', dpi=300)

Seaborn을 사용 중이라면 아래와 같이 전역 설정을 조정할 수 있습니다:

import seaborn as sns
sns.set(rc={'figure.dpi': 300, 'savefig.dpi': 300})

여백 설정

그래프 주변 여백(subplot margins)은 상대값(0~1)으로 정의되며, 전체 영역 대비 비율을 의미합니다. 기본값은 다음과 같습니다:

  • 왼쪽: 0.125
  • 오른쪽: 0.9
  • 상단: 0.88
  • 하단: 0.11

좌표계 기준 (0,0)은 왼쪽 하단, (1,1)은 오른쪽 상단을 나타냅니다. 이를 조정하여 축 레이블이나 제목이 잘리는 것을 방지할 수 있습니다.

subplot() 함수로 그리드 배치

간단한 그리드 형식의 서브플롯을 만들 때 plt.subplot()이 자주 사용됩니다. 문법은 다음과 같습니다:

plt.subplot(nrows, ncols, index)

예를 들어 plt.subplot(2, 3, 1)은 2행 3열 그리드에서 첫 번째 위치에 플롯을 생성합니다. 이 함수는 현재 활성화된 Figure에 자동으로 서브플롯을 추가합니다.

참고 사항: plt.plot()은 상태 기반 인터페이스로 간편하지만, 복잡한 레이아웃에서는 객체 기반인 ax.plot() 사용이 권장됩니다. 후자는 명시적으로 Axes 객체를 조작하므로 재사용성과 제어력이 뛰어납니다.

add_subplot() 메서드 활용

Figure 인스턴스를 직접 다룰 경우 add_subplot()을 사용합니다:

fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)

각 호출은 새로운 Axes 객체를 반환하며, 이를 통해 개별적인 스타일링과 데이터 매핑이 가능합니다. 이 방법은 여러 개의 독립된 그래프를 세밀하게 구성할 때 유리합니다.

subplots()로 멀티플롯 생성

여러 서브플롯을 한 번에 생성하고 싶을 때는 plt.subplots()가 효율적입니다:

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

이 함수는 Figure 객체와 Axes 배열을 튜플 형태로 반환합니다. axes[i, j]를 통해 특정 위치의 플롯에 접근할 수 있습니다.

다음 예제는 극좌표계를 직교좌표계로 변환하여 시각화하는 코드입니다:

import numpy as np
import matplotlib.pyplot as plt

# 설정 초기화
plt.rcParams.update({
    'font.size': 14,
    'axes.grid': True,
    'grid.color': '0.3',
    'grid.linewidth': 0.5,
    'xtick.minor.visible': True,
    'ytick.minor.visible': True,
    'figure.subplot.left': 0.15,
    'figure.subplot.right': 0.95,
    'figure.subplot.top': 0.95,
    'figure.subplot.bottom': 0.1
})

# 데이터 생성
theta = np.linspace(0, 2*np.pi, 120)
x = np.cos(theta)
y = np.sin(theta)

# 색상 배열 생성 (HSL 기반)
colors = plt.cm.hsv(np.linspace(0, 1, len(x)))

# 그래프 생성
fig, ax = plt.subplots(figsize=(6, 6))
ax.plot(x, y, color='black', lw=0.25, zorder=1)
ax.scatter(x, y, c=colors, s=88, marker='.', edgecolor='white', zorder=2)
ax.axhline(0, color='k', linewidth=0.8, zorder=1)
ax.axvline(0, color='k', linewidth=0.8, zorder=1)

# 축 설정
ax.set_xlim(-1.25, 1.25)
ax.set_ylim(-1.25, 1.25)
ax.set_aspect('equal')
ax.set_xlabel(r'$x = \cos(\theta)$', fontfamily='serif', fontsize=16)
ax.set_ylabel(r'$y = \sin(\theta)$', fontfamily='serif', fontsize=16)

plt.savefig('unit_circle.png', dpi=300, bbox_inches='tight')

결과는 중심이 원점인 단위원으로, 각 점이 HSV 색상 공간을 따라 순환하는 색상을 가집니다.

GridSpec으로 정교한 레이아웃 구성

복잡한 배치가 필요할 경우 GridSpec을 사용하면 행과 열의 비율, 병합 등을 자유롭게 조절할 수 있습니다:

from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(8, 6))
gs = GridSpec(4, 4, figure=fig, hspace=0.3, wspace=0.3)

# 주요 플롯 (2x2 크기 차지)
ax_main = fig.add_subplot(gs[0:2, 0:2])
ax_main.plot(np.random.randn(100).cumsum())

# 우측 상단 작은 플롯
ax_top_right = fig.add_subplot(gs[0, 2])
ax_top_right.hist(np.random.randn(50), bins=10, orientation='horizontal')

# 좌측 하단 밀집 플롯
ax_bottom_left = fig.add_subplot(gs[2, 0])
ax_bottom_left.scatter(np.random.randn(30), np.random.randn(30))

# 하단 우측 확대 플롯
ax_large = fig.add_subplot(gs[2:, 1:])
ax_large.imshow(np.random.rand(10, 10), cmap='Blues')

이 방식은 다양한 크기의 서브플롯을 조합할 때 매우 유용합니다.

add_gridspec()로 동적 그리드 생성

Figure 인스턴스 내에서 add_gridspec()을 사용하면 보다 유연한 그리드를 구성할 수 있습니다:

fig = plt.figure(figsize=(9, 6))
gs = fig.add_gridspec(3, 3, width_ratios=[2, 1, 1], height_ratios=[1, 2, 1])

ax1 = fig.add_subplot(gs[0, :])        # 첫 번째 행 전체 차지
ax2 = fig.add_subplot(gs[1, 0])          # 두 번째 행 첫 번째 열
ax3 = fig.add_subplot(gs[1, 1:])        # 두 번째 행 오른쪽 두 열 병합
ax4 = fig.add_subplot(gs[2, :], projection='polar')  # 극좌표 플롯

또한 SubplotSpec을 활용해 중첩 그리드도 구현 가능하며, 특히 대시보드 형태의 시각화에 적합합니다.

태그: matplotlib python Data Visualization gridspec subplot

7월 23일 06:24에 게시됨