이번 포스팅에서는 하나의 연속형 변수에 대해서 분포 형태, 퍼짐정도, 이상치 여부 등을 시각화하고, 하나의 그룹 혹은 여러개의 그룹 간 비교하는데 유용한 상자 그림 (Box plot, Box-and-Whisker Plot)을 그리는 방법을 소개하겠습니다. 


상자 그림은 연속형 변수에 대해서 최소값(min), 제 1사분위수(Q1), 중앙값(Q2, median), 제 3사분위수(Q3), 최대값(max) 의 요약통계량을 계산하는 것에서 시작합니다. 



[상자 그림 그리는 순서 및 방법]


  1. 주어진 데이터에서 각 사분위수를 계산한다.
  2. 그래프에서 제1 사분위와 제3 사분위를 밑변으로 하는 직사각형을 그리고, 제 2사분위에 해당하는 위치에 선분을 긋는다.
  3. 사분위수 범위(IQR, Interquartile range, )를 계산한다.
  4. 과 차이가 1.5*IQR 이내인 값 중에서 최댓값을 과 직선으로 연결하고, 마찬가지로 과 차이가 1.5*IQR 이내인 값 중에서 최솟값을 과 연결한다.
  5. 보다 1.5*IQR 이상 초과하는 값과 보다 1.5*IQR 이상 미달하는 값은 점이나, 원, 별표등으로 따로 표시한다(이상치 점).

* source: https://ko.wikipedia.org/wiki/상자_수염_그림

 



위의 상자 그림 그리는 방법에 대한 내용은 아래의 표준정규분포 확률밀도함수 분포 곡선에 대한 상자 그림 매핑을 보면 좀더 이해가 쉬울 것입니다. 


[Boxplot and a probability density function (pdf) of a Normal N(0,1σ2) Population]


* source: https://en.wikipedia.org/wiki/Box_plot




상자 그림을 (1) matplotlib, (2) seaborn, (3) pandas 패키지를 이용해서 그리는 방법을 차례대로 소개하겠습니다. 



import numpy as np

import pandas as pd


import matplotlib.pyplot as plt

import seaborn as sns

plt.rcParams['figure.figsize'] = [10, 6]

%matplotlib inline




예제로 사용할 데이터셋은 seaborn 패키지에 내장되어 있는 tips 라는 DataFrame 을 사용하겠습니다. 



# loading 'tips' dataset

tips = sns.load_dataset('tips')


tips.shape

(244, 7)


tips.head()

total_billtipsexsmokerdaytimesize
016.991.01FemaleNoSunDinner2
110.341.66MaleNoSunDinner3
221.013.50MaleNoSunDinner3
323.683.31MaleNoSunDinner2
424.593.61FemaleNoSunDinner4


tips.groupby(['sex', 'day']).size()

sex     day 
Male    Thur    30
        Fri     10
        Sat     59
        Sun     58
Female  Thur    32
        Fri      9
        Sat     28
        Sun     18
dtype: int64




tips DataFrame의 tip 연속형 변수에 대해서 상자 그림을 그려보겠습니다. 


  (1) matplotlib 으로 상자 그림 그리기


boxplot() 함수를 사용해서 default 세팅으로 상자 그림을 그려보겠습니다. 


# Basic box plot

plt.boxplot(tips['tip'])

plt.show()



이번에는 상자 그림의 이상치(outlier) 모양과 색깔, 제목(title), X축 이름(X label)을 설정해보겠습니다. 



# setting outlier symbol, title, xlabel

plt.boxplot(tips['tip'], sym="bo")

plt.title('Box plot of tip')

plt.xticks([1], ['tip'])

plt.show()




다음으로 상자그림을 가로로 눕히고, 가운데 상자는 중앙값 부근에서 V자 형태로 골이 패이게(notch) 그려보겠습니다. 


 

# Horizontal Box plot with notched box & red color outliers

plt.boxplot(tips['tip'], 

            notch=1, # if 'True' then notched box plot

            sym='rs', # symbol: red square

            vert=0 # vertical : if 'False' then horizontal box plot

           )

plt.show()




한 개의 축에 여러 개의 연속형 변수(total_bill, tip)에 대한 여러 개의 상자 그림을 한꺼번에 그려보겠습니다. (다수 개의 연속형 변수, 한개의 그룹)



# Multiple box plots on one Axes

fig, ax = plt.subplots()

ax.boxplot([tips['total_bill'], tips['tip']], sym="b*")

plt.title('Multiple box plots of tips on one Axes')

plt.xticks([1, 2], 

           ['total_bill', 'tip'])

plt.show()

 




  (2) seaborn 으로 여러개 그룹에 대한 상자 그림 그리기 

      (Grouped box plots by seaborn)


요일(day) 그룹별러 팁(tip)에 대한 상자 그림을 같이 그려서 비교를 해보겠습니다. (한 개의 연속 형 변수, 다수 개의 그룹)



# Grouped boxplots by seaborn

import seaborn as sns


sns.boxplot(x="day"

            y="tip"

            data=tips)

plt.show()





위의 요일(day: Thur, Fri, Sat, Sun) 그룹에 더해 hue 옵션을 사용하여 성별(sex: Male, Female)에 따른 그룹을 추가하여 (총 4개 그룹 x 2개 그룹 = 8개 그룹) 별 팁(tip) 에 대한 상자 그림을 그려서 비교해보겠습니다. 



#  2 by 4 multi-Grouped boxplots by seaborn

sns.boxplot(x="day", 

            y="tip", 

            hue="sex",

            data=tips)


plt.show()

 





  (3) pandas 로 상자 그림 그리기


pandas의 DataFrame에 df.boxplot() 함수를 사용하여 상자 그림을 그릴 수 있습니다. (2)번에서 그렸던 그룹 별 상자 그림을 pandas 의 boxplot() 함수로 그려보면 아래와 같습니다. 



# Grouped boxplots by pandas

tips.boxplot(column=["tip"], by=["day", "sex"])

plt.show()


제 개인적인 생각으로는, 그래프의 가독성은 seaborn이 더 나아 보이고, 코드의 가독성은 pandas가 더 우수해보이네요. 


많은 도움이 되었기를 바랍니다. 


이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요.


다음번 포스팅에서는 막대 그래프 그리는 방법을 소개하겠습니다. 



728x90
반응형
Posted by Rfriend
,