반응형

표준화 전후로 이상치(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/ 



반응형

해보고 확인한 것을 문서화하여 기록합니다.


부족함이 있지만 도움이 되었으면 합니다.
잘못된 부분이나 개선점을 알려주시면 감사하겠습니다.



포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
문제가 생기면 포스트와 바뀐 환경이 있나 먼저 확인해보세요.

질문을 남겨주면 가능한 빨리 답변드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기

댓글을 달아 주세요

">