Python visualization lib 중 가장 많이 사용하고 유명한 패키지는 Matplotlib입니다. Matplotlib는 numpy, pandas dataframe과 호환 잘되며 다양한 종류의 데이터와 그래프를 쉽게 구현할 수 있습니다. Matplotlib를 기반으로 보다 쉽게 구현할 수 있거나, 다양한 옵션을 제공하는 seaborn과 같은 lib도 매우 유용하게 사용할 수 있습니다.
matplotlib Sample code 얻는 법
Matplotlib Gallery 사이트에서 matplotlib로 구현하고자 하는 Graph 먼저 선택합니다. Bar, Line, Stacked plot, Scatter 2D/3D, 등 많은 종류의 그래프를 지원하고 있습니다. 그중에서 구현하고자 하는 그래프를 선택하면 matplotlib의 sample code을 클립보드, py 파일, Jupyter Notebook파일 형태로 다운로드할 수 있습니다.
예를 들어 Horizontal Bar chat를 구현해야 하는 경우 Matplotlib Gallery 사이트에서 복사한 Python code는 아래와 같습니다.
"""
===================
Horizontal bar chart
This example showcases a simple horizontal bar chart.
** 출처 *** https://matplotlib.org/stable/gallery/index.html
====================
"""
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
plt.rcdefaults()
fig, ax = plt.subplots()
# Example data
people = ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')
y_pos = np.arange(len(people))
performance = 3 + 10 * np.random.rand(len(people))
error = np.random.rand(len(people))
ax.barh(y_pos, performance, xerr=error, align='center')
ax.set_yticks(y_pos)
ax.set_yticklabels(people)
ax.invert_yaxis() # labels read top-to-bottom
ax.set_xlabel('Performance')
ax.set_title('How fast do you want to go today?')
plt.show()
matplotlib에서 한글 깨짐 현상
matplotlib에서 기본으로 사용하는 font는 영문 폰트(DejaVu Sans)입니다. 기본 설정 상태에서 한글을 표시하는 경우 아래 그림처럼 깨진 글자를 표시합니다.
Defautl font를 한글 폰트로 변경하면 쉽게 수정이 가능합니다. 우분투 기준으로 font 만 변경하는 내용은 아래와 같이 matplotlib rc 값에서 default font를 한글을 지원하는 '나눔 고딕'으로 설정합니다. 상세 내용은 링크를 참조해주세요. 추가적인 matplotlib의 default style은 https://matplotlib.org/stable/users/dflt_style_changes.html 에서 설명되어 있습니다.
# Font cache를 삭제
$ rm -rf ~/.cache/matplotlib/*
from matplotlib import font_manager, rc
# 나눔 폰트 font 확인
font_list = [f.name for f in matplotlib.font_manager.fontManager.ttflist if 'Nanum' in f.name]
# default폰트 확인
rc('font', family='NanumGothic')
matplotlib에서 마이너스 부호 (유니코드) 깨짐 현상
matplotlib에서 마이너스 기호를 출력하는 경우 한글과 유사하게 정상적으로 출력이 되지 않습니다. 수정해야 하는 내용은 아래와 같습니다.
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
# minus symbol 깨짐
plt.rcParams['axes.unicode_minus'] = False
matplotlib에서 color map 설정
color map 설정에 필요한 참고 사이트는 아래와 같습니다.
- # color map: https://matplotlib.org/stable/tutorials/colors/colormaps.html
- # color: https://seaborn.pydata.org/generated/seaborn.color_palette.html
- # edge color: https://matplotlib.org/3.2.1/gallery/color/named_colors.html
Bar chart 경우 색상을 지정하기 위해서는 plot.bar()에서 color 값을 설정할 수 있습니다.
#color map 가죠 오기
cmap = plt.get_cmap(color_map)
# bar plot
plt.bar(color=cmap(normalized_df_values) )
matplotlib에서 layout 깨지는 경우 수정 방법
matplotlib에서 여러 개의 graph를 생성하는 경우 간헐적으로 Graph layout이 깨지는 경우가 있습니다. 이 경우에는 plt.tight_layout() 함수를 호출해서 그래프 객체의 layout 을 다시 계산합니다.
#matplot layout 수정
plt.tight_layout()
matplotlib에서 그래프를 파일로 저장
matplotlib에서 graph를 파일로 저장하는 것은 plt.savefig() 함수를 사용합니다.
# pngName로 저장
plt.savefig(pngName)
matplotlib에서 Memery 해제
matplotlib에서 graph 내용을 초기화하는 경우 plt.clf() 함수를 사용합니다. Python 언어적 특성 상 객체에 대한 garbage collectiond을 지원하지만, python code 내에서 동일 객체를 재 사용하면 이전 fig의 내용이 다음 fig와 합쳐져 의도하지 않는 graph가 나올 수 있습니다. 이 경우에는 Graph를 파일에 저장하고 plt.figure 객체의 내용을 초기화해야 합니다.
# clear fingure after save
plt.clf()
지금까지 설명한 내용을 하나의 함수로 구현하면 다음과 같습니다. Panas Dataframe을 parameter로 받아서 box chart를 그리는 내용입니다.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
# ---------------------------------------------------------------------------------------------------------------------------------------------
class chart_limit:
def __init__(self):
self.min_x = 0
self.max_x = 0
self.min_y = 0
self.max_y = 0
def __init__(self, min_x, max_x, min_y, max_y):
self.min_x = min_x
self.max_x = max_x
self.min_y = min_y
self.max_y = max_y
def x(self):
return self.min_x, self.max_x
def y(self):
return self.min_y, self.max_y
def normalize_y(self, value):
return (value - self.min_y) / (self.max_y - self.min_y)
def normalize_x(self, value):
return (value - self.min_x) / (self.max_x - self.min_x)
# ---------------------------------------------------------------------------------------------------------------------------------------------
def box_chart(df, title='Title', x_label='Date', y_label='Value', lim=chart_limit('2020-01', '2021-06', -1,1), color_map='RdYlBu', pngName=None, showPng=False):
# 한글 깨짐
rc('font', family='GulimGothic')
# minus symbol 깨짐
plt.rcParams['axes.unicode_minus'] = False
# x축, y축의 최대/최소값 설정
plt.xlim (lim.x())
plt.ylim (lim.y())
# color map: https://matplotlib.org/stable/tutorials/colors/colormaps.html
# color: https://seaborn.pydata.org/generated/seaborn.color_palette.html
# edge color: https://matplotlib.org/3.2.1/gallery/color/named_colors.html
cmap = plt.get_cmap(color_map)
# bar plot
df.plot.bar(color=cmap(lim.normalize_y(df)))
# chart 제목 설정
if title:
plt.title(title)
# x축 label설정
if x_label:
plt.xlabel(x_label)
# y축 label설정
if y_label:
plt.ylabel(y_label)
# layout update
plt.tight_layout()
# save to png
if pngName:
plt.savefig(pngName)
# clear fingure after save
plt.clf()
관련 글:
[SW 개발/Python] - Python Decorator를 이용한 함수 실행 시간 측정 방법 (Sample code)
[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Python Pandas로 Excel과 CSV 파일 입출력 방법
[SW 개발/Python] - Python 정규식(Regular Expression) re 모듈 사용법 및 예제
댓글