파이썬에서 이상치 처리하기
학습 목표 매핑
SKALA 3기 Module 2 — 데이터 분석 개요 및 기초통계 (Learning Objective 2-2)
- Objective: 데이터 품질 문제(결측치·중복·이상치) 3가지를 IQR 기법으로 탐지하고, 실무 데이터셋에서 90% 정확도로 식별 가능 (Bloom L3-L4)
- Evaluation: 정확도 평가 (탐지 성공률)
이상치 탐지 방법
1. Z-score (표준정규분포)
개념: 데이터가 평균으로부터 얼마의 표준편차만큼 벗어나 있는지 측정
공식:
판정 기준:
- |Z| < 1.96: 95% 신뢰수준 범위 내 (정상)
- 1.96 ≤ |Z| < 2.58: 99% 신뢰수준 범위 내
- |Z| ≥ 2.58: 99% 신뢰수준 초과 (이상치)
Python:
from scipy.stats import zscore
# Z-score 계산
df['Z_Score'] = zscore(df['Value'])
# 이상치 탐지 (3σ 기준)
df['Outlier'] = df['Z_Score'].abs() > 32. IQR (사분위수 범위)
개념: 데이터 분포의 중간 50% 범위를 이용한 탐지
공식:
- Q1: 25 percentile
- Q3: 75 percentile
- IQR = Q3 - Q1
- 하한 = Q1 - 1.5 × IQR
- 상한 = Q3 + 1.5 × IQR
판정: 하한 미만 또는 상한 초과 → 이상치
Python:
# IQR 계산
Q1 = df['Value'].quantile(0.25)
Q3 = df['Value'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
# 이상치 탐지
df['Outlier'] = (df['Value'] < lower) | (df['Value'] > upper)이상치 처리 방법
방법 1: 삭제 (Removal)
이상치 행을 완전히 제거
Python:
# 이상치 제거
df_clean = df[~df['Outlier']]
# 또는 인덱스로 제거
outlier_idx = np.where((df['Value'] < lower) | (df['Value'] > upper))
df_clean = df.drop(outlier_idx)장점:
- ✅ 명확한 처리
- ✅ 통계 왜곡 없음
단점:
- ❌ 데이터 손실
- ❌ 샘플 크기 감소
방법 2: 대체 (Capping / Imputation)
이상치 값을 상한/하한으로 대체
Python:
# 상한/하한으로 제한 (Capping)
df['Value_Capped'] = df['Value'].clip(lower=lower, upper=upper)
# 중앙값으로 대체
median = df[~df['Outlier']]['Value'].median()
df['Value_Imputed'] = df['Value'].where(~df['Outlier'], median)
# 최대/최소값으로 대체
max_val = df[~df['Outlier']]['Value'].max()
df['Value_MaxReplace'] = df['Value'].apply(
lambda x: max_val if x > upper else (lower if x < lower else x)
)장점:
- ✅ 데이터 보존
- ✅ 샘플 크기 유지
- ✅ 머신러닝 모델 안정성
단점:
- ❌ 원본 데이터 변형
- ❌ 통계 왜곡 가능
박스플롯 시각화
import matplotlib.pyplot as plt
# 박스플롯으로 이상치 시각화
plt.figure(figsize=(10, 6))
plt.boxplot(df['Value'], vert=True)
plt.title('이상치 시각화 (박스플롯)')
plt.ylabel('Value')
plt.grid(axis='y', alpha=0.3)
plt.show()
# 파란색 상자: Q1 ~ Q3 (50% 데이터)
# 주황색 선: 중앙값 (Median)
# 수염(whisker): 하한 ~ 상한 (경계값)
# 검은 점: 이상치 (outliers)처리 방법 선택 기준
| 상황 | 추천 방법 | 이유 |
|---|---|---|
| 샘플 충분 | 삭제 | 데이터 순수성 중시 |
| 샘플 부족 | 대체 | 데이터 손실 방지 |
| 금융/의료 | 대체 | 정보 손실 최소화 |
| 머신러닝 | 대체 | 모델 안정성 |
| 통계 분석 | 삭제 | 가정 충족 |
| 센서 데이터 | 삭제 | 오류 명백 |
실전 예시
# 시계열 데이터의 이상치 처리
data = {
'Date': pd.date_range('2026-01-01', periods=100),
'Sales': [100, 105, 98, 102, 95, 500, 103, ... # 500은 이상치
}
df = pd.DataFrame(data)
# IQR 기반 이상치 탐지
Q1 = df['Sales'].quantile(0.25)
Q3 = df['Sales'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
# 이상치 확인
print(f"이상치: {df[(df['Sales'] < lower) | (df['Sales'] > upper)]}")
# 상한/하한으로 제한 (추천)
df['Sales_Clean'] = df['Sales'].clip(lower=lower, upper=upper)
# 결과 비교
print(f"원본 mean: {df['Sales'].mean():.2f}")
print(f"정제 후 mean: {df['Sales_Clean'].mean():.2f}")주의사항
⚠️ 이상치가 항상 오류는 아님:
- 극단값도 유효할 수 있음 (예: 명절 판매량 급증)
- 도메인 지식으로 판단 필수
⚠️ 자동 처리의 위험:
- 단순한 규칙 적용은 위험
- 항상 도메인 전문가 검토 필수
⚠️ 처리 방법 문서화:
- 어떤 방법으로 처리했는지 기록
- 재현성과 투명성 확보
학습 설계 포인트
Cognitive Level (Bloom)
- L2 (Understand): Z-score/IQR 개념, 판정 기준
- L3 (Apply): 실제 데이터에 적용
- L4 (Analyze): 삭제 vs 대체 선택 판단
권장 실습
- 탐지: 샘플 데이터에서 이상치 식별
- 시각화: 박스플롯으로 확인
- 비교: 처리 전후 통계량 비교 (평균, 표준편차)
- 정확도: 탐지된 이상치 도메인 검증
참고 자료
- Pandas clip(): https://pandas.pydata.org/docs/reference/api/pandas.Series.clip.html
- Scipy zscore: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.zscore.html
- 박스플롯 해석: https://en.wikipedia.org/wiki/Box_plot
타 소스와의 연계
outlier-detection-iqr-zscore-medium (이상치 탐지 수학/코드) eda-exploratory-data-analysis-geeksforgeeks (EDA 8단계 프로세스) eda-python-tds-prabhu (실제 데이터셋 정제 사례)