Matplotlib + Seaborn + Plotly 조합 전략
발표가 끝난 직후, 민서와 선배는 강의실 복도에서 잠깐 이야기를 나눴습니다. 교수님께서 시각화 자료가 특히 인상적이었다고 칭찬해주셨습니다.
"근데 선배, 발표 중에 '이 그래프를 마우스로 클릭할 수 있으면 좋겠다' 싶었어요. Seaborn은 정적이잖아요."
선배가 고개를 끄덕였습니다. "맞아. 그게 Seaborn의 한계이기도 해. 그래서 Plotly를 알아야 해."
세 도구의 포지셔닝
파이썬 시각화 생태계의 세 축을 이해하는 것이 중요합니다.
Matplotlib: 완전한 자유, 세밀한 제어
Matplotlib은 파이썬 시각화의 근간입니다. Seaborn과 Plotly 모두 내부적으로 Matplotlib 위에 올라가거나 영향을 받았습니다. 픽셀 하나까지 직접 제어할 수 있고, 논문이나 출판물처럼 정확한 레이아웃이 필요할 때 빛을 발합니다. 대신 기본 코드양이 많고, 통계 시각화를 만들 때는 직접 계산 로직을 추가해야 합니다.
Seaborn: 통계 시각화, 빠른 탐색
Seaborn은 "통계 시각화를 위한 Matplotlib 래퍼"입니다. barplot, boxplot, violinplot, heatmap 같은 통계 그래프를 단 몇 줄로 만들 수 있습니다. Pandas DataFrame과 자연스럽게 연동되고, 기본 스타일이 아름답습니다. 탐색적 데이터 분석(EDA) 단계에서 가장 생산적인 도구입니다. 단, 결과물은 정적 이미지입니다.
Plotly: 인터랙티브, 웹 대시보드
Plotly는 브라우저에서 동작하는 인터랙티브 차트를 만듭니다. 마우스 호버로 데이터 값 확인, 줌인/줌아웃, 특정 계열 숨기기 등이 가능합니다. Plotly Express를 사용하면 Seaborn처럼 간결한 코드로 인터랙티브 차트를 만들 수 있습니다. 웹 대시보드(Dash)와 결합하면 실시간 데이터 시각화 앱도 만들 수 있습니다.
상황별 선택 가이드
| 상황 | 추천 도구 | 이유 |
|---|---|---|
| 탐색적 데이터 분석(EDA) | Seaborn | 빠른 시각화, 통계 자동 계산 |
| 논문/학술 보고서 그래프 | Matplotlib + Seaborn | 세밀한 제어, 고해상도 출력 |
| 발표용 인터랙티브 차트 | Plotly | 청중이 직접 탐색 가능 |
| 웹 대시보드 | Plotly + Dash | 실시간 업데이트, 웹 배포 |
| 세밀한 커스터마이징 | Matplotlib | 완전한 자유도 |
| 빠른 프로토타입 | Seaborn 또는 Plotly Express | 코드량 최소화 |
Plotly Express 맛보기
Seaborn과 Plotly Express의 인터페이스는 놀랍도록 비슷합니다. 아래 코드를 실행하려면 pip install plotly로 Plotly를 먼저 설치해야 합니다.
import seaborn as snsimport plotly.express as pximport pandas as pdtips = sns.load_dataset("tips")# Seaborn 방식import matplotlib.pyplot as pltfig_sns, ax = plt.subplots(figsize=(8, 5))sns.scatterplot(data=tips, x="total_bill", y="tip", hue="sex", ax=ax)ax.set_title("Seaborn: 정적 차트")plt.tight_layout()plt.savefig("seaborn_scatter.png", dpi=100)plt.show()# Plotly Express 방식 (인터랙티브)fig_px = px.scatter( tips, x="total_bill", y="tip", color="sex", title="Plotly: 인터랙티브 차트 (마우스 올려보기)", labels={"total_bill": "Total Bill ($)", "tip": "Tip ($)"})fig_px.show()# fig_px.write_html("plotly_scatter.html") # HTML로 저장 가능
두 코드의 구조가 거의 동일하다는 것을 알 수 있습니다. data=, x=, y=, color=(hue에 해당). Seaborn을 마스터했다면 Plotly Express로 넘어가는 데 하루면 충분합니다.
조합 예제: EDA → 최종 발표 워크플로우
실제 프로젝트에서는 세 도구를 단계별로 조합합니다.
import seaborn as snsimport matplotlib.pyplot as pltimport matplotlib.gridspec as gridspecimport pandas as pdimport numpy as np# ── 1단계: EDA는 Seaborn으로 빠르게 ──────────────────penguins = sns.load_dataset("penguins").dropna()print("=== EDA 단계: Seaborn으로 빠른 탐색 ===")# 변수 간 관계 파악g = sns.pairplot(penguins, hue="species", plot_kws={"alpha": 0.5})g.figure.suptitle("EDA: Pairplot (Seaborn)", y=1.02)plt.tight_layout()plt.show()# 분포 확인fig, axes = plt.subplots(1, 2, figsize=(12, 4))sns.histplot(data=penguins, x="flipper_length_mm", hue="species", kde=True, ax=axes[0])axes[0].set_title("EDA: 날개 길이 분포")sns.boxplot(data=penguins, x="species", y="body_mass_g", hue="species", ax=axes[1])axes[1].set_title("EDA: 체중 분포")plt.tight_layout()plt.show()# ── 2단계: 최종 발표 자료는 Matplotlib으로 다듬기 ────────print("\n=== 발표 자료: Matplotlib으로 정밀 조정 ===")# 논문/발표 스타일: 격자 없이, 선명하게plt.style.use("seaborn-v0_8-white")fig = plt.figure(figsize=(12, 8))gs = gridspec.GridSpec(2, 3, figure=fig, hspace=0.4, wspace=0.35)# 메인 차트: 산점도 (Seaborn으로 그리고 Matplotlib으로 다듬기)ax_main = fig.add_subplot(gs[0, :2])species_colors = {"Adelie": "#E74C3C", "Chinstrap": "#3498DB", "Gentoo": "#2ECC71"}for species, group in penguins.groupby("species"): ax_main.scatter( group["flipper_length_mm"], group["body_mass_g"], c=species_colors[species], label=species, alpha=0.7, s=60, edgecolors="white", linewidths=0.5 )ax_main.set_xlabel("Flipper Length (mm)", fontsize=11)ax_main.set_ylabel("Body Mass (g)", fontsize=11)ax_main.set_title("Flipper Length vs. Body Mass by Species", fontsize=12, fontweight="bold")ax_main.legend(title="Species", frameon=True)ax_main.spines["top"].set_visible(False)ax_main.spines["right"].set_visible(False)# 우측 상단: 종별 비율 파이차트ax_pie = fig.add_subplot(gs[0, 2])species_counts = penguins["species"].value_counts()ax_pie.pie( species_counts, labels=species_counts.index, colors=[species_colors[s] for s in species_counts.index], autopct="%1.1f%%", startangle=90, pctdistance=0.85)ax_pie.set_title("Species Distribution", fontsize=10)# 하단 좌: 날개 길이 분포 (Seaborn 활용)ax_hist = fig.add_subplot(gs[1, 0])for species, group in penguins.groupby("species"): ax_hist.hist(group["flipper_length_mm"], bins=15, alpha=0.6, color=species_colors[species], label=species, density=True)ax_hist.set_xlabel("Flipper Length (mm)", fontsize=10)ax_hist.set_ylabel("Density", fontsize=10)ax_hist.set_title("Flipper Length Distribution", fontsize=10)ax_hist.legend(fontsize=8)ax_hist.spines["top"].set_visible(False)ax_hist.spines["right"].set_visible(False)# 하단 중: 체중 분포 (Seaborn boxplot → Matplotlib 축에 삽입)ax_box = fig.add_subplot(gs[1, 1])sns.boxplot(data=penguins, x="species", y="body_mass_g", palette=species_colors, hue="species", legend=False, ax=ax_box, linewidth=1.5)ax_box.set_xlabel("Species", fontsize=10)ax_box.set_ylabel("Body Mass (g)", fontsize=10)ax_box.set_title("Body Mass by Species", fontsize=10)ax_box.spines["top"].set_visible(False)ax_box.spines["right"].set_visible(False)# 하단 우: 상관행렬 heatmapax_corr = fig.add_subplot(gs[1, 2])num_cols = ["bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g"]corr = penguins[num_cols].corr()sns.heatmap(corr, annot=True, fmt=".2f", cmap="coolwarm", center=0, ax=ax_corr, cbar=False, xticklabels=["Bill\nLen", "Bill\nDep", "Flipper", "Mass"], yticklabels=["Bill\nLen", "Bill\nDep", "Flipper", "Mass"])ax_corr.set_title("Correlation", fontsize=10)fig.suptitle("Palmer Penguins: Comprehensive Analysis", fontsize=14, fontweight="bold", y=1.01)plt.savefig("final_presentation.png", dpi=200, bbox_inches="tight", facecolor="white")print("발표 자료 저장 완료: final_presentation.png")plt.show()
민서와 선배의 마무리 대화
대시보드를 완성하고 저장하는 동안 선배가 말했습니다.
"자, 이제 정리해볼게. EDA 할 때는 Seaborn. 빠르고, 통계를 자동으로 계산해주고, DataFrame과 잘 붙으니까. 최종 발표 자료나 논문 그림은 Matplotlib으로 다듬어. 픽셀 단위로 제어할 수 있거든. 그리고 청중이 직접 탐색하게 하고 싶거나 웹에 올려야 하면 Plotly."
민서가 고개를 끄덕이며 물었습니다. "세 가지를 다 배워야 하는 거네요. 힘들지 않나요?"
"사실 핵심 개념은 같아. x, y, hue, 제목, 레이블. 하나를 잘 배우면 나머지는 금방이야. 너 지금 Seaborn을 제대로 배웠으니까, Matplotlib이랑 Plotly는 이제 2~3일이면 쓸 수 있어."
"그럼 저 이제 세 가지 도구를 상황에 맞게 골라 쓸 줄 알게 된 건가요?"
선배가 웃으며 답했습니다. "정확해. 그게 진짜 실력이야."
세 도구를 함께 배우기 위한 로드맵
지금까지 이 교재를 통해 Seaborn을 익혔습니다. 다음 단계로 나아가고 싶다면 아래 순서를 추천합니다.
- Matplotlib 심화:
Artist객체,GridSpec,FuncAnimation. 논문 수준의 그래프 제어. - Plotly Express:
px.scatter,px.bar,px.line. Seaborn과 인터페이스가 비슷해서 빠르게 익힐 수 있습니다. - Plotly Graph Objects: 더 세밀한 인터랙티브 제어가 필요할 때.
- Dash: Plotly 기반 웹 대시보드 프레임워크. 실시간 데이터 시각화 앱 개발.
핵심 정리
- Matplotlib은 완전한 자유도와 세밀한 제어, Seaborn은 통계 시각화와 빠른 탐색, Plotly는 인터랙티브와 웹 대시보드에 강점이 있습니다.
- 실전에서는 "EDA → Seaborn, 최종 발표 → Matplotlib 다듬기, 인터랙티브 → Plotly"의 워크플로우를 따릅니다.
- Seaborn을 마스터했다면 Plotly Express로의 전환은 하루면 충분합니다.
- 도구를 많이 아는 것보다 상황에 맞는 도구를 고를 줄 아는 것이 더 중요합니다.