안녕하세요? Justkode 입니다. 오늘은 Matplotlib에 대해서 알아보는 시간을 가져보도록 하겠습니다.
Matplotlib는 데이터 분석을 위해 만들어진 라이브러리로 Numpy, Pandas와 함께 많이 사용 됩니다. 혹은 머신 러닝, 딥러닝의 결과를 확인 할 때나, 이미지 처리의 결과를 확인 할 때 사용합니다.
오늘은 그래프를 그리고, 이미지를 시각화 하는 것에 대한 여러 가지 예제를 다뤄 보도록 하겠습니다.
터미널, cmd에서 다음 명령어를 실행합니다. (가상 환경이 있다면, 가상 환경 위에서 설치 합니다.)
pip3 install matplotlib
일단 필수적인 Module들을 Import 해 보겠습니다. Matplotlib을 사용 할 때는 Numpy, Pandas가 같이 사용 되므로, 가능 하면 같이 Import 하는 것을 권장 합니다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
가장 기본적인 Line Plot 예제 입니다. 이 예제 같은 경우에는 plt.subplots()
를 이용하여, subplot을 이용 하는 예제 입니다. ax.plot(x, y)
은 쉽게 생각 하자면, "subplot에 (x, y) 쌍에 대한 선을 긋는다." 라고 생각하면 됩니다. 밑에 있는 함수에 대해 추가 설명을 드리면 다음과 같습니다.
ax.set_xlim(start, end)
: x축의 시작 좌표와 끝 좌표를 설정 합니다.ax.set_ylim(start, end)
: y축의 시작 좌표와 끝 좌표를 설정 합니다.ax.set_xlabel(string)
: x축에 대한 라벨을 설정 합니다.ax.set_ylabel(string)
: y축에 대한 라벨을 설정 합니다.ax.set_title(string)
: 그래프의 타이틀을 설정 합니다.ax.grid()
: 그래프에 격자를 추가합니다.plt.show()
: 그래프를 출력 합니다.만약 plt.subplots()
를 사용 하지 않고, 단일 plot을 사용 한다면 plt
내부 메서드를 사용 하면 됩니다. ax.set_xlim()
같은 함수를 plt.xlim()
이런 식으로 바꿔주기만 하면 됩니다.
x = np.arange(0, 10, 0.01) # x축 좌표 입력, np.arange로 0~10, 0.01 간격으로
y = np.sin(x) # y축 좌표 입력, x의 각 Element에 sin 함수가 적용된 것을 반환
fig, ax = plt.subplots() # subplots 적용
ax.plot(x, y) # x, y 값 삽입
ax.set_xlim(0, 10) # x 범위
ax.set_xlabel("time") # x 라벨 설정
ax.set_ylim(-1.5, 1.5) # y 범위
ax.set_ylabel("value") # y 라벨 설정
ax.set_title("value per time") # 타이틀 설정
ax.grid() # 점자형 그래프 설정
plt.show()
Line Plot
다음 예제는 꺾은 선 그래프 예제 입니다. plt.plot()
(혹은 ax.plot()
) 에 색상과 마킹 옵션도 다음과 같이 추가 해 줄수 있습니다. 기타 옵션은 같습니다.
# subplot 없이 그냥 plt만 써도 가능
years = [2015, 2016, 2017, 2018, 2019]
rank = [5, 3, 2, 3, 4]
plt.plot(
years, # x축 데이터
rank, # y축 데이터
color='blue', # 선 색깔
marker='o', # 꼭짓점 설정
linestyle='solid' # 선 스타일 설정
)
plt.xlim(2014.5, 2019.5) # x 범위 설정 (start, end)
plt.ylim(6, 1) # y 범위 설정 (start, end)
plt.title("Tottenham Hotspur's EPL Rankings 2015-2019") # title 설정
plt.xlabel('year') # x축 레이블 설정
plt.ylabel('rank') # y축 레이블 설정
plt.show()
Line Plot
한 번에 여러 가지 선을 그리고 싶을 때는 어떻게 하면 될까요? 그냥 plt.plot()
을 여러 번 호출 하면 됩니다. 세 번째 파라미터로 색상과, 선에 대한 정보를 주석에 입력 한 것과 같이 기입 할 수 있으며, label
정보를 입력하여, 구분 할 수 있으며, plt.legend()
를 통해 범주 정보를 삽입 할 수 있습니다. loc
에 들어 간 파라미터에 따라 위치가 달라집니다.
dele = [7.35, 7.35, 7.09, 6.95, 6.89]
eriksen = [7.45, 7.53, 7.4, 7.08, 6.51]
son = [6.53, 7.14, 6.99, 7.1, 7.23]
kane = [7.53, 7.68, 7.6, 7.38, 7.2]
xs = [2015, 2016, 2017, 2018, 2019]
plt.plot(xs, dele, 'r-', label='Dele Alli') # x, y, 선 색깔 및 타입 (r: 빨강, -: 실선)
plt.plot(xs, eriksen, 'g--', label='Christian Eriksen') # (g: 초록, --: 파선)
plt.plot(xs, son, 'b-.', label='Heung-Min Son') # (b: 파랑 -.: 1점 쇄선)
plt.plot(xs, kane, 'k:', label='Harry Kane') # (k: 검정, -: 점선)
plt.xlim(2014.5, 2019.5) # x 범위 설정 (start, end)
plt.ylim(6, 8) # y 범위 설정 (start, end)
plt.legend(loc=8) # loc=8로 하단 중앙에 범례 설정
plt.xlabel("Year")
plt.ylabel("Rating")
plt.title("DESK's Annual rating")
plt.show()
Multiple Line Plot
아까 처음에 이용했던 plt.subplots()
를 이용 하여, 여러 개의 Subplot을 만들 수 있습니다. Subplot을 이용 하여, plot을 가로, 세로로 나누어서 Subplot을 만든 후에, 각 Subplot에 대해 그래프를 설정 해 줄 수 있습니다. plt.subplots()
는 Tuple을 반환 하는데, 두 번째 Element로 Input Parameter에 해당 하는 사이즈를 가진 Subplots를 반환 합니다.
x = np.arange(0, 10, 0.01) # x축 입력
y1 = np.sin(x) # y축 입력
y2 = np.sin(x ** 1.1) # y축 입력
fig, (ax1, ax2) = plt.subplots(2, 1) # subplots (row, col)
ax1.plot(x, y1) # x, y 값 삽입
ax2.plot(x, y2)
ax1.set_xlim(0, 10) # x 범위
ax2.set_xlim(0, 10)
ax1.set_ylim(-1.5, 1.5)
ax2.set_ylim(-1.5, 1.5)
ax2.set_xlabel("time")
ax1.set_ylabel("value") # y 라벨 설정
ax2.set_ylabel("value")
ax1.set_title("value per time") # 타이틀 설정
ax1.grid() # 점자형 그래프 설정
plt.show()
Multiple Subplots
2차원 Subplot은 다음과 같이 구현 가능 합니다.
x = np.arange(0, 10, 0.01) # x축 입력
y1 = np.sin(x) # y축 입력
y2 = np.sin(x ** 1.1) # y축 입력
y3 = np.sin(x ** 1.2) # y축 입력
y4 = np.sin(x ** 1.3) # y축 입력
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) # subplots (row, col)
ax1.plot(x, y1) # x, y 값 삽입
ax2.plot(x, y2)
ax3.plot(x, y3)
ax4.plot(x, y4)
for ax in [ax1, ax2, ax3, ax4]:
ax.set_xlim(0, 10)
ax.set_ylim(-1.5, 1.5)
ax3.set_xlabel("time")
ax4.set_xlabel("time")
ax1.set_ylabel("value") # y 라벨 설정
ax3.set_ylabel("value")
ax1.set_title("value per time") # 타이틀 설정
ax1.grid() # 점자형 그래프 설정
plt.show()
Multiple Subplots
막대 그래프는 plt.bar()
를 이용 할 수 있으며, 색상과 정렬(배치) 방식을 선택 할 수 있습니다.
x = list('abcde')
y = [2, 4, 5, 3, 7]
plt.bar(x, y, width=0.3, color='green', align='center')
plt.show()
Bar Plot
다음과 같이 같은 x값을 가진 여러 개의 plot을 배치 시킬 수 있습니다.
x = list('abcde')
y1 = [2, 4, 5, 3, 7]
y2 = [3, 6, 5, 8, 2]
# 'a', 'b', 'c'.. 는 숫자 value가 아니기 때문에 axis를 지정 해 주어야 함.
x_axis = np.arange(len(x))
plt.xticks(x_axis, x)
plt.bar(x_axis - 0.2, y1, width=0.3, color='red', align='center', label='y1')
plt.bar(x_axis + 0.2, y2, width=0.3, color='blue', align='center', label='y2')
plt.legend(loc=1)
plt.show()
Multiple Bar Plot
히스토그램 또한 구현 가능합니다. Pandas를 이용 하여 범위 별 x축 Index를 지정 하고, 해당하는 Value를 Count 하는 식으로 진행 합니다.
mu, sigma = 10, 1
s = np.random.normal(mu, sigma, 1000) # 가우시안 분포 사용
factor = pd.cut(pd.Series(s), [i for i in range(5, 16)]) # pd.cut
temp = pd.value_counts(factor).sort_index() # 분포에 대한 Count
xs = [i for i, _ in enumerate(temp.values)] # x축 index 생성
plt.bar(xs, temp.values) # 해당 인덱스에 일치하는 값을 가진, 바 형태 그래프 생성
plt.xlabel("range")
plt.ylabel("count")
plt.xticks([i for i, _ in enumerate(temp.index)], temp.index) # x 눈금 및 레이블 설정
plt.title("Histogram")
plt.ylim(0, 400) # y 범위 설정 (start, end)
for index, value in enumerate(temp.values):
plt.text(index - 0.3, value + 10, str(value)) # x 좌표, y 좌표, text
plt.show()
Histogram
혹은 plt.hist()
를 이용하여 빠르게 Histogram을 사용 할 수 있습니다. 첫 번째 파라미터로는 array-like
객체, 두 번째 파라미터로는 int
(자를 갯 수 입력, 자동으로 범위 할당) 혹은 array-like
(pd.cut
처럼 자르고 싶은 범위 할당)를 넣으면 됩니다.
# 대략적으로 빠르게
plt.hist(s, [i for i in range(5, 16)] , density=True) # target, int or sequence, density
plt.show()
Histogram
x, y 좌표가 있다면 plt.scatter()
를 통해 이렇게 점을 찍을 수도 있습니다. c parameter를 통해서 색상을 지정 해 줄 수 있습니다. (R,G,B 값 삽입) s parameter를 통해서 크기를 설정 해 줄 수 있습니다.
x = np.random.randn(10)
y = np.random.randn(10)
plt.scatter(x, y,
c=[np.random.choice(range(256), size=3) / 256 for i in range(10)],
s=[np.random.normal(100, 20) for i in range(10)]
)
for X, Y, index in zip(x, y, [i for i in range(10)]):
plt.annotate(index, # Text
xy=(X, Y), # 텍스트 X, Y 좌표
xytext=(5, -5), # 텍스트 이격
textcoords="offset points" # 좌표 point 기준으로 설정함)
)
plt.title("x and y")
plt.xlim(-3, 3)
plt.ylim(-3, 3)
plt.xlabel("x")
plt.ylabel("y")
plt.show()
Scatter
2D ndarray 에 대해 적용 할 수 있는 Heatmap을 사용 할 수 있습니다. 2D ndarray를 plt.imshow()
를 이용하여, 이미지처럼 출력합니다. 그 다음 plt.colorbar()
를 이용하여, 색상에 따른 값을 나타내는 컬러 바를 출력합니다.
x = list('abcde')
y = list('ijklm')
arr = np.random.randint(5, 20, (5, 5))
plt.xticks([i for i, _ in enumerate(x)], x)
plt.yticks([i for i, _ in enumerate(y)], y)
plt.xlabel("abcde")
plt.ylabel("ijklm")
plt.title("Heatmap Example")
plt.imshow(arr) # image와 유사한 데이터 표시
plt.colorbar() # 우측 컬러바 설정
plt.show()
Heatmap
이미지 파일을 출력 할 수 있습니다. matplotlib.image
를 임포트 한 이후, img.imread(image 경로)
를 통해 이미지를 ndarray
화 시킬 수 있습니다.
import matplotlib.image as img
fileName = './mushroom.jpeg'
ndarray = img.imread(fileName) # 256, 256, 3(RGB)
fig, ax = plt.subplots()
ax.imshow(ndarray)
plt.show()
Image
matplotlib
의 기능은 위에서 설명한 차트 외에도 3D Plot, Stack Bar Chart 다양한 기능이 있습니다. 구글 검색을 통해서도 다양한 예시를 볼 수 있고, matplotlib
을 쉽게 구현 한 third party package인 Seaborn 이라는 라이브러리도 있으니 참고 부탁드립니다. 다음 시간에는 SQL에 대해서 알아 보는 시간을 가져보도록 하겠습니다.