데이터 셋을 분석할 때 평균값이 지나치게 크거나 작게 나오는 경우가 있습니다.
이는 종종 이상치(Outiers) 때문입니다.
예를 들어, 나이 데이터에 250살이 들어있거나, 월 소득이 1억원인 샘플이 있을 수 있습니다.
이런 이상치는 단순한 입력 오류일 수도 있고, 극단적인 케이스일 수도 있지만,
그 존재만으로도 분석 결과를 심각하게 왜곡시킬 수 있습니다.
Structural Cause: 이상치가 발생하는 원인
원인 | 예시 |
입력 오류 | 설문 응답 시 2살을 22살로 잘못 입력 |
단위 혼동 | 연봉을 만 단위로 적어야 하는데 억 단위로 적음 |
실제 극단적 상황 | 재벌, 슈퍼노인 등 특이 케이스 |
수집 과정의 오류 | 센서 오작동, 크롤링 오류 등 |
(등등 더 다양한 원인 발생할 수도 있습니다.)
만일 위와 같은 이유로 발생한 이상치를 방치 했을 때 발생하는 문제는 다음과 같습니다.
- 평균 값 / 표준편차에 큰 영향
- 평균 소득: 대부분은 300만원 수준인데, 한 명이 1억이면 평균이 500만원처럼 왜곡됨
- 스케일링 / 정규화 시 왜곡
- MinMaxScaler 적용 시 이상치에 끌려 전체 범위가 쭉 퍼짐
- 모델 학습 시 과적합 또는 무의미한 경계 생성
그럼 지금부터 이상치 탐지 및 처리 방법에 대해 알아보도록 하겠습니다.
위 데이터의 간단한 설명을 하자면 캘리포니아 주택 가격 예측을 위한 데이터 셋입니다.
머신러닝 회귀 문제에 자주 활용되는 데이터입니다.
Kaggle에서 확인할 수 있습니다.
컬럼명 | 설명 |
longitude | 지리적 위치 (경도) |
latitude | 지리적 위치 (위도) |
housing_median_age | 해당 지역의 주택 중간 연식 |
total_rooms | 총 방 개수 |
total_bedrooms | 총 침실 개수 |
population | 지역 인구 수 |
households | 세대 수 |
median_income | 중간 소득 (단위: 만 달러) |
median_house_value | 주택 중간 가격 (타겟 변수) |
이상치 탐지 및 처리 방법
import pandas as pd
df = pd.read_csv('housing.csv')
1. 기술통계 기반 탐지 (IQR, Z-score)
1_1. IQR (Interquartile Range) 방식이란?
IQR은 사분위 범위(Interquartile Range)로, 전체 데이터를 중앙값 기준으로 4등분했을 때 Q1 (25%)과 Q3 (75%) 사이의 범위를 말합니다.
- Q1 (1사분위수): 하위 25% 위치에 있는 값
- Q3 (3사분위수): 상위 25% 이전에 있는 값
- IQR = Q3 - Q1
하한 = Q1 - 1.5 * IQR
상한 = Q3 + 1.5 * IQR
→ 이 범위를 벗어난 값 = 이상치
직관적 장점: 평균이나 표준편차처럼 극단값의 영향을 덜 받기 때문에, 왜도(skew)가 큰 데이터에도 적합합니다.
해당 기술을 적용해서 df의 이상치를 확인해보겠습니다.
IQR(Interquartile Range) 방식
Q1 = df['median_income'].quantile(0.25)
Q3 = df['median_income'].quantile(0.75)
IQR = Q3 - Q1
# IQR 기준 이상치 탐지
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df['median_income'] < lower_bound) | (df['median_income'] > upper_bound)]
print(f"IQR 기준 이상치 개수: {len(outliers)}")
# IQR 기준 이상치 개수: 681
1_2. Z-score 방식이란?
Z-score는 표준점수라고도 하며, 각 값이 평균에서 얼마나 떨어져 있는지를 표준편차 기준으로 나타낸 수치입니다.
Z = (x - 평균) / 표준편차
- Z가 0에 가까우면 평균에 가깝고,
- Z가 ±3을 넘어가면 극단값으로 간주
Z-score 방식은 정규분포에 가까운 데이터일수록 적합하며, 전체 분포에서 벗어난 값을 정량적으로 측정하는 데 유용합니다.
Z-score 방식 (표준점수)
from scipy.stats import zscore
df['income_z'] = zscore(df['median_income'])
# Z-score가 ±3 이상인 데이터는 이상치로 간주
outliers = df[df['income_z'].abs() > 3]
2. 시각화 기반 탐지
import seaborn as sns
import matplotlib.pyplot as plt
sns.boxplot(x=df['median_income'])
plt.title("Boxplot of Median Income")
plt.show()
3. 이상치 처리 방법
방법 | 설명 |
삭제 | 이상치를 drop하여 분석 대상에서 제외 |
값 대체 | 평균, 중앙값, 최대 허용치 등으로 수정 |
로그 변환 | 극단값을 줄이기 위해 log, sqrt 등 변환 적용 |
비지도 모델 활용 | Isolation Forest, DBSCAN 등으로 이상치 탐지 |
이상치 삭제 방법
# IQR 범위 벗어난 값 제거
df_clean = df[(df['median_income'] >= lower_bound) & (df['median_income'] <= upper_bound)]
혹은 로그 변환
import numpy as np
df['log_income'] = np.log1p(df['median_income']) # 0을 고려한 로그 변환
아래 표로 선택 기준을 정리해놨으니 참고하시면 좋을 듯 합니다.
방법 | 장점 | 단점 | 사용 조건 |
삭제 | 간단하고 모델에 영향 없음 | 정보 손실, 샘플 수 감소 | 이상치가 명백히 오류일 때 |
대체 | 데이터 보존 가능 | 주관적 기준이 개입될 수 있음 | 비교적 균등 분포일 때 |
변환 | 분포 안정화에 효과적 | 해석이 어려워질 수 있음 | 로그/지수 분포에서 유용 |
모델 기반 탐지 | 자동화 및 고차원 적용 가능 | 과도한 탐지는 false positive 가능 | 변수 간 관계를 고려할 때 |
사실 더 다양한 방법이 존재하지만 데이터 이상치를 탐지할 때 제가 생각하는 제일 중요한 Point는 해당 데이터의 도메인 지식이라고생각합니다.
A 도메인에서는 이상치데이터로 간주되는 값이 B 도메인에서는 정상 데이터일 수도 있습니다.
항상 데이터를 분석하기전에 해당 데이터의 도메인 지식을 충분히 숙지 하시는 걸 추천드리겠습니다.
- 정상값을 이상치로 오인: 예외적인 값이지만 실제 중요한 정보일 수도 있음
- 0을 이상치로 간주: 맥락 없이 제거하면 안 됨 (예: 소득=0은 실제 실직자일 수 있음)
- 로그 변환 시 음수 존재: log(x)는 음수 불가 → log1p(x) 또는 필터링 필요
정리
이상치는 분석 정확도를 떨어뜨리는 주요 원인 중 하나입니다.
IQR, Z-score, Boxplot 등 다양한 기법으로 탐지할 수 있습니다.
위에 정리해둔 삭제, 대체, 변환 등 상황에 맞는 방법을 선택하여 처리하는 것이 제일 중요합니다.
참고 자료
'Data Analysis' 카테고리의 다른 글
범주형 변수 인코딩 - Label, One-Hot, Ordinal (0) | 2025.05.19 |
---|---|
정규화(Normalization) vs 표준화(Standardization) (0) | 2025.05.14 |
결측치(Missing Values) 처리 (0) | 2025.05.12 |
Hypothesis Test란? (0) | 2023.08.23 |
데이터 분석가의 역할 (Data Analyst) (0) | 2023.08.11 |