지난 포스팅에서는 Python으로 연속형 자료에 대해 히스토그램박스 그래프를 그리는 방법을 소개하였습니다. 


이번 포스팅에서는 이산형 자료에 대해 범주(category), 계급(class)별로 빈도나 합계 등을 막대로 그려서 비교하는데 유용하게 사용하는 막대 그래프(bar chart)를 Python의 matplotlib, seaborn, pandas를 사용하여 그리는 방법을 소개하겠습니다. 


예제로 사용할 데이터셋은 seaborn에 내장되어 있는 tips 데이터셋입니다. 



# importing packages

import numpy as np

import pandas as pd


import matplotlib.pyplot as plt

import seaborn as sns

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

 



# Loading 'tips' dataset from seaborn

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.61FemaleNoSunDinner

4





  (1) matplotlib으로 막대 그리프 그리기 (bar chart by matplotlib)


tips DataFrame에서 요일(day)별로 tip 의 합계를 구해서 막대 그래프로 비교를 해보겠습니다. 



# Summary Statistics

tips_sum_by_day = tips.groupby('day').tip.sum()

tips_sum_by_day

day
Thur    171.83
Fri      51.96
Sat     260.40
Sun     247.39 

Name: tip, dtype: float64

 



label = ['Thur', 'Fri', 'Sat', 'Sun']

index = np.arange(len(label))

 



# Basic Bar Chart

plt.bar(index, tips_sum_by_day)

plt.title('Sum of Tips by Day', fontsize=20)

plt.xlabel('Day', fontsize=18)

plt.ylabel('Sum of Tips', fontsize=18)

plt.xticks(index, label, fontsize=15)

plt.show()

 




막대 그래프의 막대 색깔(bar color)과 투명도(transparency, alpha)를 조절해보겠습니다. 



# bar color, transparency

plt.bar(label, tips_sum_by_day, 

        color='red', # color

        alpha=0.5) # transparency

plt.show()

 





막대그래프의 막대 폭(width)을 좀더 좁게하고, 가운데 정렬 대신에 한쪽 끝으로 정렬(align)을 변경해보겠습니다. 



# bar width, align

plt.bar(label, tips_sum_by_day, 

        width=0.5, # default: 0.8

        align='edge') # default: 'center'

plt.show()

 




X축의 라벨이 갯수가 많거나 길이가 길 경우에는 X 축 라벨을 비스듬히 눕히거나 90도로 세우는 것이 보기에 더 효과적일 때가 있습니다. X축 라벨을 90도 회전시켜 보겠습니다.  



# X tick labels rotation

plt.bar(index, tips_sum_by_day)

plt.xlabel('Day', fontsize=18)

plt.xticks(index, label, fontsize=15, 

           rotation=90) # when X tick labels are long

plt.show()

 




X축의 라벨 개수가 많다면 막대그래프를 아예 가로로 눕혀서 그리는 것이(horizontal bar chart) 보기에 효과적일 때도 있습니다. 옆으로 누운 막대그래프는 plt.barh() 함수를 사용합니다. 



# Horizontal Bar Chart

plt.barh(index, tips_sum_by_day)

plt.title('Sum of Tips by Day', fontsize=18)

plt.ylabel('Day', fontsize=15)

plt.xlabel('Sum of Tips', fontsize=15)

plt.yticks(index, label, fontsize=13, rotation=0)

plt.show()




2개의 범주형 변수를 사용하여 각 클래스별로 빈도나 합계를 막대그래프로 비교하려면 (a) 위로 쌓은 막대그래프 (stacked bar chart)나, (b) 옆으로 나란히 놓은 막대그래프 (dodged bar chart)를 사용합니다. 


먼저, (a) 요일(day)과 성별(sex)의 두개 범주형 변수의 클래스별로 팁(tip)의 합계를 비교하기 위해 위로 쌓은 막대그래프 (stacked bar chart)를 그려보겠습니다. 



# summary by group

tips_sum_by_day_male = tips[tips['sex'] == 'Male'].groupby('day').tip.sum()

tips_sum_by_day_female = tips[tips['sex'] == 'Female'].groupby('day').tip.sum()


print('--Male--')

print(tips_sum_by_day_male);

print(' ')

print('--Female--')

print(tips_sum_by_day_female);

--Male--

day
Thur     89.41
Fri      26.93
Sat     181.95
Sun     186.78
Name: tip, dtype: float64
 
--Female--
day
Thur    82.42
Fri     25.03
Sat     78.45
Sun     60.61
Name: tip, dtype: float64




# Bar Chart by 2 categorical variables

# Stacked Bar Chart

label = ['Thur', 'Fri', 'Sat', 'Sun']

N = len(tips['day'].unique())

index = np.arange(N)

alpha = 0.5


p1 = plt.bar(index, tips_sum_by_day_male, color='b', alpha=alpha)

p2 = plt.bar(index, tips_sum_by_day_female, color='r', alpha=alpha,

             bottom=tips_sum_by_day_male) # stacked bar chart

plt.title('Stacked Bar Chart of Sum of Tips by Day & Sex', fontsize=20)

plt.ylabel('Sum of Tips', fontsize=18)

plt.xlabel('Day', fontsize=18)

plt.xticks(index, label, fontsize=15)

plt.legend((p1[0], p2[0]), ('Male', 'Female'), fontsize=15)

plt.show()

 




다음으로 (b) 요일(day)과 성별(sex)의 두개 범주형 변수의 클래스별로 팁(tip)의 합계를 비교하기 위해 옆으로 나란히 놓은 막대그래프를 그려보겠습니다. 두번째 막대 그래프에서 X축의 위치를 bar_width 만큼 오른쪽으로 바로 붙여서 그려지도록 index+bar_width 로 설정(빨간색 부분)해주면 됩니다. 



# Dodged Bar Chart (with same X coordinates side by side)

bar_width = 0.35

alpha = 0.5


p1 = plt.bar(index, tips_sum_by_day_male, 

             bar_width, 

             color='b', 

             alpha=alpha,

             label='Male')

p2 = plt.bar(index + bar_width, tips_sum_by_day_female, 

             bar_width, 

             color='r', 

             alpha=alpha,

             label='Female')


plt.title('Dodged Bar Chart of Sum of Tips by Day & Sex', fontsize=20)

plt.ylabel('Sum of Tips', fontsize=18)

plt.xlabel('Day', fontsize=18)

plt.xticks(index, label, fontsize=15)

plt.legend((p1[0], p2[0]), ('Male', 'Female'), fontsize=15)

plt.show()

 




  (2) seaborn 으로 막대 그래프 그리기 (bar chart by seaborn)


seaborn 패키지를 사용하여 위의 matplotlib 으로 그린 stacked bar chart를 그려보겠습니다. input 으로 사용하는 집계한 데이터프레임(aggregated DataFrame)을 먼저 만들고, sns.barplot() 함수에서 hue argument를 같이 사용하고 dodge=False를 설정해서 위로 쌓은 막대그래프를 그립니다. matplotlib 대비 코드가 한결 간결해졌습니다. 



tips_sum_by_day_sex = pd.DataFrame(tips.groupby(['day', 'sex']).tip.sum())

tips_sum_by_day_sex = tips_sum_by_day_sex.reset_index()

tips_sum_by_day_sex

daysextip
0ThurMale89.41
1ThurFemale82.42
2FriMale26.93
3FriFemale25.03
4SatMale181.95
5SatFemale78.45
6SunMale186.78
7SunFemale60.61

 



# Stacked Bar Chart

sns.barplot(x='day', y='tip', hue='sex', data=tips_sum_by_day_sex, 

           dodge=False) # stacked bar chart

plt.title('Stacked Bar Chart by Seaborn', fontsize='20')

plt.show()




seaborn으로 옆으로 나란히 두 개의 범주형 변수의 클래스별 막대그래프를 그려서 비교를 하려면 dodge=True (default setting) 을 해주면 됩니다. 



# Dodged Bar Chart

sns.barplot(x='day', y='tip', hue='sex', data=tips_sum_by_day_sex) # default : dodge=True

plt.title('Dodged Bar Chart by Seaborn', fontsize=20)

plt.legend(fontsize=12)

plt.show()





  (3) pandas 로 막대 그래프 그리기 (bar chart by pandas)


pandas로도 막대 그래프를 그릴 수 있는데요, 위의 matplotlib, seaborn으로 그릴 때 사용했던 데이터 집계 테이블 형태가 조금 다르므로 유심히 살펴보고 참고해서 사용하시기 바랍니다. 



# make a DataFrame

tips_sum_by_day = pd.DataFrame(tips.groupby('day').tip.sum())

tips_sum_by_day = tips_sum_by_day.reset_index()

daytip
0Thur171.83
1Fri51.96
2Sat260.40
3Sun247.39

 




pandas DataFrame에 df.plot.bar() 함수를 사용하거나 df.plot(kind='bar') 를 사용해서 막대그래프를 그립니다.  rot 는 X축 라벨의 회전(rotation) 각도를 설정하는데 사용합니다. 



# basic bar chart with a single column

tips_sum_by_day.plot.bar(x='day', y='tip', rot=0)

plt.show()





이번에는 pandas로 요일(day)과 성별(sex)의 두개 범주형 변수의 각 클래스별로 팁의 합계(summation of tip)를 집계하여 위로 쌓은 막대그래프(stacked bar chart)를 그려보겠습니다. 



# making a DataFrame with 'day' and 'sex' groups

tips_sum_by_day_sex = pd.DataFrame(tips.groupby(['day', 'sex']).tip.sum())

tips_sum_by_day_sex = tips_sum_by_day_sex.reset_index()


# pivot

tips_sum_by_day_sex_pivot = \

    tips_sum_by_day_sex.pivot(index='day', 

                              columns='sex', 

                              values='tip')

tips_sum_by_day_sex_pivot

sexMaleFemale
day
Thur89.4182.42
Fri26.9325.03
Sat181.9578.45
Sun186.7860.61




# Stacked Bar Chart by pandas

tips_sum_by_day_sex_pivot.plot.bar(stacked=True, rot=0)

plt.title('Stacked Bar Chart by Pandas', fontsize=20)

plt.show()




이번에는 pandas로 요일(day)별 성별(sex) 팁의 합계를 옆으로 나란히 막대그래프(dodged bar chart by pandas)로 그려서 비교를 해보겠습니다. 



# Dodged Bar Chart by pandas

tips_sum_by_day_sex_pivot.plot(kind='bar', rot=0)

plt.title('Dodged Bar Chart by Pandas', fontsize=20)

plt.legend(fontsize='12')

plt.show()

 



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


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



Posted by R Friend R_Friend

이번 포스팅에서는 하나의 연속형 변수에 대해서 분포 형태, 퍼짐정도, 이상치 여부 등을 시각화하고, 하나의 그룹 혹은 여러개의 그룹 간 비교하는데 유용한 상자 그림 (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가 더 우수해보이네요. 


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


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


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



Posted by R Friend R_Friend

지난번 포스팅에서는 하나의 그룹, 하나의 변수에 대한 히스토그램, 커널밀도곡선을 그리는 방법을 소개하였습니다. 


이번 포스팅에서는

(1) 여러개의 그룹에 대한 히스토그램, 커널밀도곡선 그리기

(2) 여러개의 변수에 대한 히스토그램, 커널밀도곡선 그리기

에 대해서 알아보겠습니다. 



먼저, matlplotlib.pyplot, seaborn 패키지를 importing하고, 예제로 사용할 iris 데이터셋을 불러오겠습니다. 



import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import seaborn as sns


# loading 'iris' dataset

iris = sns.load_dataset('iris')

iris.shape

(150, 5)


iris.head()

sepal_lengthsepal_widthpetal_lengthpetal_widthspecies
05.13.51.40.2setosa
14.93.01.40.2setosa
24.73.21.30.2setosa
34.63.11.50.2setosa
45.03.61.40.2setosa

 

iris.groupby('species').size()

species
setosa        50
versicolor    50
virginica     50
dtype: int64




iris는 붓꽃인데요, 아래처럼 versicolor, setosa, virginica의 3개 종(species) 그룹별로 각 50개씩 꽃잎 길이와 넓이, 꽃받침 길이와 넓이의 4개 변수를 측정한 데이터셋입니다. 


* image source: https://www.datacamp.com/community/tutorials/machine-learning-in-r



  (1) 여러개 그룹의 히스토그램, 커널밀도곡선 그리기


petal_length 변수에 대해서 setosa, versicolor, virginica 종의 3개 그룹(groups)의 히스토그램과 커널밀도곡선을 그룹별로 색깔을 다르게 하여 그려보겠습니다. 



# 1-1. Multiple histograms on the same axis

sns.distplot(iris[iris.species == "setosa"]["petal_length"], 

             color="blue", label="setosa")


sns.distplot(iris[iris.species == "versicolor"]["petal_length"], 

             color="red", label="versicolor")


sns.distplot(iris[iris.species == "virginica"]["petal_length"], 

             color="green", label="virginica")


plt.legend(title="Species")

plt.show()


 




만약 그룹 개수가 많아서 위에서처럼 일일이 코딩하기가 시간이 오래걸리고 반복되는 코드가 길게 늘어서는게 싫다면 아래처럼 for loop 을 사용해주면 됩니다. 


그래프의 제목, X축 이름, Y축 이름, 범례 이름을 설정하는 방법도 같이 소개합니다. 



# 1-2. Via for loop

grp_col_dict = {'setosa': 'blue', 

                    'versicolor': 'red', 

                    'virginica': 'green'}


# for loop of species group

for group in grp_col_dict:

    

    # subset of group

    subset = iris[iris['species'] == group]

    

    # histogram and kernel density curve

    sns.distplot(subset['petal_length'], 

                    hist = True, # histogram

                    kde = True,  # density curve

                    kde_kws = {'linewidth': 2}, 

                    color = grp_col_dict[group],

                    label = group)


# setting plot format

plt.title('Histogram & Density Plot by Groups')

plt.xlabel('Petal Length(unit:cm)')

plt.ylabel('Density')

plt.legend(prop={'size': 12}, title = 'Group')

plt.show()




  (2) 여러개 변수의 히스토그램, 커널밀도곡선 그리기


이번에는 sepal_width, sepal_length, petal_width, petal_length 의 4개 변수(variable)에 대해서 히스토그램과 커널밀도곡선을 그려보겠습니다. (단, 종(species)의 구분없이 전체 사용)


for loop 을 사용하였는데요, 위의 그룹 indexing 과 이번의 변수 indexing 부분이 다르다는 점 유심히 살펴보시기 바랍니다. 



# 2-1. Multiple histograms on the same axis

var_color_dict = {'sepal_length': 'blue', 

                      'sepal_width': 'red', 

                      'petal_length': 'yellow', 

                      'petal_width': 'green'}


# for loop

for var in var_color_dict:

    sns.distplot(iris[var],                  

                    color = var_color_dict[var], 

                    hist_kws = {'edgecolor': 'gray'}, 

                    label = var)


plt.legend(title = 'Variables')

plt.show()





위의 (2-1) 그래프는 1개의 window에 동일한 축을 사용하여 4개 변수의 히스토그램과 밀도곡선을 그리다보니 중첩이 되면서 좀 헷갈리고 보기에 어려운 점이 있습니다. 


이런 경우에 그래프를 각 변수별로 분리해서 4개의 window subplots에 하나씩 그려서 비교하는 것도 좋은 방법입니다. ax=axes[0, 0] 은 좌상, ax=axes[0, 1]은 우상, ax=axes[1, 0]은 좌하, ax=axes[1, 1]은 우하 위치의 subplot 입니다. 



# 2-2. Multiple histograms at separate windows

f, axes = plt.subplots(2, 2, figsize=(8, 6), sharex=True)

sns.distplot(iris["sepal_length"], color="blue", ax=axes[0, 0])

sns.distplot(iris["sepal_width"], color="red", ax=axes[0, 1])

sns.distplot(iris["petal_length"], color="yellow", ax=axes[1, 0])

sns.distplot(iris["petal_width"], color="green", ax=axes[1, 1])

plt.show()





for loop을 사용해서 그리려면 아래 코드를 참고하세요. 



var_color_dict = {'sepal_length': 'blue', 

                      'sepal_width': 'red', 

                      'petal_length': 'yellow', 

                      'petal_width': 'green'}


i = [0, 0, 1, 1]

j = [0, 1, 0, 1]


# for loop

f, axes = plt.subplots(2, 2, figsize=(8, 6), sharex=True)

for var, i, j in zip(var_color_dict, i, j):

    sns.distplot(iris[var],                  

                    color = var_color_dict[var],

                    ax = axes[i, j])

    

plt.show()



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


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



Posted by R Friend R_Friend

탐색적 데이터 분석 단계에서 변수의 분포, 중심 경향, 퍼짐 정도, 치우침 정도 등을 한눈에 살펴볼 수 있는 시각화 종류로 히스토그램이 많이 사용됩니다. 


이번 포스팅에서는 Python의 matplotlib.pyplot, seaborn, pandas를 이용해서 하나의 변수, 하나의 그룹에 대한 히스토그램(Histogram)을 그리는 방법을 소개하겠습니다. 


그리고 다음번 포스팅에서는 여러개의 변수, 여러개의 그룹별 히스토그램을 그리는 방법을 다루어보겠습니다. 


필요한 패키지를 import하고 데이터셋을 loading하겠습니다. 

예제로 사용할 데이터는 seaborn 패키지에 들어있는 iris 데이터세입니다. setosa, versicolor, virginica 종별로 50개씩, 총 150개의 붖꽃 관측치에 대해서 꽃받침(sepal)과 꽃입(petal)의 길이와 넓이를 측정한 자료입니다. 기계학습 공부할 때 약방의 감초처럼 분류나 군집분석 예제로 사용되곤 하는 바로 그 데이터셋입니다. 



import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import seaborn as sns


# Data Loading

iris = sns.load_dataset('iris')

iris.shape

(150, 5)

iris.head()
sepal_lengthsepal_widthpetal_lengthpetal_widthspecies
05.13.51.40.2setosa
14.93.01.40.2setosa
24.73.21.30.2setosa
34.63.11.50.2setosa
45.03.61.40.2setosa


iris.groupby('species').size()

species
setosa        50
versicolor    50
virginica     50
dtype: int64

 




  (1) matplotlib.pyplot 으로 히스토그램 그리기


plt.hist() 함수에 X변수의 데이터와 bin의 개수를 입력해주면 됩니다. 이렇 히스토그램을 그리면 그래프 뿐만 아니라 아래처럼 2개의 array와 <a list of Patch objects>가 같이 반환됩니다. 


히스토그램을 그릴 때는 bin의 개수를 적당히(?) 설정하는 것이 매우 중요합니다. bin 개수가 너무 적으면 분포가 뭉뚱그려지며, bin 개수가 너무 많으면 이빨빠지 빗처럼 보기에 이상해집니다. 대개의 경우 bins 값을 입력하지 않은채로 default 세팅으로 해서 그래프를 그려도 제법 보기에 좋게 나오는데요, 혹시 마음에 들지 않는다면 bins=x 값을 변경해가면서 여러번 시도를 해보시기 바랍니다. 



plt.hist(iris['sepal_width'], bins=10)



히스토그램만 보고 싶을 때는 아래처럼 n, bins, patches = plt.hist() 처럼 관측치 값, bin 개수, patch 객체를 n, bins, patches 에 별도로 할당해주면 됩니다. 



n, bins, patches = plt.hist(iris['sepal_width'], bins=10)

 


n, bins, patches

(array([ 4.,  7., 22., 24., 37., 31., 10., 11.,  2.,  2.]),
 array([2.  , 2.24, 2.48, 2.72, 2.96, 3.2 , 3.44, 3.68, 3.92, 4.16, 4.4 ]),
 <a list of 10 Patch objects>)





Y축을 빈도수(frequency)가 아니라 density로 하고 싶을 때는 density=True 를 설정해주면 됩니다. 



# Y axis as density

n, bins, patches = plt.hist(iris['sepal_width'], bins=10, density=True)





히스토그램의 색깔은 facecolor = 'blue' 식으로 설정해주며, alpha 는 투명도(0~1)를 조절할 때 사용합니다. alpha 가 0에 가까워질수록 투명해집니다. 



# facecolor, alpha

n, bins, patches = plt.hist(iris['sepal_width'], bins=10, 

                            density=True, 

                            facecolor='blue'

                            alpha=0.5)




X축과 Y축 이름은 plt.xlabel(), plt.ylabel() 함수로 지정하며, 제목은 plt.title()를 사용하여 추가할 수 있습니다. X축과 Y축의 범위를 강제로 지정해주고 싶으면 plt.axis(X축 시작, X축 끝, Y축 시작, Y축 끝)의 순서대로 값을 입력해줍니다. 



# Setting X, Y label and Title, axis

n, bins, patches = plt.hist(iris['sepal_width'], 

                            bins=10, 

                            density=True, 

                            facecolor='blue', 

                            alpha=0.5)

plt.xlabel('X bins')

plt.ylabel('Density')

plt.title('Histogram of Sepal Width')

plt.axis([1.5, 4.5, 0, 1.1])

plt.show()




  (2) seaborn 패키지로 히스토그램 그리기


seaborn 패키지의 distplot() 함수로 히스토그램을 그리니 density 기준의 히스토그램에 kernel density curve가 겹쳐져서 그래프가 그려졌습니다. 디폴트 세팅으로 그렸는데 bin 개수도 적당해보이고, 분포 곡선까지 겹쳐서 그려주니 편리하고 좋네요. (density curve와 겹쳐그려야 하므로 히스토그램은 frequency가 아니라 density 기준입니다.) 



sns.distplot(iris['sepal_width'])

plt.show()

 




물론 세부 옵션 설정을 통해서 그래프를 자유자재로 그릴 수 있습니다. 옵션 이름만 보면 무슨 기능인지 짐작할 수 있으므로 부연설명은 생략하겠습니다. 


kde=True 에서 kde는 Kernel Density Estimate 를 하여 커널 밀도 함수 곡선을 그리라는 뜻입니다. 


sns.distplot()에서 반환된 axis를 사용해서 seaborn histogram의 제목(title), X축 이름(X axis label), Y축 이름(Y axis label)을 설정할 수 있습니다. (ax.set_title(), ax.set_xlabel(), ax.set_ylabel())



# Kernel Density Curve with histogram

ax = sns.distplot(iris['sepal_width'], 

                      hist=True, 

                      kde=True, 

                      bins=10, 

                      color='blue', 

                      hist_kws={'edgecolor': 'gray'}, 

                      kde_kws={'linewidth': 2})

ax.set_title('Histogram of Sepal Width')

ax.set_xlabel('Sepal Width(cm)')

ax.set_ylabel('Density')

plt.show()




Kernel Density Curve만 그리고 싶다면 sns.distplot(x, hist=False) 라고 해서 그려도 되는데요, 좀더 많은 옵션을 사용하고 싶으면 아래처럼 sns.kdeplot() 함수를 사용하면 편리합니다. 



# Kernel Density Estimate Plot

sns.kdeplot(iris['sepal_width'],  

               shade=True, 

               bw=2, 

               label="Sepal Width")

plt.legend()

plt.show()





  (3) pandas.DataFrame.hist 를 이용한 히스토그램 그리기


pandas의 DataFrame에 아래처럼 바로 hist() 함수를 사용해서 히스토그램을 그릴 수 있습니다. matplotlib.pyplot.hist() 함수를 pandas가 가져다가 히스토그램을 그려주므로 (1)번의 plt.hist() 의 결과와 동일하게 나왔습니다. (디폴트 세팅은 grid=True 여서 격자로 그리드가 쳐져 있음)



# Histogram by pandas.DataFrame.hist

iris['sepal_width'].hist(bins=10, grid=False)

plt.show()



저는 개인적으로는 seaborn 의 그래프가 제일 이뻐보이기는 한데요, 여러 책의 예제 코드로 가장 많이 눈에 띄이는 것은 matplotlib.pyplot 이네요. 간단하게 쓰기에는 pandas.DataFrame.hist 가 손이 제일 덜 가구요. 


다음번 포스팅에서는 여러개의 변수/그룹에 대한 히스토그램 그리는 방법을 소개하겠습니다. 


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


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



Posted by R Friend R_Friend