
Matplotlib · Seaborn · Figure Engineering · Accessibility · Robustness
데이터를 설득력 있게 전달하는 시각적 구조를 어떻게 설계할 것인가?
1. 색상·형태·축·스케일을 포함한 시각적 표현의 정확성(Accuracy)
2. Matplotlib의 Figure/Axes 구조를 통한 통제력(Control)
3. 접근성·해석력·강건성을 모두 만족하는 실무형 그래프 설계 기법(Engineering)
그래프는 크게 세 가지 유형의 데이터에 대해 서로 다른 팔레트를 요구한다:
| 데이터 유형 | 적합한 팔레트 | 예시 | 목적 |
|---|---|---|---|
| 순차형(Sequential) | 하나의 색에서 명도·채도 변화 | viridis, Blues, Reds | 크기·순위 변화 시각화 |
| 발산형(Diverging) | 중심값(0)을 기준으로 양극단 대비 | coolwarm, vlag, RdBu | 양수/음수·차이·편차 표현 |
| 범주형(Qualitative) | 독립적이고 대비가 강한 색상 | Set1, tab10 | 그룹 구분, 순서 X |
실무에서 가장 많이 발생하는 실수는 색상 하나만으로 정보를 구분하는 것이다.
색각 유형에 따라 특정 색상(빨강–초록, 파랑–보라 등)을 구분하지 못할 수 있다.
sns.lineplot(
data=df, x='Time', y='Metric',
hue='Group',
style='Group', # 선 스타일/마커 스타일로 추가 인코딩
markers=True,
dashes=False
)
Matplotlib은 “그림을 그리는 도구”가 아니라,
그래프를 구성하는 객체들을 조립하는 도구이다.
서로 다른 스케일(예: 온도 vs 습도)을 하나의 타임라인에 담아야 하는 상황이 많다.
fig, ax1 = plt.subplots(figsize=(10, 6))
ax1.plot(time, temp, 'r-')
ax1.set_ylabel("Temperature (°C)", color='red')
ax1.tick_params(axis='y', labelcolor='red')
ax2 = ax1.twinx()
ax2.plot(time, humidity, 'b-')
ax2.set_ylabel("Humidity", color='blue')
ax2.tick_params(axis='y', labelcolor='blue')
이중축 그래프는 상관관계 환상을 만들기 매우 쉽다.
그래서 실무에서는 이중축 그래프를 사용할 때 다음 중 1개 이상을 함께 제시해야 한다:
시각화의 품질은 축에서 결정된다 해도 과언 X
자동 틱은 대부분 다음과 같은 문제를 만든다:
따라서 항상 Axes 객체에서 직접 제어해야 한다.
ax.set_xticks(x_positions)
ax.set_xticklabels(months, rotation=45, ha='right')
ax.set_yticks(np.arange(0, 110, 25))
가독성과 해석력이 극적으로 상승한다.
Pandas DatetimeIndex는 자동으로 Matplotlib 날짜로 변환되지만,
등의 문제가 생긴다.
import matplotlib.dates as mdates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d'))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=10))
ax.xaxis.set_minor_locator(mdates.DayLocator(interval=5))
잘못된 날짜 라벨은 시계열 그래프 전체 의미를 왜곡시킨다.
날짜는 “순차적 맥락”을 주기 때문에 틱이 엉키면 흐름 자체가 무너진다.
Seaborn은 두 레이어로 나뉜다.
| 구분 | Axes Level | Figure Level |
|---|---|---|
| 대표 함수 | scatterplot, boxplot, heatmap | lmplot, catplot, relplot |
| 반환 | Axes | FacetGrid |
| 장점 | 세밀한 커스터마이징 | 여러 서브플롯 자동 구성 |
| 단점 | 단일 플롯만 | 축 제어가 간접적 |
**- 원하는 레이아웃을 정확히 통제해야 한다 → Axes Level
서브플롯별로 데이터 범위가 매우 다를 때 중요한 기능이다.
g = sns.FacetGrid(df, col="Category", sharex=False, sharey=False)
g.map(sns.histplot, "Value")
g.set_titles(col_template="Category: {col_name}")
공유 축을 해제하면:
히트맵은 행렬 데이터의 구조적 인사이트를 보여주는 도구다.
핵심 파라미터:
center=0: 발산형 팔레트의 기준vmin vmax: 색상 스케일 고정cbar: 색상 막대 표시 제어sns.heatmap(
corr, center=0, cmap="coolwarm",
cbar=False, annot=True, fmt=".2f"
)
데이터가 아래와 같은 형태라면:
ax.set_yscale("log")
로그 스케일은 다음을 해결한다:
Heatmap에서는 LogNorm()으로 색상 스케일도 로그화할 수 있다.
PNG는 확대하면 깨지고, 인쇄 시 품질 저하가 있다.
SVG는 다음 장점을 가진다:
fig.savefig("plot.svg", format="svg", transparent=True, bbox_inches="tight")
데이터를 보여주는 것과
데이터가 무엇을 의미하는지 전달하는 것은 완전히 다른 문제다.
실무 그래프는 다음 요소를 포함해야 한다:
| 요소 | 역할 |
|---|---|
annotate() | 맥락 제공 |
| 색상–축–선 스타일 통일 | 인지적 부하 감소 |
| 의미 있는 제목 | 그래프의 ‘결론’을 한 문장으로 표현 |
| 축 라벨 정교화 | 해석 오류 방지 |
| 범주 | 핵심 개념 | 실제 효과 |
|---|---|---|
| 강건성(Robustness) | Figure/Axes 분리, OO 방식 | 에러 감소, 구조적 그래프 |
| 정확성(Accuracy) | 팔레트 전략, 정규화, 로그 스케일 | 데이터 왜곡 최소화 |
| 접근성(Accessibility) | hue + style, 색각보정 | 모두가 읽을 수 있는 그래프 |
| 해석력(Interpretability) | Annotation, 틱 제어, 축 디자인 | 메시지가 명확하게 전달됨 |
| 품질(Quality) | SVG 출력, 투명 배경 | 인쇄·웹·대시보드 최고의 품질 |