[파이썬 기초] Matplotlib / Seaborn 시각화

2026. 6. 18. 20:00·BI&Programming-Tools/Python

데이터 분석에서 시각화는 데이터의 분포와 패턴을 직관적으로 파악하는 데 필수적입니다.

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
'BI&Programming-Tools/Python' 카테고리의 다른 글
  • [파이썬 기초] argparse로 커맨드라인 도구 만들기
  • [파이썬 기초] 통계 기초 (scipy)
  • [파이썬 기초] NumPy & Pandas 기초
  • [파이썬 기초] 클래스, 모듈, 예외처리
데이터로 읽는 생명
데이터로 읽는 생명
is-note 님의 블로그 입니다.
  • 데이터로 읽는 생명
    In Silico Note
    데이터로 읽는 생명
  • 전체
    오늘
    어제
    • 분류 전체보기 (190)
      • Bio-Knowledge (16)
        • 분자생물학 & 유전학 기초 (0)
        • 전사체학 & 유전자 발현 (0)
        • 구조생물학 & 단백질 (0)
        • 싱글셀 & 다중오믹스 (0)
        • 임상유전학 & 질환 데이터 (0)
      • Programming (4)
        • API (4)
      • BI&Programming-Tools (111)
        • File Formats (14)
        • Linux & Bash Script (38)
        • Python (35)
        • R (11)
        • 통계 (8)
        • Pipeline Manager (0)
        • Etc (5)
      • Bio Data Analysis (28)
        • 서열분석개론 (6)
        • WGS(Whole Genome Seq) (11)
        • WES(Whole Exome Seq) (2)
        • RNA-Seq (4)
        • Metagenome (2)
        • Non-human Resequencing (1)
        • 임상유전체 분석 (1)
        • Multi-Omics (1)
      • Bio-Trends & Tech (1)
      • 코딩테스트 연습 (30)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    R
    유전체분석
    파일포맷
    bioinformatics
    데이터분석
    wgs
    파이썬기초
    R기초
    코딩테스트
    리눅스기초
    생물정보학
    리눅스
    통계
    파이썬연습
    fasta
    분자생물학
    GATK
    ngs
    파이썬
    FASTQ
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
데이터로 읽는 생명
[파이썬 기초] Matplotlib / Seaborn 시각화
상단으로

티스토리툴바