전처리 기법: 이상치(Outlier)
이전 포스팅인 '결측치: 중복 데이터'를 이어서 작성합니다.
https://kys0411.tistory.com/175
전처리 기법: 중복 데이터
데이터는 앞선 포스팅에서 사용한 데이터를 이용한다. https://kys0411.tistory.com/174 전처리 기법: 결측치(Missing Data) [관세청 수출입 무역 통계]를 가공한 데이터로 실습해보겠다. https://tradedata.go.kr/cts
kys0411.tistory.com
이상치
이상치란 대부분 값의 범위에서 벗어나 극단적으로 크거나 작은 값을 의미한다. Min-Max Scailing 해보면 대부분의 값은 0에 가깝고 이상치만 1에 가까운 값을 가진다. 극단적인 값이 생기면 데이터 간의 차이는 의미 없어지기 때문에 제거해야한다.
이상치를 찾는 것은 Anomaly detection 이라는 세부 분야가 있을 정도로 큰 분야이다.
가장 먼저 생각해볼 수 있는 간단하고 자주 사용되는 방법은 z-score 방법이다.
z-score는 평균을 빼주고 표준편차로 나눠 계산한다. zscore 가 특정 기준을 넘어서는 데이터를 이상치라고 한다. 여기서 특정 기준을 작게하면 이상치라고 판단하는 데이터가 많아지고, 기준을 크게 하면 이상치라고 판단하는 데이터가 적어진다.
이상치를 처리하는 방법은 크게 다음과 같다.
- 가장 간단한 방법으로 이상치를 삭제한다. 이상치를 원래 데이터에서 삭제하고, 이상치끼리 따로 분석하는 방법이 있다.
- 이상치를 다른 값으로 대체할 수 있다. 데이터가 적으면 삭제하는 방법보다 낫다.
- 결측치와 마찬가지로 예측 모델을 사용하여 대체할 수도 있다.
- Bining을 통해 수치형 데이터를 범주형으로 바꿀 수 있다.
z-score method
outlier라는 함수를 만들어 이상치의 인덱스를 리턴하도록 한다. outlier 함수는 데이터프레임(df), 칼럼(col), 기준(z)를 입력받는다.
- abs(df[col] - np.mean(df[col])) : 데이터에서 평균을 빼준 것에 절대값을 취한다.
- abs(df[col] - np.mean(df[col]))/np.std(df[col]) : 위에서 얻은 값을 표준편차로 나눠준다.
- df[abs(df[col] - np.mean(df[col]))/np.std(df[col])>z].index: 값이 z보다 큰 데이터의 인덱스를 추출한다.
def outlier(df, col, z):
return df[abs(df[col] - np.mean(df[col]))/np.std(df[col])>z].index
기준치(z)가 1.5일 때,
trade.loc[outlier(trade, '무역수지', 1.5)]

기준치(z)가 2일 때,
trade.loc[outlier(trade, '무역수지', 2)]

이상치가 아닌 데이터만 뽑는다면?
def not_outlier(df, col, z):
return df[abs(df[col] - np.mean(df[col])) / np.std(df[col]) <= z].index
trade.loc[not_outlier(trade, '무역수지', 1.5)]

IQR method
IQR(Interquartile range) 방법은 4분위 범위수로 이상치를 알아낸다.

Q3, Q1 = np.percentile(data, [75 ,25])
IQR = Q3 - Q1
IQR
data[(Q1-1.5*IQR > data)|(Q3+1.5*IQR < data)]
# Q. 사분위 범위수를 이용해서 이상치를 찾는 outlier2() 함수를 구현해보세요.
def outlier2(df, col):
# IQR
Q1 = df['무역수지'].quantile(0.25)
Q3 = df['무역수지'].quantile(0.75)
IQR = Q3 - Q1
# 이상치
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df['무역수지'] < lower_bound) | (df['무역수지'] > upper_bound)]
print(outliers)
return outliers
outlier2(data), '무역수지')