데이터 분석 • 처리

박스 플롯(IQR 사분위수): 이상치 찾기

AIstarter 2024. 3. 26. 16:50

해당 포스팅은 

1. 박스 플롯(IQR 사분위수) 설명

2. Python 코드로 이상치 살펴보기

다음과 같은 순으로 정리해보고자 합니다.

 


1. 박스플롯(IQR 사분위수) 설명

'박스 플롯'은 '상자 수염 그림'(Box-and-Whisker Plot) '상자 그림' 등 다양한 이름으로 불린다.

 

박스 플롯(box plot)
①데이터의 대략적인 분포와 개별적인이상치들을 동시에 보여줄 수 있으며,
서로 다른 데이터 뭉치를 쉽게 비교할 수 있도록 도와주는 시각화 기법으로 가장 널리 쓰이는 시각화 형태 중 하나이다.

 

박스 플롯을 IQR 사분위수라고도 하는데, 

박스 플롯의 상자는 아래 그림과 같이,
제1사분위수(Q1), 제2사분위수(Q2), 제3사분위수(Q3)를 드러낸다.

 

각 분위 수는 전체 데이터를 100%로 보고, 이를 4분위로 나눠서 데이터가 어디 비율에 해당하는지 볼 수 있도록 기준점을 세운 것이다.
제1사분위수(Q1) 는 25% 지점,  

제2사분위수(Q1) 는 50% 지점,  

제3사분위수(Q1) 는 75% 지점,  

제4사분위수(Q1) 는 100% 지점을 나타낸다.

예를 들어, 데이터로 {1,2,3,4,...,97,98,99,100} 이런 데이터가 있으면

Q1 = 25, Q2 = 50, Q3 =75, Q4 = 100인 것이다.

 

이 사분위수를 활용하여 시각적으로 나타낸 것이 아래의 박스플롯이다.

여기서 상자의 길이는 전체 데이터의 정확히 절반이 담겨 있는 범위인 사분위수범위를 시각적으로 표현한다.

 

상자의 좌측 변과 우측 변은 각각 Q1과 Q3의 위치를 나타낸다.

이 박스의 범위를 Q1부터 Q3까지의 위치라고 보면 된다.
이를 Interquatile Range라고 하여, 줄여서 IQR이라고 한다.

즉, IQR = Q3 - Q1 이다.

 

상자 안의 눈금은 Q2(즉, 중앙값)를 보여준다.

이 상태에서 최소값과 최대값 위치까지 수염(whisker)을 그려주면 위와 같은 박스 플롯이 만들어진다.

 

최소값은 Q1 - (범위조절변수)* IQR,
최대값은 Q3 + (범위조절변수)* IQR로 통계적으로 설정한다.

 

이 최소값과 최대값 범위에서 넘어난 데이터는 정상 범위에서 벗어난 outliers, 즉, 이상치에 해당한다.

 

이러한 박스플롯을 활영한 이상치를 찾는 과정은

단순히 통계적으로 바라보는 이상치 바라보는 관점이다.

주의해야할 점은 실제 데이터의 이상치를 제거하고자 할때,
박스플롯을 통한 이상치 찾는 방식을 맹신하여 사용하면 안된다.

 


2. 코드로 이상치 찾아보기

이에서 설명한 개념을 Python으로 
① 데이터의 박스 플롯을 그려보고

② 이상치에 해당하는 부분을 제거해보고자 한다.

 

# 필요한 패키지 설치
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
#데이터 불러와서 살펴보기
df = pd.read_csv("heart_2020_cleaned.csv")
df['BMI'].describe()

 

#사용할 컬럼만 저장
df_sp1= df_sp[['BMI','PhysicalHealth','MentalHealth']] 

# boxplot
plt.figure(figsize=(10,8))
sns.boxplot(y='BMI',data =df_sp1)

 

# Q1, Q3범위 정하기
Q1=df_sp1['BMI'].quantile(0.25)
Q3=df_sp1['BMI'].quantile(0.75)
IQR = Q3- Q1 # IQR값 계산
rev_range=2 # 범위조절변수 #보통 1.5 자주 사용

# 이상치 범위 설정
filter=(df_sp1['BMI']>=Q1-rev_range*IQR) &(df_sp1['BMI']<=Q3+rev_range*IQR)
# 이상치 제거한 데이터 저장
df_rm=df_sp1.loc[filter]
#전과 이상치 제거한 BMI 컬럼 데이터 비교
df_sp1['BMI'].describe()
df_rm['BMI'].describe()

왼쪽이 이상치 제거 전, 오른쪽이 이상치 제거 후 데이터이다.