파이썬 시각화 라이브러리 matplotlib으로 막대 차트 그리는 방법을 정리했다.
막대 차트 그리기 (bar)
막대 차트는 plt.bar()
로 그린다.
bar 차트는 plot과 달리 x값에 항목을 문자열로 구성된 리스로 넣는 게 아니라, 0부터 시작하는 정수 리스트로 넣어주어야 하므로 리스트의 길이를 range로 잡아서 넣는 게 일반적이다. 그 후에 subplot
에서 set_xticks()
와 set_xticklabels()
를 통해 항목 이름을 넣어주면 된다.
from matplotlib import pyplot as plt days_in_year = [88, 225, 365, 687, 4333, 10756, 30687, 60190, 90553] plt.bar(range(len(days_in_year)), days_in_year) plt.show()

x축 눈금 레이블이 너무 긴 경우에는 rotation
을 활용해서 글자를 회전시킬 수 있다.
ax = plt.subplot() ax.set_xticks([0, 1, 2, 3, 4, 5, 6, 7, 8]) ax.set_xticklabels(['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto'], rotation=30)

단, x-label
을 설정하기 전에 먼저 x-ticks
을 설정해야 한다. 왜냐하면 막대 당 하나의 눈금이 붙는 게 기본 값이 아니기 때문이다. 특히 많은 막대를 그리는 경우에는 자연스럽게 눈금이 생략될 수 있다. x-label
앞에 x-ticks
을 설정하는 것을 건너 뛰면 잘못된 위치에 눈금이 생길 수도 있다.
막대 차트 나란히 그리기
막대 차트 두 개를 나란히 놓고 그리고 싶다면 어떻게 해야 할까. 예를 들면 이렇게.

x축 값을 잘 다뤄주면 된다. 좀 까다롭지만 리스트 컴프리헨션을 활용한 재밌는 코드가 등장한다.
t = 2 # There are two sets of data: A and B w = 0.8 # We generally want bars to be 0.8 n = 1 # A is first set of data d = 6 # There are 5 topics we're plotting x_values = [t*element + w*n for element in range(d)] # 함수 def create_x(t, w, n, d): return [t*x + w*n for x in range(d)]
예를 들어 n에 1과 2를 넣어서 각각 돌리면 각각 [0.8, 2.8, 4.8, 6.8, 8.8, 10.8]
, [1.6, 3.6, 5.6, 7.6, 9.6, 11.6]
와 같은 리스트가 생성된다. 이걸 x 눈금으로 놓고 막대 그래프 두 개를 그리는 방법이다.
예제로 확인해보자.
from matplotlib import pyplot as plt drinks = ["cappuccino", "latte", "chai", "americano", "mocha", "espresso"] sales1 = [91, 76, 56, 66, 52, 27] sales2 = [65, 82, 36, 68, 38, 40] n = 1 # This is our first dataset (out of 2) t = 2 # Number of dataset d = 6 # Number of sets of bars w = 0.8 # Width of each bar store1_x = [t*element + w*n for element in range(d)] plt.bar(store1_x, sales1) n = 2 # This is our second dataset (out of 2) t = 2 # Number of dataset d = 6 # Number of sets of bars w = 0.8 # Width of each bar store2_x = [t*element + w*n for element in range(d)] plt.bar(store2_x, sales2) plt.show()

이제 x축 눈금(xticks)을 손봐줘야 한다. 이건 두 x값들의 중간값으로 설정하면 된다.
글로 쓰자니 좀 복잡하군. 그냥 막대 차트 2개 나란히 그리는 코드를 처음부터 끝까지 짜서 예제로 첨부했다. 아래에서 확인하자.
from matplotlib import pyplot as plt topics = ['A', 'B', 'C', 'D', 'E'] value_a = [80, 85, 84, 83, 86] value_b = [73, 78, 77, 82, 86] def create_x(t, w, n, d): return [t*x + w*n for x in range(d)] value_a_x = create_x(2, 0.8, 1, 5) value_b_x = create_x(2, 0.8, 2, 5) ax = plt.subplot() ax.bar(value_a_x, value_a) ax.bar(value_b_x, value_b) middle_x = [(a+b)/2 for (a,b) in zip(value_a_x, value_b_x)] ax.set_xticks(middle_x) ax.set_xticklabels(topics) plt.show()

누적 막대 차트 그리기 (bottom)
누적 막대 차트 그리는 법을 알아보자.
그냥 plt.bar()
를 두 개 선언하면 되는데, 아래 깔릴 값으로 먼저 bar를 그리고, 그 다음 위에 올 값으로 bar를 그릴 때에는 bottom
에다가 아래 깔릴 값을 다시 넣어주면 된다. 이 위에 쌓아 올리겠다는 뜻으로 이해하면 편하다. (각 값이 무엇을 의미하는지 구분을 해야 하니 legend
를 사용해서 레이블을 달아주자.)
from matplotlib import pyplot as plt down = [1, 2, 2, 1, 2] top = [2, 3, 4, 2, 1] plt.bar(range(len(down)), down) plt.bar(range(len(top)), top, bottom=down) plt.legend([‘TOP’, ‘BOTTOM’] plt.show()

만약 100%의 누적 막대 차트를 그리고 싶다면 아래와 같은 예제를 참고하자. 예제에서는 합계가 30이다.
from matplotlib import pyplot as plt import numpy as np topics = ['one', 'two', 'three', 'four', 'five'] As = [6, 3, 4, 3, 5] Bs = [8, 12, 8, 9, 10] Cs = [13, 12, 15, 13, 14] Ds = [2, 3, 3, 2, 1] Fs = [1, 0, 0, 3, 0] c_bottom = np.add(As, Bs) d_bottom = np.add(c_bottom, Cs) f_bottom = np.add(d_bottom, Ds) x = range(len(topics)) plt.bar(x, As) plt.bar(x, Bs, bottom=As) plt.bar(x, Cs, bottom=c_bottom) plt.bar(x, Ds, bottom=d_bottom) plt.bar(x, Fs, bottom=f_bottom) ax = plt.subplot() ax.set_xticks(x) ax.set_xticklabels(topics) plt.title('TITLE') plt.xlabel('X LABEL') plt.ylabel('Y LABEL') plt.show()

오차 막대 표시하기 (yerr)
막대그래프 위에 오차 막대(error bar)를 표시해주고 싶을 때가 있다. 이때는 yerr
를 사용해서 값을 넣어주면 된다. 하나의 값을 넣을 수도 있지만, 리스트를 통해 각 항목에 해당하는 오차 막대를 각각 넣어주는 것도 가능하다. 오차 막대의 너비는 capsize
로 조절한다.
from matplotlib import pyplot as plt values = [10, 13, 11, 15, 20] yerr = [1, 3, 0.5, 2, 4] plt.bar(range(len(values)), values, yerr=yerr, capsize=10) plt.show()

음영 넣기 (fill_between)
오차 범위에 음영을 넣어주는 방법도 있다. bar에서도 사용할 수 있지만, 일반적인 plot에서 더 많이 사용하는 방식이다. 이렇게 추가하면 된다.
plt.fill_between(x_values, y_lower, y_upper, alpha=0.2)
x_values에는 plt.plot()
에 포함되는 x값 리스트를 넣어주고, y_lower
와 y_upper
에는 각각 음영을 칠할 범위 하한선, 상한선을 리스트로 넣어주면 된다. alpha
값은 음영 색의 투명도를 결정한다.
아래 예제를 보자.
from matplotlib import pyplot as plt months = range(12) month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] revenue = [16000, 14000, 17500, 19500, 21500, 21500, 22000, 23000, 20000, 19500, 18000, 16500] plt.plot(months, revenue) # plt.bar(months, revenue) ax = plt.subplot() ax.set_xticks(months) ax.set_xticklabels(month_names) y_lower = [i*0.9 for i in revenue] y_upper = [i*1.1 for i in revenue] plt.fill_between(months, y_lower, y_upper, alpha=0.2) plt.show()

bar로 그리면 아래와 같이 나온다.
