KDE 플롯 (kdeplot)
히스토그램을 보던 민서가 불만을 가졌습니다.
"bins 수를 바꿀 때마다 모양이 달라지는 게 좀 불안한데요. 더 매끄럽게 볼 수 없을까요?"
"KDE 플롯을 써봐. 히스토그램을 부드럽게 만든 곡선이야. bins를 정할 필요가 없어."
이 차트가 보여주는 것
KDE(Kernel Density Estimation, 커널 밀도 추정)는 각 데이터 포인트 위에 작은 종 모양의 곡선(커널)을 올려놓고, 모두 더해서 하나의 매끄러운 곡선을 만듭니다. 마치 히스토그램의 막대들을 하나로 연결해 부드럽게 만든 것과 비슷합니다.
곡선이 높은 구간에 데이터가 많이 몰려 있습니다.
import seaborn as snsimport matplotlib.pyplot as plttips = sns.load_dataset("tips")sns.kdeplot(data=tips, x="total_bill")plt.title("계산 금액의 분포 (KDE)")plt.xlabel("계산 금액 (달러)")plt.show()
fill=True: 곡선 아래를 채운다
import seaborn as snsimport matplotlib.pyplot as plttips = sns.load_dataset("tips")sns.kdeplot(data=tips, x="total_bill", hue="time", fill=True, alpha=0.5)plt.title("식사 시간에 따른 계산 금액 분포")plt.xlabel("계산 금액 (달러)")plt.show()
fill=True는 곡선 아래 영역을 색으로 채워 그룹 간 비교를 더 직관적으로 만들어 줍니다.
bw_adjust: 매끄러움 조절
bw_adjust는 커널의 너비를 조절합니다. 값이 작을수록 데이터를 더 세밀하게 따라가고, 값이 클수록 더 부드럽게 표현합니다.
import seaborn as snsimport matplotlib.pyplot as plttips = sns.load_dataset("tips")fig, axes = plt.subplots(1, 3, figsize=(15, 4))for ax, bw in zip(axes, [0.3, 1.0, 3.0]): sns.kdeplot(data=tips, x="total_bill", bw_adjust=bw, fill=True, ax=ax) ax.set_title(f"bw_adjust={bw}") ax.set_xlabel("계산 금액 (달러)")plt.suptitle("bw_adjust에 따른 매끄러움 변화", y=1.02)plt.tight_layout()plt.show()
bw_adjust=0.3은 데이터의 작은 굴곡을 모두 드러내고, bw_adjust=3.0은 전체적인 경향만 남깁니다. 기본값 1.0이 대부분의 상황에서 적절합니다.
2D KDE: 두 변수의 결합 분포
x와 y를 모두 지정하면 두 변수의 결합 분포를 2D 등고선으로 표현합니다.
import seaborn as snsimport matplotlib.pyplot as plttips = sns.load_dataset("tips")fig, axes = plt.subplots(1, 2, figsize=(12, 5))# 등고선만sns.kdeplot(data=tips, x="total_bill", y="tip", ax=axes[0])axes[0].set_title("2D KDE (등고선)")# 채우기sns.kdeplot( data=tips, x="total_bill", y="tip", fill=True, cmap="Blues", thresh=0.05, ax=axes[1])axes[1].set_title("2D KDE (채우기)")plt.tight_layout()plt.show()
등고선이 조밀한 곳에 데이터가 집중되어 있습니다. thresh=0.05는 밀도가 5% 이하인 외곽 영역을 표시하지 않습니다.
히스토그램과 KDE 비교
import seaborn as snsimport matplotlib.pyplot as plttips = sns.load_dataset("tips")fig, axes = plt.subplots(1, 3, figsize=(15, 4))# 히스토그램만sns.histplot(data=tips, x="total_bill", bins=20, ax=axes[0])axes[0].set_title("히스토그램")# KDE만sns.kdeplot(data=tips, x="total_bill", fill=True, ax=axes[1])axes[1].set_title("KDE")# 히스토그램 + KDEsns.histplot(data=tips, x="total_bill", bins=20, kde=True, ax=axes[2])axes[2].set_title("히스토그램 + KDE")plt.tight_layout()plt.show()
세 번째 차트가 두 가지 장점을 모두 보여줍니다. bins에 따른 실제 빈도도 보이고, 전체 분포 형태도 한눈에 들어옵니다.