이상치(Outlier) 제거하는 Python 예제 코드
표준화 전후로 이상치(Outlier)를 제거하는 Python 예제 코드입니다.
2022. 4. 5 최초작성
이상치는 대부분의 값과 다르게 아주 작거나 아주 큰 값을 의미합니다.
평균 ± 표준편차 × 3 을 벗어나는 것을 이상치로 취급하여 제거해본 예제 코드입니다. 표준화를 적용 전후에 각각 이상치를 제거해봤습니다.
전체 코드입니다.
import pandas as pd import numpy as np import matplotlib.pyplot as plt from collections import Counter # 5개의 특징으로 구성된 샘플 40개 생성 a = np.random.randint(1, 13, size=200).reshape(40, 5) df_raw = pd.DataFrame(a) # 0번째 특징에 이상치 추가 df_raw.iloc[0, 0] = -30 df_raw.iloc[1, 0] = 30 df_raw.iloc[2, 0] = 60 df_raw.iloc[3, 0] = -27 df_raw.iloc[4, 0] = 27 df_raw.iloc[5, 0] = -60 # 평균과 표준편차 df_raw_mean = df_raw.mean(axis=0) df_raw_std = df_raw.std(axis=0) # df_raw에 포함된 숫자(key_raw) 별로 몇개가 존재하는지 계산(value_raw) key_raw = Counter(df_raw.values.flatten()).keys() value_raw = Counter(df_raw.values.flatten()).values() # mean - 3*std ~ mean + 3*std 범위 벗너나면 이상치로 제거 df_raw_result = df_raw.copy() df_raw_result[df_raw_result > df_raw_mean + df_raw_std * 3] = 0 df_raw_result[df_raw_result < df_raw_mean - df_raw_std * 3] = 0 # df_raw_result에 포함된 숫자(key_raw_result) 별로 몇개가 존재하는지 계산(value_raw_result) key_raw_result = Counter(df_raw_result.values.flatten()).keys() value_raw_result = Counter(df_raw_result.values.flatten()).values() # 표준화 적용 df_standardization = (df_raw - df_raw_mean) / df_raw_std # df_standardization에 포함된 숫자(key_standardization) 별로 몇개가 존재하는지 계산(value_standardization) key_standardization = Counter(df_standardization.values.flatten()).keys() value_standardization = Counter(df_standardization.values.flatten()).values() # -3 ~ 3 범위 벗어나면 이상치로 제거 df_standardization_result = df_standardization.copy() df_standardization_result[df_standardization_result > 3] = 0 df_standardization_result[df_standardization_result < -3] = 0 # df_standardization_result에 포함된 숫자(key_standardization_result) 별로 몇개가 존재하는지 계산(value_standardization_result) key_standardization_result = Counter(df_standardization_result.values.flatten()).keys() value_standardization_result = Counter(df_standardization_result.values.flatten()).values() # 이상치가 존재했던 셀만 값을 출력하여 변화 확인 print('df_raw') for i in range(6): print(df_raw.iloc[i, 0], end=" ") print('\n') print('df_raw_result') for i in range(6): print(df_raw_result.iloc[i, 0], end= " ") print('\n') print('df_standardization') for i in range(6): print(df_standardization.iloc[i, 0], end=" ") print('\n') print('df_standardization_result') for i in range(6): print(df_standardization_result.iloc[i, 0], end=" ") print('\n') # 이상치 제거되는 것을 그래프로 확인 k = 0 # 각 값들의 분포 모양 비교 f,ax = plt.subplots(1,4,figsize=(12, 5)) ax[0].bar(key_raw, value_raw, color='red') ax[0].set_xlim([-65, 65]) ax[0].set_ylim([0, 45]) ax[0].set_title('rawdata before') ax[0].axvline(df_raw_mean[k], color='b', linestyle='dashed', linewidth=1) ax[0].axvline(df_raw_mean[k] - df_raw_std[k]*3 , color='k', linestyle='dashed', linewidth=1) ax[0].axvline(df_raw_mean[k] + df_raw_std[k]*3 , color='k', linestyle='dashed', linewidth=1) ax[1].bar(key_raw_result, value_raw_result, color='red') ax[1].set_xlim([-65, 65]) ax[1].set_ylim([0, 45]) ax[1].set_title('rawdata after') ax[1].axvline(df_raw_mean[k], color='b', linestyle='dashed', linewidth=1) ax[1].axvline(df_raw_mean[k] - df_raw_std[k]*3, color='k', linestyle='dashed', linewidth=1) ax[1].axvline(df_raw_mean[k] + df_raw_std[k]*3 , color='k', linestyle='dashed', linewidth=1) ax[2].bar(key_standardization, value_standardization, color='red') ax[2].set_xlim([-7, 7]) ax[2].set_ylim([0, 45]) ax[2].set_title('Standardization data before') ax[2].axvline(-3, color='k', linestyle='dashed', linewidth=1) ax[2].axvline(3 , color='k', linestyle='dashed', linewidth=1) ax[3].bar(key_standardization_result, value_standardization_result, color='red') ax[3].set_xlim([-7, 7]) ax[3].set_ylim([0, 45]) ax[3].set_title('Standardization data after') ax[3].axvline(-3, color='k', linestyle='dashed', linewidth=1) ax[3].axvline(3 , color='k', linestyle='dashed', linewidth=1) plt.show() |
이상치 제거를 보여주는 그래프입니다.
왼쪽 2개는 표준화 전에 이상치를 제거한 전후이고 오른쪽 2개는 표준화 후에 이상치를 제거한 전후입니다.
이상치에 해당되는 값만 출력한 결과입니다.
df_raw
-30 30 60 -27 27 -60
df_raw_result
-30 30 0 -27 27 0
df_standardization
-2.124591463996994 1.4536678437874169 3.2427974976796223 -1.9456784986077733 1.2747548783981963 -3.913721117889199
df_standardization_result
-2.124591463996994 1.4536678437874169 0.0 -1.9456784986077733 1.2747548783981963 0.0
참고
https://machinelearningmastery.com/how-to-use-statistics-to-identify-outliers-in-data/
https://analyticsindiamag.com/outlier-detection-using-z-score-a-complete-guide-with-python-codes/