본문 바로가기
SW 개발/Data 분석 (RDB, NoSQL, Dataframe)

Python Dataframe Visualization: matplotlib로 chart 그리기 (sample code)

by Kibua20 2021. 7. 28.

Python visualization lib 중 가장 많이 사용하고 유명한 패키지는 Matplotlib입니다. Matplotlib는 numpy, pandas dataframe과 호환 잘되며 다양한 종류의 데이터와 그래프를 쉽게 구현할 수 있습니다.  Matplotlib를 기반으로 보다 쉽게 구현할 수 있거나,  다양한 옵션을 제공하는 seaborn과 같은 lib도 매우 유용하게 사용할 수 있습니다. 

 

Matplotlib (출처:  https://matplotlib.org)

 

 

matplotlib Sample code 얻는 법

Matplotlib Gallery 사이트에서 matplotlib로 구현하고자 하는 Graph 먼저 선택합니다. Bar, Line, Stacked plot, Scatter 2D/3D, 등 많은 종류의 그래프를 지원하고 있습니다. 그중에서 구현하고자 하는 그래프를 선택하면 matplotlib의 sample code을 클립보드, py 파일, Jupyter Notebook파일 형태로 다운로드할 수 있습니다.   

 

matplotlib의 Gallery에서 Sample code 복사

 

예를 들어 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)입니다.  기본 설정 상태에서 한글을 표시하는 경우 아래 그림처럼 깨진 글자를 표시합니다.  

 

matplot에서 한글 깨짐 현상

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 설정에 필요한 참고 사이트는 아래와 같습니다.

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 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Random Number를 가지는 Pandas Dataframe 생성 (좋은 code와 나쁜 code 비교)

[SW 개발/Python] - Python Decorator를 이용한 함수 실행 시간 측정 방법 (Sample code)

[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Pandas Dataframe 처리 속도 향상을 위한 병렬 처리 방법: Swifter 모듈 (사용법 쉬움)

[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Pandas Dataframe Groupby() 함수로 그룹별 연산하기: Split, Apply, Combine

[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Python Pandas로 Excel과 CSV 파일 입출력 방법

[SW 개발/Python] - Python 정규식(Regular Expression) re 모듈 사용법 및 예제

[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Python KoNLPy와 WordCloud를 활용하여 WordCloud 생성하기 (Sample code 포함)

[SW 개발/Python] - Python: JSON 개념과 json 모듈 사용법

[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Python Selenium과 BeautifulSoup을 활용하여 Google PlayStore 사용자 리뷰 (댓글) 가져오기 (Sample Code 포함)




댓글