이상치의 제거는 데이터 분석에 매우 중요합니다.
특히, 최근에는 어떤 모델을 사용하지만 보다, 어느 데이터로 학습할지가 모델 성능에 있어서 보다 중요한 요소가 된 만큼, 이상치 제거는 그 중요성이 더욱 커졌다.
이상치를 제거하는 방법은 정말 많지만, 자주 사용하는 몇 가지 방법을 조사하기로 한다.
이상치(Outlier)란?
- 이상값이란, 일반적인 데이터 분포에 따르지 않는 값이며, 다른 데이터와 차이가 매우 큰 값을 갖는 데이터 포인트를 의미한다.
- 이상치가 발생하는 요인은, 데이터 수집 과정에서 에러가 발생하거나, 데이터 자체가 이상값을 포함하고 있는 경우, 변경점 발생에 의한 데이터 분포의 변화 등이 존재한다.
- 이상값은 상대적인 개념입니다.
즉, 어떤 데이터를 어떻게 분석하고 어떤 기준으로 이상값을 판별하는지에 따라 이상값 데이터가 다르다.
이상치(Outlier)를 제거하는 방법
1.사분위수(Quartiles)방법
- 사분위수법은 데이터 분포와 값의 크기를 이용하여 대략적인 이상값 구간을 설정하는 방법이다.
- 간단하고 직관적이며 이상치 제거에 많이 활용된다.
- 통계 값을 기반으로 1D 데이터에서도 쉽게 활용할 수 있습니다.
- 방법은 다음과 같습니다.
- 데이터를 값 기준으로 정렬한 후, 데이터의 분포에 따라 4등분하고, 각 부분의 값을 각각 1사분위, 2사분위, 3사분위, 4사분위로 나타낸다.
(서브 0~25%, 25~50%, 50~75%, 75~100%) - 1사분위수(값 기준 하위 25%가 되는 값)와 3사분위수(값 기준 상위 25%가 되는 값)를 구한다.
- 3사분위수와 1사분위수의 차이로 IQR(Interquartile Range)을 구한다.
- 일반적으로 1사분위수와 3사분위수로 IQR의 특정 배수(통상은 1.5) 이상 어긋난 값을 이상값으로 판정하여 제거한다.
- 데이터를 값 기준으로 정렬한 후, 데이터의 분포에 따라 4등분하고, 각 부분의 값을 각각 1사분위, 2사분위, 3사분위, 4사분위로 나타낸다.
- 파이썬 코드 구현
import numpy as np
def outlier_remove(data, threshold=1.5):
q1, q3 = np.percentile(data, (25, 75)) # 1사분위수, 3사분위수 계산
IQR = q3 - q1 # IQR 계산
lower_bound = q1 - (threshold * IQR) # Outlier 판단 Lower Bound 계산
upper_bound = q3 + (threshold * IQR) #Outlier 판단 Upper Bound 계산
filtered_data = (x for x in data if x >= lower_bound and x <= upper_bound)
outlier = (x for x in data if x not in filtered_data)
return filtered_data, outlier, q1, q3, iqr, lower_bound, upper_bound
if __name__ =='__main__':
X = np.random.normal(0, 1000, 1000)
filtered_data, outlier, q1, q3, IQR, lower_bound, upper_bound = outlier_remove(X)
2. Z-score 방법
- Z-score법은 데이터의 평균과 표준편차를 이용하여 이상값을 제거하는 방법이다.
- Z-score 방법은 데이터 분포 정규 분포를 따르는 가정이 필요합니다.
- 통계 값을 기반으로 1D 데이터에서도 쉽게 활용할 수 있습니다.
- 방법은 다음과 같습니다.
- 데이터 포인트의 평균과 표준 편차를 구합니다.
- 각 데이터 포인트의 Z-score (Z = |x – μ|/σ)를 요구한다.
Z-score는 데이터 포인트가 평균으로부터의 거리가 어떤 시그마 범위에 있는지를 의미합니다. - Z-score가 특정 threshold(일반적으로 3) 이상인 값은 이상값으로 판단하여 삭제합니다.
- 데이터 포인트의 평균과 표준 편차를 구합니다.
- 파이썬 코드 구현
import numpy as np
def outlier_remove(data, threshold=3):
z_scores = np.abs(data - np.mean(data)) / np.std(data) # Z-score 계산
filtered_data = data(z_scores < threshold)
outlier = data(z_scores>threshold)
return filtered_data, outlier
if __name__ == '__main__':
X = np.random.normal(0, 1000, 1000)
filtered_data, outlier = outlier_remove(X)