'multiple horizontal bar plots with fixed and shared x axis scale'에 해당되는 글 1건

  1. 2020.01.18 [Python] 여러개의 수평/수직 막대그래프를 축 단위를 고정하여 그리기 (multiple bar plots with fixed and shared axis scale)

이번 포스팅에서는 1. plt.subplot() 2. plt.subplots() 를 이용해서 


(1) (nrows=1, ncols=3)개의 복수의 하위 막대 그래프를 그리는 방법

     (multiple subplots of bar plots using plt.subplot())

(2) 복수의 막대 그래프 간에 y 축의 단위를 고정하는 방법 (fix y axis scale)

(3) 복수의 막대 그래프 간에 y 축의 이름을 공유하는 방법 (share y axis label)

(4) 복수의 하위 그래프 간 여백을 작게 하여 밀착해서 그리는 방법 (plots in tight layout)


을 소개하겠습니다. 


그리고 마지막에는 복수의 옆으로 누운 막대 그래프 (multiple horizontal bar plots) 를 그리는 방법을 소개하겠습니다. 


먼저 예제로 사용할 간단한 DataFrame을 만들어보겠습니다. 



import numpy as np

import pandas as pd

import matplotlib.pyplot as plt


# make a sample DataFrame

grp = ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']

col = ['x1', 'x2', 'x3'] * 3

val = [3.5, 4.2, 2.9, 0.5, 0.2, 0.3, 1.5, 2.5, 2.6]


df = pd.DataFrame({'grp': grp, 

                  'col': col, 

                  'val': val})


df

grpcolval
0ax13.5
1ax24.2
2ax32.9
3bx10.5
4bx20.2
5bx30.3
6cx11.5
7cx22.5
8cx32.6

 




  1. plt.subplot() 으로 복수의 막대 그래프 그리기


(1-1) (행 1개, 열 3개) 로 구성된 복수의 하위 막대 그래프 그리기 

        (multiple subplots of bar plots using plt.subplot())


plt.subplot(nrow, ncol, position) 의 형태로 행과 열의 위치에 여러개의 하위 그래프를 그릴 수 있습니다. 


아래의 예제에서는 고쳤으면 하는 3가지 문제점이 보이네요. 

첫째 문제는 Y 축의 단위(y axis scale)가 서로 다르다 보니 비교를 하기가 힘듭니다. 

둘째 문제는 X축과 Y축의 이름(label)과 단위 눈금(ticks)이 반복해서 나타나서 지저분해 보입니다. 

셋째 문제는 복수의 하위 그래프 간 간격이 떨어져 있어서 좀 작게 보입니다. 


아래에 차례대로 이들 문제를 해결해 보겠습니다. 



# (1-1) multiple bar plots with different y axis scale

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


for i, grp in enumerate(['a', 'b', 'c']):

    df_i = df[df['grp'] == grp]

    plt.subplot(1, 3, i+1)

    plt.bar(df_i['col'], df_i['val'], color='blue', alpha=0.5)

    plt.title('Group: %s' %grp, fontsize=18)

    plt.xlabel('X variable', fontsize=14)

    plt.ylabel('Value', fontsize=14)

    plt.xticks(fontsize=12)

    plt.yticks(fontsize=12)






(1-2) 복수의 막대 그래프 간에 y 축의 단위를 고정하는 방법 (fix y axis scale)


plt.ylim(min, max) 의 형태로 y 축의 단위를 설정 또는 고정 (set/ fix y axis scale) 할 수 있습니다. 



 # (1-2) Set fixed y axis scale and Share it together

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

max_val = np.ceil(max(df['val']))


for i, grp in enumerate(['a', 'b', 'c']):

    df_i = df[df['grp'] == grp]

    plt.subplot(1, 3, i+1)

    plt.bar(df_i['col'], df_i['val'], color='blue', alpha=0.5)

    plt.title('Group: %s' %grp, fontsize=18)

    plt.xlabel('X variable', fontsize=14)

    plt.ylabel('Value', fontsize=14)

    plt.xticks(fontsize=12)

    plt.yticks(fontsize=12)

    # set fixed y axis scale

    plt.ylim(0, max_val)





(1-3) 복수의 막대 그래프 간에  X, Y 축의 이름을 공유하는 방법 (share X and Y axis label)


if 조건문을 사용하여 X축의 이름(X label)은 중간 위치 (index = 1)의 하위 그래프만 나타나게 하고, Y축의 이름(Y label)은 첫번째 그래프(index = 0) 에만 나타나게 하면 X축과 Y축의 이름을 서로 공유한 것과 같은 효과를 낼 수 있습니다. 



# (1-3) Display only 1 X and Y label

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

max_val = np.ceil(max(df['val']))


for i, grp in enumerate(['a', 'b', 'c']):

    df_i = df[df['grp'] == grp]

    plt.subplot(1, 3, i+1)

    plt.bar(df_i['col'], df_i['val'], color='blue', alpha=0.5)

    plt.title('Group: %s' %grp, fontsize=18)

    

    # display only 1 X and Y label

    if i == 1:

        plt.xlabel('X variable', fontsize=14)

    if i == 0:

        plt.ylabel('Value', fontsize=14)

    if i != 0:

        plt.yticks([])

    

    plt.xticks(fontsize=12)

    plt.yticks(fontsize=12)

    plt.ylim(0, max_val)





(1-4) 복수의 하위 그래프 간 여백을 작게 하여 밀착해서 그리는 방법 (plots in tight layout)


plt.tight_layout() 메소드를 이용하여 복수의 하위 그래프 간 여백 간격을 좁게하여 밀집된 형태로 좀더 크게 복수의 그래프를 그릴 수 있습니다. 



# (1-4) Display multiple plots in Tight Layout

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

max_val = np.ceil(max(df['val']))


for i, grp in enumerate(['a', 'b', 'c']):

    df_i = df[df['grp'] == grp]

    plt.subplot(1, 3, i+1)

    plt.bar(df_i['col'], df_i['val'], color='blue', alpha=0.5)

    plt.title('Group: %s' %grp, fontsize=18)

    

    # display only 1 X and Y label

    if i == 1:

        plt.xlabel('X variable', fontsize=14)

    if i == 0:

        plt.ylabel('Value', fontsize=14)

    if i != 0:

        plt.yticks([])

    

    plt.xticks(fontsize=12)

    plt.yticks(fontsize=12)

    plt.ylim(0, max_val)


# display in tight layout

plt.tight_layout()





  2. plt.subplots() 로 복수의 막대 그래프 그리기


plt.subplots() 는 위의 plt.subplot() 보다 좀더 적은 코드로 깔끔하게 복수의 하위 막대그래프를 그릴 수 있습니다. 

  • (nrows, ncols) 로 하위 그래프를 그릴 행과 열을 지정해줍니다. 
  • sharey=True 로 y 축 공유, sharex=True 로 복수 그래프 간 x 축을 공유할 수 있습니다. (편리!)
  • if 조건문과 함께 사용해서 ax.set_ylabel(), ax.set_xlabel() 로 y축과 x축의 이름을 하나만 나타나게 하였습니다. 
  • plt.tight_layout() 로 복수의 하위 그래프 간 여백을 좁게 해서 그래프를 그렸습니다. 


# (2-1) Multiple bar plots

# (2-2) Use fixed y axis scale

# (2-3) Display only 1 X and Y label

# (2-4) Display multiple plots in Tight Layout

fig, axes = plt.subplots(nrows=1

                         , ncols=3

                         , sharey=True

                         , figsize=(12,6))


grp = ['a', 'b', 'c']


for i, ax in enumerate(axes):

    df_i = df[df['grp'] == grp[i]]

    ax.bar(df_i['col'], df_i['val'], color='blue', alpha=0.5)

    ax.set_title("Group: {grp}".format(grp=grp[i]), fontsize=18)

    if i == 0:

        ax.set_ylabel("Value", fontsize=14)

    if i == 1:

        ax.set_xlabel("X variable", fontsize=14)

        

plt.tight_layout()





  3. 복수의 옆으로 누운 막대 그래프 (multiple horizontal bar plot) 그리기


ax.barh() 를 사용하여 옆으로 누운 막대 그래프 (horizontal bar plot)을 그렸으며, 복수개의 하위 그래프 그리는 방법은 2번에서 소개한 plt.subplots() 함수를 차용하였습니다. 


이때 옆으로 누운 막대 그래프이기 때문에, 가독성을 높이기 위해서 그룹의 이름을 제목(title)이 아니라 Y 축 이름(y label) 에 표시를 하였습니다. 



# Horizontal Multiple Bar Plots using plt.subplots()

fig, axes = plt.subplots(nrows=3

                         , ncols=1

                         , sharex=True

                         , figsize=(8,10))


grp = ['a', 'b', 'c']


for i, ax in enumerate(axes):

    df_i = df[df['grp'] == grp[i]]

    ax.barh(df_i['col'], df_i['val'], color='blue', alpha=0.5)

    #ax.set_title("Group: {grp}".format(grp=grp[i]), fontsize=18)

    ax.set_ylabel("Group: {grp}".format(grp=grp[i]), fontsize=18)

    if i == 2:

        ax.set_xlabel("Value", fontsize=14)

        

plt.tight_layout()


 



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

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



728x90
반응형
Posted by Rfriend
,