데이터 분석에서 시각화는 데이터의 분포와 패턴을 직관적으로 파악하는 데 필수적입니다.
Matplotlib은 파이썬 시각화의 기반 라이브러리이고, Seaborn은 Matplotlib을 기반으로 통계 시각화에 특화된 고수준 라이브러리입니다.
pip install matplotlib seaborn
Matplotlib 기초
Figure와 Axes
Matplotlib의 구조를 이해하는 것이 먼저입니다.
- Figure: 전체 그림 영역 (캔버스)
- Axes: Figure 안의 실제 그래프가 그려지는 영역
import matplotlib.pyplot as plt
import numpy as np
# 방법 1: plt 인터페이스 (간단한 그래프)
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.show()
# 방법 2: Figure/Axes 명시적 사용 (권장)
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.show()
여러 그래프를 한 Figure에 배치할 때는 subplots()의 행, 열 인자를 사용합니다.
fig, axes = plt.subplots(2, 3, figsize=(12, 8))
# axes[0, 0], axes[0, 1] ... 형태로 각 Axes에 접근
기본 그래프 유형
선 그래프 (line plot)
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(x, y1, label="sin", color="blue", linewidth=2)
ax.plot(x, y2, label="cos", color="red", linestyle="--")
ax.set_title("Sin & Cos")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.legend()
ax.grid(True)
plt.tight_layout()
plt.show()
산점도 (scatter plot)
np.random.seed(42)
coverage = np.random.normal(30, 10, 100)
gc_content = np.random.normal(0.5, 0.05, 100)
fig, ax = plt.subplots(figsize=(6, 5))
scatter = ax.scatter(coverage, gc_content, c=gc_content,
cmap="viridis", alpha=0.7, edgecolors="none")
plt.colorbar(scatter, ax=ax, label="GC content")
ax.set_xlabel("Coverage (x)")
ax.set_ylabel("GC Content")
ax.set_title("Coverage vs GC Content")
plt.tight_layout()
plt.show()
막대 그래프 (bar plot)
genes = ["BRCA1", "TP53", "EGFR", "KRAS", "MYC"]
expression = [12.5, 8.3, 21.0, 15.6, 9.4]
fig, ax = plt.subplots(figsize=(7, 4))
bars = ax.bar(genes, expression, color="steelblue", edgecolor="white")
ax.set_xlabel("Gene")
ax.set_ylabel("Expression Level")
ax.set_title("Gene Expression")
# 막대 위에 값 표시
for bar, val in zip(bars, expression):
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.2,
f"{val}", ha="center", va="bottom", fontsize=9)
plt.tight_layout()
plt.show()
히스토그램 (histogram)
np.random.seed(42)
read_lengths = np.random.normal(150, 15, 1000)
fig, ax = plt.subplots(figsize=(7, 4))
ax.hist(read_lengths, bins=30, color="steelblue",
edgecolor="white", alpha=0.8)
ax.set_xlabel("Read Length (bp)")
ax.set_ylabel("Count")
ax.set_title("Read Length Distribution")
ax.axvline(read_lengths.mean(), color="red",
linestyle="--", label=f"Mean: {read_lengths.mean():.1f}")
ax.legend()
plt.tight_layout()
plt.show()
박스플롯 (box plot)
np.random.seed(42)
data = {
"sample_01": np.random.normal(30, 5, 50),
"sample_02": np.random.normal(25, 8, 50),
"sample_03": np.random.normal(35, 4, 50),
}
fig, ax = plt.subplots(figsize=(7, 5))
ax.boxplot(data.values(), labels=data.keys(), patch_artist=True)
ax.set_ylabel("Coverage (x)")
ax.set_title("Coverage Distribution per Sample")
plt.tight_layout()
plt.show()
그래프 스타일 설정
# 스타일 적용
plt.style.use("seaborn-v0_8") # seaborn 스타일
plt.style.use("ggplot") # ggplot 스타일
# 사용 가능한 스타일 목록
print(plt.style.available)
# 폰트 크기 전역 설정
plt.rcParams["font.size"] = 12
plt.rcParams["axes.titlesize"] = 14
plt.rcParams["figure.dpi"] = 100
그래프 저장
fig.savefig("output.png", dpi=300, bbox_inches="tight")
fig.savefig("output.pdf", bbox_inches="tight") # 벡터 형식
fig.savefig("output.svg", bbox_inches="tight")
bbox_inches="tight"는 그래프 주변의 여백을 자동으로 조정합니다. 논문이나 보고서에 사용할 그래프는 dpi=300 이상으로 저장합니다.
Seaborn
Seaborn은 Matplotlib보다 적은 코드로 통계적 시각화를 만들 수 있습니다. Pandas DataFrame과 자연스럽게 연동됩니다.
import seaborn as sns
import pandas as pd
import numpy as np
# 예시 데이터
np.random.seed(42)
df = pd.DataFrame({
"sample_id": [f"s{i:02d}" for i in range(30)],
"species": ["Homo sapiens"] * 15 + ["Mus musculus"] * 15,
"coverage": np.concatenate([
np.random.normal(30, 5, 15),
np.random.normal(25, 7, 15)
]),
"gc_content": np.concatenate([
np.random.normal(0.51, 0.03, 15),
np.random.normal(0.49, 0.03, 15)
]),
"expression": np.random.lognormal(2, 0.8, 30)
})
분포 시각화
histplot / kdeplot
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 히스토그램 + KDE
sns.histplot(data=df, x="coverage", hue="species",
kde=True, ax=axes[0])
axes[0].set_title("Coverage Distribution")
# KDE만
sns.kdeplot(data=df, x="coverage", hue="species",
fill=True, alpha=0.4, ax=axes[1])
axes[1].set_title("Coverage KDE")
plt.tight_layout()
plt.show()
boxplot / violinplot
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.boxplot(data=df, x="species", y="coverage",
palette="Set2", ax=axes[0])
axes[0].set_title("Coverage by Species (Boxplot)")
sns.violinplot(data=df, x="species", y="coverage",
palette="Set2", inner="box", ax=axes[1])
axes[1].set_title("Coverage by Species (Violin)")
plt.tight_layout()
plt.show()
관계 시각화
scatterplot / regplot
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 그룹별 산점도
sns.scatterplot(data=df, x="coverage", y="gc_content",
hue="species", palette="Set1",
alpha=0.8, ax=axes[0])
axes[0].set_title("Coverage vs GC Content")
# 회귀선 포함
sns.regplot(data=df, x="coverage", y="gc_content",
scatter_kws={"alpha": 0.5}, ax=axes[1])
axes[1].set_title("Coverage vs GC Content (with regression)")
plt.tight_layout()
plt.show()
pairplot
여러 수치형 열 간의 관계를 한 번에 시각화합니다.
sns.pairplot(df[["coverage", "gc_content", "expression", "species"]],
hue="species", diag_kind="kde", palette="Set1")
plt.suptitle("Pairplot", y=1.02)
plt.show()
히트맵
상관관계 행렬이나 발현량 행렬 시각화에 자주 사용합니다.
# 상관관계 히트맵
corr = df[["coverage", "gc_content", "expression"]].corr()
fig, ax = plt.subplots(figsize=(6, 5))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="coolwarm",
center=0, vmin=-1, vmax=1, ax=ax)
ax.set_title("Correlation Heatmap")
plt.tight_layout()
plt.show()
# 발현량 히트맵 (생물정보학 예시)
np.random.seed(42)
expr_matrix = pd.DataFrame(
np.random.lognormal(2, 1, (8, 6)),
index=[f"Gene_{i}" for i in range(1, 9)],
columns=[f"Sample_{i}" for i in range(1, 7)]
)
fig, ax = plt.subplots(figsize=(8, 6))
sns.heatmap(expr_matrix, cmap="YlOrRd", annot=False,
linewidths=0.5, ax=ax)
ax.set_title("Gene Expression Heatmap")
plt.tight_layout()
plt.show()
countplot / barplot
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 범주별 빈도
sns.countplot(data=df, x="species", palette="Set2", ax=axes[0])
axes[0].set_title("Sample Count by Species")
# 범주별 평균 + 오차 막대
sns.barplot(data=df, x="species", y="coverage",
palette="Set2", errorbar="sd", ax=axes[1])
axes[1].set_title("Mean Coverage by Species (±SD)")
plt.tight_layout()
plt.show()
스타일 설정
sns.set_theme(style="whitegrid") # 흰 배경 + 그리드
sns.set_theme(style="ticks") # 축 눈금만
sns.set_theme(style="dark") # 어두운 배경
sns.set_context("paper") # 논문용 (작은 폰트)
sns.set_context("talk") # 발표용 (큰 폰트)
sns.set_context("poster") # 포스터용 (더 큰 폰트)
Matplotlib vs Seaborn 선택 기준
| 상황 | 권장 |
| 커스터마이징이 많이 필요한 그래프 | Matplotlib |
| DataFrame 기반 통계 시각화 | Seaborn |
| 히트맵, pairplot, violinplot | Seaborn |
| 서브플롯 레이아웃 조정 | Matplotlib |
| 논문용 그래프 세부 조정 | Matplotlib (Seaborn 그린 뒤 Matplotlib으로 수정) |
Seaborn으로 그린 그래프도 Matplotlib의 ax 객체를 통해 추가 조정이 가능합니다. 실무에서는 Seaborn으로 초안을 빠르게 만든 뒤 Matplotlib으로 세부 조정하는 방식을 많이 사용합니다.
'BI&Programming-Tools > Python' 카테고리의 다른 글
| [파이썬 기초] argparse로 커맨드라인 도구 만들기 (0) | 2026.06.20 |
|---|---|
| [파이썬 기초] 통계 기초 (scipy) (0) | 2026.06.19 |
| [파이썬 기초] NumPy & Pandas 기초 (0) | 2026.06.18 |
| [파이썬 기초] 클래스, 모듈, 예외처리 (0) | 2026.06.18 |
| [파이썬 기초] 파일 형식 처리 (CSV, TSV, FASTA) (0) | 2026.06.17 |
