EDA 마지막 주는 "데이터를 숫자로 정직하게 요약하고, 그 요약을 믿어도 되는지 검증하는" 일이다. MLS-C01은 알고리즘을 묻기 전에 통계 직관을 먼저 묻는다. 분포가 치우쳤는가, 평균과 중앙값 중 무엇을 믿을 것인가, 이 표본이 모집단을 공정하게 대표하는가 — 여기서 어긋나면 어떤 모델을 골라도 결론이 틀린다.
평균보다 먼저 분포를 본다. 모양을 먼저 본다. 평균이 같아도 모양은 천차만별이다.
분포 특징
의미
EDA 함의
대칭(symmetric)
좌우 균형, 정규분포에 가까움
평균·표준편차가 대표성을 가진다
오른쪽 치우침(양의 왜도)
오른쪽 꼬리가 길다(소득·가격)
평균 > 중앙값, 로그 변환 후보
왼쪽 치우침(음의 왜도)
왼쪽 꼬리가 길다(만점 근처 점수)
평균 < 중앙값
다봉(multimodal)
봉우리가 여럿
하위 집단이 섞여 있는지 의심
고첨도(high kurtosis)
뾰족하고 꼬리가 두껍다
이상치·극단값이 잦다
왜도(skewness): 비대칭 정도. 0이면 대칭, 양수면 오른쪽 꼬리.
첨도(kurtosis): 꼬리의 두께. 클수록 극단값이 잦다.
대칭(정규) 오른쪽 꼬리(양의 왜도) 왼쪽 꼬리(음의 왜도)
▁▃▅█▅▃▁ ▂▅█▆▄▃▂▁▁▁ ▁▁▁▂▃▄▆█▅▂
평균 = 중앙값 평균 > 중앙값 평균 < 중앙값
(소득·주택가격·체류시간) (만점 근처 시험점수)
다봉(multimodal) 고첨도(heavy tail)
▁▃█▄▁▁▂▅█▃▁ ▁▁▂▄█▄▂▁▁
하위집단 혼재 의심 → 세그먼트 분리 가운데는 뾰족, 꼬리는 두껍다 → 이상치 빈발
import pandas as pddf = pd.read_csv("data/transactions.csv")# 분포 모양을 숫자로 요약print(df["amount"].skew()) # 왜도: 양수면 오른쪽 치우침print(df["amount"].kurt()) # 첨도: 양수면 뾰족하고 꼬리가 두껍다print(df["amount"].describe()) # count, mean, std, min, 25/50/75%, max
"분포를 먼저 보라"는 원칙을 극적으로 보여 주는 사례가 앤스컴의 4중주(Anscombe's Quartet, 1973)다. 네 데이터셋이 평균·분산·상관계수·회귀직선까지 모두 같은데 산점도를 그리면 전혀 다른 모양(직선형, 곡선형, 이상치 하나가 선을 끌어당기는 형태 등)이 나온다. 요약 통계량만 믿고 시각화를 건너뛰면 실제 데이터 구조가 통째로 숨는다. EDA가 히스토그램·박스플롯·산점도를 항상 포함하는 이유다.
표준편차는 "평균에서 평균적으로 얼마나 떨어져 있는가"를 원래 단위로 말해 준다. 정규분포에서는 평균 ±1σ에 약 68%, ±2σ에 약 95%, ±3σ에 약 99.7%가 들어간다(68-95-99.7 규칙).
표본에서 표준편차를 구할 때는 n이 아니라 n−1로 나눈다(베셀 보정, Bessel's correction). 표본 평균은 그 표본에 대해 제곱 편차를 최소화하는 값이라, 그대로 쓰면 모집단 분산을 체계적으로 과소추정한다. 자유도를 하나 줄여(n−1) 이 편향을 보정한다. pandas .std()는 표본 기준(ddof=1)이 기본이고 numpy np.std()는 모집단 기준(ddof=0)이 기본이라 같은 데이터에서 값이 미묘하게 달라진다. 시험 함정 포인트다.
import numpy as npfrom sklearn.preprocessing import StandardScaler, PowerTransformer# 표준화: 모양은 그대로, 척도만 바뀐다scaler = StandardScaler()df["amount_std"] = scaler.fit_transform(df[["amount"]])print(df["amount_std"].skew()) # 원본과 동일 — 모양 불변# 로그 변환: 오른쪽 치우침 완화 (양수 전용)df["amount_log"] = np.log1p(df["amount"]) # log(1+x), 0을 다룰 수 있다print(df["amount_log"].skew()) # 0에 가까워짐 — 더 대칭적# Box-Cox / Yeo-Johnson: 데이터가 최적 변환을 정한다pt = PowerTransformer(method="yeo-johnson")df["amount_yj"] = pt.fit_transform(df[["amount"]])
⚠️ 함정: "표준화·정규화하면 치우친 데이터가 정규분포가 되는가?"라는 질문이 함정이다. 아니다. 표준화는 평균과 척도만 바꾸고 왜도·첨도는 그대로 남는다. 정규성에 가까이 가려면 로그·Box-Cox 같은 비선형 변환이 필요하다. 또한 로그는 0과 음수에서 정의되지 않으므로 log1p나 Yeo-Johnson을 써야 한다.
⚠️ 함정: 어떤 변환이든 학습셋으로만 fit하고 검증·테스트셋에는 transform만 적용해야 한다. 전체 데이터로 평균·최댓값·λ를 구하면 그 순간 누수(leakage)다. 이 원칙은 Day 3에서 본격적으로 다룬다.
한 지역·한 기간에서만 수집하면 선택 편향(selection bias)이 생기고, 모델은 현실과 다른 분포를 학습한다.
표본이 작으면 추정이 흔들리고, 커질수록 표준오차 σ/√n가 줄어 추정이 정밀해진다.
표본 평균이 모집단 평균을 믿을 만하게 추정하는 근거는 중심극한정리(CLT)다. 모집단 분포 모양과 무관하게 n이 충분히 크면 표본 평균들의 분포가 표준오차 σ/√n인 정규분포에 근사한다. 표본이 클수록 추정이 촘촘해지고 신뢰구간도 정규분포를 따른다. EDA에서 "표본이 충분히 크고 대표성이 있는가"를 묻는 습관이 여기서 나온다.