안녕하세요. 문범우입니다.
이번 포스팅에서는 파이썬 기반 시각화 라이브러리인 matplotlib에 대해서 알아보도록 하겠습니다.
해당 내용은 flearning의 김길호님의 강의를 바탕으로 작성되었습니다.
https://www.flearning.net/courses/6
1. Matplotlib 이란?
matplotlib은 다양한 데이터를 많은 방법으로 도식화 할 수 있도록 하는 파이썬 라이브러리로써, 우리는 matplotlib의 pyplot을 이용하게 됩니다.
이는 mathworks에서 개발한 매트랩(MATLAB)과 비슷한 형태를 가지고 있습니다.
matplotlib을 이용하면 우리가 이전에 알아본 numpy나 pandas에서 사용되는 자료구조를 쉽게 시각화 할 수 있습니다.
matplotlib을 사용하기 위해서는 먼저 matplotlib을 설치하고 아래와 같이 import를 해주어야 합니다.
import matplotlib
import matplotlib.pyplot as plt
또한 jupyter notebook에서 그래프를 제대로 확인하기 위해서는 아래와 같은 매직 커맨드를 작성해주셔야 합니다.
%matplotlib inline
이러한 매직커맨드는 맨 뒤에 inline 이외에도 우리가 아래에서 사용하는 nbagg 등의 다양한 속성이 있습니다.
Matplotlib 기초¶
1. Matplotlib 이란?¶
import matplotlib
import matplotlib.pyplot as plt
%matplotlib nbagg
#위와 같은 것이 %로 시작하는 것을 jupyter notebook의 magic command라고 한다.
# %who는 변수명의 리스트를 보여주고 %magic 은 모든 매직명령어를 보여준다.
# 전체적인 magic 명령어에 대해서는 다음 블로그를 참고
# http://studymake.tistory.com/601
# matplotlib 을 jupyter notebook에서 사용할 때, plot의 이미지를 보여주기 위해 magic command를 사용하는데,
# 이때 우리가 사용하는 nbagg 이외에도 다음과 같은 요소를 사용할 수 있다.
# Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'notebook', 'wx', 'qt', 'nbagg','gtk', 'tk', 'inline']
# 사용되는 명령어에 대한 차이점이 정리되어 있는 사이트는 따로 찾지 못했지만
# 각각에 대해서는 matplotlib의 공식문서에서 참고 할 수 있는듯 하며,
# 우리가 사용하는 nbagg에 대해서는 다음 링크에서 확인할 수 있다.
# https://matplotlib.org/users/prev_whats_new/whats_new_1.4.html#the-nbagg-backend
import numpy as np
import pandas as pd
# Series를 통한 line plot 그리기
s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10))
s
# 위에서 정의한 s라는 시리즈에 대해서 line plot을 그리고 싶다면?
s.plot()
s 라는 Series에서의 index와 value를 통해 그래프가 그려졌다.
그래프 우측상단의 전원버튼을 누르기 전까지 우리는 해당 그래프를 interactive하게 조작할 수 있다.
# DataFrame을 통한 line plot 그리기
df = pd.DataFrame(np.random.randn(10, 4).cumsum(axis=0),
columns=["A", "B", "C", "D"],
index=np.arange(0, 100, 10))
df
df.plot()
# 하나의 열에 대해서만 보고 싶다면?
df['B'].plot()
Bar plot 그리기¶
s2 = pd.Series(np.random.rand(16), index=list("abcdefghijklmnop"))
s2
s2.plot(kind='bar')
# 가로방향의 bar plot그리기
s2.plot(kind='barh')
df2 = pd.DataFrame(np.random.rand(6, 4),
index=["one", "two", "three", "four", "five", "six"],
columns=pd.Index(["A", "B", "C", "D"], name="Genus"))
df2
df2.plot(kind='bar')
df2.plot(kind='barh', stacked=True)
위와 같이 Stacked 속성을 True로 설정하면, 하나의 인덱스에 대한 각 열의 값을 한줄로 쌓아서 나타내준다.
Histogram 그리기¶
# histogram은 index가 필요없다.
s3 = pd.Series(np.random.normal(0, 1, size=200))
s3
s3.hist()
x 축의 구간 개수를 bin이라고 한다.
이를 직접 설정할 수도 있다.
s3.hist(bins=50)
s3.hist(bins=100, normed=True)
# normed 속성을 True로 설정하면, 각 bin에 속하는 개수를 전체 개수로 나눈 비율, 즉 정규화 한 값을 bar의 높이로 사용하게 된다.
산점도(Scatter plot) 그리기¶
산점도의 경우에는 서로 다른 두 개의 독립변수에 대해 두 변수가 어떤 관계가 있는지 살펴보기 위해 사용된다.
x1 = np.random.normal(1, 1, size=(100, 1))
x2 = np.random.normal(-2, 4, size=(100, 1))
X = np.concatenate((x1, x2), axis=1)
X
df3 = pd.DataFrame(X, columns=["x1", "x2"])
df3
plt.scatter(df3['x1'], df3['x2']) # x1이 x축, x2가 y축
3. Plot 모양 변형하기¶
fig = plt.figure()
# 비어있는 figure가 생성된다.
# subplot 추가하기, add_subplot 에는 총 3가지 인자가 들어간다.
ax1 = fig.add_subplot(2, 2, 1)
# 첫번째 숫자와 두번째 숫자 : 우리가 figure를 어떤 크기로 나눌지에 대한 값이다. 즉 위의 같은 경우는 2,2 이므로 우리의 figure를 2x2로 나눈다는 뜻.
# 세번째 숫자 : 첫번째, 두번째 숫자로 나눈 figure에서 좌측상단으로 우측방향으로 숫자가 붙는다. 이때 우리가 add하고자 하는 subplot이 몇번째에 들어가는지를 나타낸다.
# 즉, 위와 같은 경우 figure는 다음과 같이 나누어진다.
# 1 2
# 3 4
# 이때 우리는 1위치에 subplot을 추가하고 해당 subplot을 ax1이라는 변수로 반환받는다.
ax2 = fig.add_subplot(2,2,2)
ax3 = fig.add_subplot(2,2,3)
plt.plot(np.random.randn(50).cumsum())
# 위치를 지정하지 않고 plot을 그리니 맨마지막에 그림이 그려진다.
# figure에 추가된 subplot상 맨 마지막에 위치한 곳에 그려지는 것이 아니라, 제일 마지막에 추가한 subplot에 그려진다.
# 2 -> 3 -> 1 순으로 subplot을 추가하여 테스트 해보면 1번 요소에 그려진다.
plt.plot(np.random.randn(200).cumsum())
# 강의에서는 한번더 위치 지정 없이 그리면 그 전의 요소에 그려진다고 했는데,
# 실제로 진행해보면 그냥 위의 것과 똑같이 제일 마지막에 추가한 subplot에 중복되서 그려진다.
# 그럼 우리가 원하는 위치에 그림을 그리기 위해서는?
# 위에서 add_subplot 을 할때 변수명을 지정하여 반환값을 받았다.
# 해당 변수를 통해 plot을 그리면 된다.
ax1.hist(np.random.randn(100), bins = 20) # bins는 x축 bar의 개수
ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))
# 또 다른 방법
fig, axes = plt.subplots(2,3)
# 위와 같이 만들면 2x3 subplot들을 가지는 figure를 만드는 것
# 이때 반환되는 값은 2개로써, figrue 자체와, 축
# 반환받은 axes에는 우리가 위에서 설정한 크기와 같은 shape의 리스트로 각 요소에는 subplot 객체가 들어있다.
axes
3-1. Plot 꾸미기¶
plt.plot(np.random.randn(50), color = 'g', marker='o', linestyle='--')
marker¶
값 마킹
"." point
"," pixel
"o" circle
"v" triangle_down
"^" triangle_up
"<" triangle_left
">" triangle_right
"8" octagon
"s" square
"p" pentagon
"*" star
"h" hexagon
"+" plus
"x" x
"D" diamond
line style¶
값 라인 스타일
"-" solid line
"--" dashed line
"-." dash-dotted line
":" dotted line
"None" draw nothing
# 굳이 각각에 대해서 언급해주지 않고, 아래와 같이 연속적으로 나타내줘도 된다.
plt.plot(np.random.randn(30), 'k.-')
fig, axes = plt.subplots(2,1)
data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop'))
data.plot(kind='bar', ax=axes[0], color='k', alpha=0.7) #plot 함수를 그릴때, figure에서 원하는 위치를 지정하기 위해 ax 속성을 사용
data.plot(kind='barh', ax=axes[1], color='g', alpha=0.3)
우리가 만들 plot의 눈금, 레이블, 범위 등을 지정 및 수정할 수 있다.
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum())
# 이때 그래프에서 나타내는 눈금을 tick이라고 한다.
# 즉, 위의 그래프의 x tick은 200이고 y tick은 10이다.
ax.set_xticks([0, 250, 500, 750, 1000])
# 눈금을 문자로 하기 위해서는?
labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], rotation = 30, fontsize='small')
# 제목 입력하기
ax.set_title('random walk plot')
# 라벨 입력하기
ax.set_xlabel('Stages')
ax.set_ylabel('Values')
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum(), 'k', label='one')
ax.plot(np.random.randn(1000).cumsum(), 'b--', label='two')
ax.plot(np.random.randn(1000).cumsum(), 'r.', label='three')
# 범례 표시하기
ax.legend(loc='best')
# loc는 범례가 위치할 곳을 의미한다. best를 주게 되면 현재 그래프에서 최적의 위치를 자동으로 찾는다.
x축 범위 및 y축 범위 수정하기
ax.get_xlim()
# 현재 그래프의 x축 범위를 가져온다.
# 이를 변경하려면,
ax.set_xlim([100,900])
ax.set_ylim([-100,100])
3. Matplotlib을 이용한 데이터시각화 맛보기¶
battles = pd.read_csv('game-of-thrones/battles.csv', sep=',')
deaths = pd.read_csv('game-of-thrones/character-deaths.csv', sep=',')
battles.head()
battles.columns
battles.shape
deaths.shape
deaths.columns
deaths.head()
book_nums_to_death_count = deaths['Book of Death'].value_counts().sort_index()
book_nums_to_death_count
ax1 = book_nums_to_death_count.plot(color = 'k', marker='o', linestyle='--')
# 모양 가다듬기
ax1.set_xticks(np.arange(1,6))
ax1.set_xlim([0,6])
ax1.set_ylim([0,120])
battles = battles.set_index(['name'])
battles.head()
large_battle_mask = battles['attacker_size'] + battles['defender_size'] > 10000
large_battles = battles.loc[large_battle_mask, ['attacker_size', 'defender_size']]
large_battles.shape
large_battles
ax2 = large_battles.plot(kind='barh', stacked=True, fontsize=8)
large_battles['attacker_pcts'] = large_battles['attacker_size'] / (large_battles['attacker_size'] + large_battles['defender_size'])
large_battles['defender_pcts'] = large_battles['defender_size'] / (large_battles['attacker_size'] + large_battles['defender_size'])
large_battles
ax3 = large_battles[['attacker_pcts', 'defender_pcts']].plot(kind='barh', stacked=True, fontsize=8)
battles
col_names = battles.columns[4:12]
col_names
# 각 가문이 얼마나 전투에 참여했는지 보기위해 먼저 col_names를 가져왔다.
# 이에 대해서 unique 처리를 하려고하는데, 이때 NaN값이 있으면 오류가 발생하므로 이를 먼저 처리한다.
# NaN을 None이라는 문자열로 대체할 것
house_names = battles[col_names].fillna("None").values
house_names[:5]
house_names = np.unique(house_names)
house_names
house_names = house_names[house_names != 'None']
house_names
houses_to_battle_counts = pd.Series(0, index=house_names)
houses_to_battle_counts
for col in col_names:
houses_to_battle_counts = houses_to_battle_counts.add(battles[col].value_counts(), fill_value = 0)
houses_to_battle_counts
ax4 = houses_to_battle_counts.hist(bins=10)
ax4
'AI & BigData > 데이터분석 관련' 카테고리의 다른 글
나이브 베이즈 분류(Naive Bayesian Classification) 란? (1) | 2018.07.07 |
---|---|
pandas(판다스) 기초 정리 (13) | 2018.06.08 |
numpy(넘파이) 기초 정리 (12) | 2018.06.07 |