Matplotlib - 4. 고급 사용법

2025. 1. 21. 12:16프로그래밍 (확장)/Python-Matplotlib

Matplotlib은 기본적인 그래프 생성뿐만 아니라 고급 기능을 활용하여 시각화를 더욱 정교하고 유연하게 만들 수 있습니다. 이 섹션에서는 서브플롯, 다중 축, 스타일 변경, 애니메이션 생성, 사용자 정의 틱 포매터, 그리고 이미지 처리와 관련된 고급 사용법을 다룹니다.


4.1 서브플롯과 레이아웃

plt.subplot()과 plt.subplots()

plt.subplot()

plt.subplot()은 하나의 Figure에 여러 그래프를 배치할 때 사용됩니다.

예제:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y1 = [10, 20, 30, 40]
y2 = [40, 30, 20, 10]

plt.subplot(2, 1, 1)  # 2행 1열에서 첫 번째 위치
plt.plot(x, y1, label="Dataset 1")
plt.title("First Plot")
plt.legend()

plt.subplot(2, 1, 2)  # 2행 1열에서 두 번째 위치
plt.plot(x, y2, label="Dataset 2", color="red")
plt.title("Second Plot")
plt.legend()

plt.tight_layout()  # 여백 자동 조정
plt.show()

plt.subplots()

plt.subplots()은 Figure와 Axes 객체를 반환하여 서브플롯을 보다 유연하게 제어할 수 있습니다.

예제:

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

axes[0, 0].plot(x, y1, color="blue")
axes[0, 0].set_title("Top Left")

axes[0, 1].plot(x, y2, color="red")
axes[0, 1].set_title("Top Right")

axes[1, 0].bar(x, y1, color="green")
axes[1, 0].set_title("Bottom Left")

axes[1, 1].scatter(x, y2, color="purple")
axes[1, 1].set_title("Bottom Right")

plt.tight_layout()  # 간격 자동 조정
plt.show()

GridSpec을 활용한 레이아웃 조정

GridSpec은 서브플롯의 크기와 위치를 정교하게 조정할 수 있습니다.

예제:

from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(8, 6))
gs = GridSpec(3, 3, figure=fig, wspace=0.3, hspace=0.5)  # 간격 조정

ax1 = fig.add_subplot(gs[0, :])  # 첫 행 전체
ax2 = fig.add_subplot(gs[1, :-1])  # 두 번째 행 첫 두 열
ax3 = fig.add_subplot(gs[1:, -1])  # 마지막 열
ax4 = fig.add_subplot(gs[-1, 0])  # 마지막 행 첫 번째 열
ax5 = fig.add_subplot(gs[-1, 1])  # 마지막 행 두 번째 열

ax1.plot(x, y1, color="blue")
ax2.bar(x, y2, color="orange")
ax3.scatter(x, y1, color="green")
ax4.plot(x, y2, linestyle="--", color="purple")
ax5.plot(x, y1, linestyle=":", color="red")

plt.tight_layout()
plt.show()

4.2 다중 축(Axes)

twinx()를 사용한 서로 다른 축 스케일

하나의 그래프에서 두 개의 y축을 사용하여 서로 다른 스케일의 데이터를 비교할 수 있습니다.

예제:

x = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
y2 = [1, 4, 9, 16, 25]

fig, ax1 = plt.subplots()

ax1.plot(x, y1, color="blue", label="Primary Axis")
ax1.set_ylabel("Primary Axis", color="blue")
ax1.tick_params(axis="y", labelcolor="blue")

ax2 = ax1.twinx()  # 두 번째 y축 생성
ax2.plot(x, y2, color="red", linestyle="--", label="Secondary Axis")
ax2.set_ylabel("Secondary Axis", color="red")
ax2.tick_params(axis="y", labelcolor="red")

lines_1, labels_1 = ax1.get_legend_handles_labels()
lines_2, labels_2 = ax2.get_legend_handles_labels()
ax1.legend(lines_1 + lines_2, labels_1 + labels_2, loc="upper left")  # 범례 통합

plt.title("Dual Axis Example")
plt.tight_layout()
plt.show()

4.3 스타일 변경

Matplotlib 스타일 시트 사용

스타일 시트를 사용하여 그래프의 전체적인 디자인을 변경할 수 있습니다.

사용 가능한 스타일 확인:

print(plt.style.available)

예제:

plt.style.use("ggplot")  # ggplot 스타일 적용

x = [1, 2, 3, 4]
y = [10, 15, 20, 25]

plt.plot(x, y, label="Sample Data")
plt.title("Styled Plot")
plt.legend()
plt.show()

4.4 애니메이션

FuncAnimation을 사용한 애니메이션 생성 및 저장

FuncAnimation은 동적인 데이터 변화를 시각화할 때 사용됩니다. 생성된 애니메이션은 MP4 또는 GIF 파일로 저장할 수 있습니다.

예제:

import numpy as np
from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots()
x, y = [], []
line, = ax.plot([], [], lw=2)

# 초기화 함수
def init():
    ax.set_xlim(0, 10)
    ax.set_ylim(-1, 1)
    return line,

# 업데이트 함수
def update(frame):
    x.append(frame)
    y.append(np.sin(frame))
    line.set_data(x, y)
    return line,

ani = FuncAnimation(fig, update, frames=np.linspace(0, 10, 100), init_func=init, blit=True)
ani.save("sine_wave_animation.mp4", writer="ffmpeg")  # 애니메이션 저장
plt.show()

4.5 사용자 정의 틱(tick) 포매터

FuncFormatter로 축 눈금 포맷 변경

축 눈금을 사용자 정의 형식으로 표시할 수 있습니다.

예제:

from matplotlib.ticker import FuncFormatter

x = [1, 2, 3, 4, 5]
y = [10, 20, 30, 40, 50]

fig, ax = plt.subplots()
ax.plot(x, y)

# 사용자 정의 포매터 함수
def currency(x, pos):
    return f"${x:,.0f}"

ax.yaxis.set_major_formatter(FuncFormatter(currency))
plt.title("Custom Tick Formatter Example")
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
plt.show()

4.6 이미지 처리

plt.imshow()를 사용한 이미지 시각화와 변환

이미지 데이터를 시각화하거나 필터를 적용하여 처리할 수 있습니다.

예제:

import numpy as np
from scipy.ndimage import gaussian_filter

# 임의의 이미지 데이터 생성
image_data = np.random.rand(100, 100)
smoothed_data = gaussian_filter(image_data, sigma=2)  # 가우시안 블러 적용

plt.subplot(1, 2, 1)
plt.imshow(image_data, cmap="viridis", interpolation="nearest")
plt.title("Original Image")

plt.subplot(1, 2, 2)
plt.imshow(smoothed_data, cmap="viridis", interpolation="nearest")
plt.title("Smoothed Image")

plt.colorbar(label="Intensity", ax=plt.gca())
plt.tight_layout()
plt.show()