seaborn은 matplotlib 위에 얹힌 통계 그래프 API입니다. "데이터프레임의 어떤 열을 x축·y축·색·격자에 대응시킬지"만 선언하면, 그룹화·집계·색 매핑·범례·축 라벨을 자동으로 처리합니다.
입력은 원칙적으로 tidy(long) 데이터입니다: 관측 1건이 1행, 변수 1개가 1열이며, x=, y=, hue=에는 열 이름 문자열을 넘깁니다.
seaborn 함수는 두 계열로 나뉩니다: 넘겨준 Axes 하나에 그리는 axes-level(histplot, boxplot, scatterplot ...)과, 자체 FacetGrid(Figure 전체)를 만드는 figure-level(displot, catplot, relplot). 이 구분이 이후 모든 챕터의 전제입니다.
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
sns.set_theme()
tips = sns.load_dataset("tips")시각화를 논할 때는 어느 계층을 이야기하는지 먼저 획정합니다. 세 계층은 관심사가 다릅니다.
seaborn은 가운데 계층입니다. 아래(matplotlib)로 내려가면 ax.spines·ax.set_xticks 같은 세부 제어를, 위(이론)로 올라가면 차트 선택의 근거를 다룹니다. seaborn은 "선택된 차트를 데이터에 맞게 빠르게 그리는" 도구이지, 차트를 대신 골라 주지는 않습니다.
💡 이럴 때: 축 눈금 포맷, 이중 y축, 주석 화살표처럼 seaborn이 노출하지 않는 것이 필요하면, seaborn으로 그린 뒤 반환된
Axes를 받아 matplotlib API로 마저 손봅니다. 계층을 오르내리는 것이지 둘 중 하나를 버리는 게 아닙니다.
seaborn은 모든 그림을 결국 matplotlib Axes에 그립니다. seaborn이 더해 주는 것은 다음 네 가지입니다.
histplot은 비닝, kdeplot은 커널 밀도 추정, barplot은 평균+신뢰구간, lineplot은 자동 집계+오차 밴드를 함수 안에서 계산합니다.hue(색), size(크기), style(마커·선모양)에 데이터 열을 대응시키면 범례까지 자동 생성됩니다.col, row에 열을 주면 카테고리별 서브플롯 격자를 만듭니다.set_theme() 한 줄로 폰트·색·격자 스타일이 일관되게 바뀝니다.# matplotlib만으로: 그룹별로 직접 반복
for key, grp in tips.groupby("smoker"):
plt.scatter(grp["total_bill"], grp["tip"], label=key)
plt.legend()
# seaborn: 선언 한 줄
sns.scatterplot(data=tips, x="total_bill", y="tip", hue="smoker")두 결과의 산점도는 비슷하게 보이지만, seaborn 쪽은 색 팔레트·범례 제목·축 라벨이 열 이름에서 자동으로 채워집니다.
seaborn의 자동화는 "어떤 열이 어떤 변수인지"를 알아야 작동합니다. 그래서 long 형식을 전제합니다.
# long (권장): 관측 1건 = 1행
# day | total_bill | tip
# Sun | 21.0 | 3.3
# Sun | 10.3 | 1.6
# wide (그대로는 부적합): 각 요일이 별도 열
# Sun | Mon | Tue
# 21.0 | 15.2 | 18.4wide 표는 pandas.melt로 편 뒤 넘깁니다.
long = wide.melt(var_name="day", value_name="total_bill")
sns.boxplot(data=long, x="day", y="total_bill")hue/col 매핑은 long에서만 온전히 동작합니다.x=, y=에 열 이름 대신 pandas Series나 배열을 직접 넘길 수도 있습니다.💡 이럴 때: "여러 지표를 한 그림에 겹쳐 보고 싶다"면, 지표별 열을 그대로 두지 말고
melt로(지표이름, 값)두 열로 편 다음hue="지표이름"으로 넘깁니다.
거의 모든 seaborn 함수가 아래 인자를 공유합니다.
sns.scatterplot(data=tips, x="total_bill", y="tip",
hue="sex", size="size", style="time")한 축만 주면(예: x만) 단변량 플롯으로, 둘 다 주면 이변량 플롯으로 해석됩니다.
하나의 matplotlib Axes에 그리고, 그 Axes를 반환합니다. ax= 인자로 그릴 위치를 지정할 수 있습니다.
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
sns.histplot(data=tips, x="total_bill", ax=axes[0])
sns.boxplot(data=tips, x="day", y="total_bill", ax=axes[1])
fig.suptitle("axes-level: 내가 만든 서브플롯에 끼워 넣기")대표 함수: histplot, kdeplot, ecdfplot, rugplot, boxplot, violinplot, boxenplot, stripplot, swarmplot, barplot, pointplot, countplot, scatterplot, lineplot, regplot, residplot, heatmap.
subplots, GridSpec)에 자유롭게 합성됩니다.ax에서 이어서 조정합니다.Figure 전체를 관리하는 FacetGrid(또는 JointGrid/PairGrid)를 새로 만들고, 그 그리드 객체를 반환합니다. ax=를 받지 않습니다.
g = sns.displot(data=tips, x="total_bill", col="time", row="sex", kind="hist")
g.set_axis_labels("결제 금액", "빈도")
g.figure.suptitle("figure-level: col·row로 격자 자동 생성", y=1.03)figsize가 아니라 height(패싯 하나의 높이)와 aspect(가로/세로 비)로 합니다.Axes는 g.axes 또는 g.axes_dict로 접근합니다.💡 이럴 때: 카테고리별로 나눠서 봐야 패턴이 보이면 figure-level(
col=/row=)을 씁니다. 반대로 이미 만든 대시보드 격자 한 칸에 넣어야 하면 axes-level +ax=를 씁니다.
💡 이럴 때: figure-level 함수에 ax=를 넘기면 오류가 납니다. 서브플롯에 합성이 필요하면 대응하는 axes-level 함수(displot→histplot)로 바꿉니다.
1) 그림을 카테고리별 격자로 나눠야 하나?
예 → figure-level (displot / catplot / relplot, col=/row=)
아니오 → 2)
2) 내가 만든 matplotlib subplots/GridSpec 안에 끼워야 하나?
예 → axes-level + ax=
아니오 → 둘 다 가능. 단일 그림이면 axes-level이 간단
3) 산점도+주변 분포(jointplot)나 변수쌍 격자(pairplot)가 필요하나?
예 → JointGrid / PairGrid 계열 (5장)💡 이럴 때: 튜토리얼 예제를 따라 하는데
ax=가 안 먹혀서 당황하면, 그 함수가 figure-level인지부터 확인합니다.sns.displot(figure)과sns.histplot(axes)은 이름이 한 글자 차이입니다.
댓글
GitHub 계정으로 의견이나 질문을 남길 수 있습니다.