[matplotlib] 막대 그래프

  • 시각화

파이썬 시각화 라이브러리 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_lowery_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로 그리면 아래와 같이 나온다.

추천 글


댓글 남기기