Python 그래프와 시각화(matplotlib)

전창우·2023년 9월 18일
0

python for data analysis

목록 보기
8/23

정보를 시각화하는 것은 데이버 분석에 있어서 핵심 중 하나다.
시각화는 다음과 같은 이유로 필수적이다.

1)특잇값을 찾아낸다
2)데이터 변형이 필요한지 알아본다
3)모델에 대한 아이디어를 찾기 위한 과정의 일부이다.

matplotlib 라이브러리를 통해 데이터를 시각화 해보자.

figure와 subplot

matplotlib에서 그래프는 Figure 객체 내에 존재한다. 그래프를 위한 새로운 figure은 plt.figure를 사용해서 생성할 수 있다.

figure는 도화지로 생각하면 된다.

import matplotlib.pyplot as plt
fig= plt.figure()
#>><Figure size 640x480 with 0 Axes>

빈 figure로는 그래프를 그릴 수 없으므로, add_subplot을 사용해서 하나 이상의 subplots 객체를 생성해야한다.

subplot은 그래프를 그리기 위한 틀이라 생각하면 된다.
현재 하나의 도화지(fig)에 세 개의 틀(ax1,ax2,ax3)이 그려져 있다.

ax1=fig.add_subplot(2,2,1)#2*2의 크기, 1번째 서브플롯 선택
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
fig

plot 명령어로 그래프를 띄우면, matplotlib은 가장 최근의 figure와 그 서브플롯을 그린다. 만약 서브플롯이 없다면 하나를 생성한다.

plt.plot(np.random.randn(50).cumsum(),'k--')

'k--'옵션은 검은 점선을 그리기 위한 스타일 옵션이다.
fig_add_subplot 에서 반환되는 객체는 AxesSubplot인데, 각각의 인스턴스 메서드를 호출해서 다른 빈 서브플롯에 직접 그래프를 그릴 수 있다.

_=ax1.hist(np.random.randn(100),bins=20,color='k',alpha=0.3)
ax2.scatter(np.arange(30),np.arange(30)+3*np.random.randn(30))
fig

특정한 배치에 맞추어 여러 개의 subplot을 포함하는 figure를 생성하는 일은 흔하다. plt.subplots 메서드는 Numpy 배열과 서브플롯 객체를 새로 생성하여 반환한다.

fig, axes=plt.subplots(2,3)
axes
#array([[<Axes: >, <Axes: >, <Axes: >],
#       [<Axes: >, <Axes: >, <Axes: >]], dtype=object)

axes 배열은 2차원 배열로 쉽게 색인될 수 있어서 편리하게 사용할 수 있다. 서브플롯이 같은 x축 혹은 y축을 가져야 한다면 각각 sharex와 sharey를 사용해서 지정할 수 있다.
같은 범위 내에서 데이터를 비교해야 할 경우 특히 유용하다. pyplot.subplots의 자세한 옵션을 살펴보자.

인자설명
nrows서브플롯의 로우 수
ncols서브플롯의 컬럼 수
sharex모든 서브플롯이 같은 x축 눈금을 사용하도록 한다.
sharey모든 서브플롯이 같은 y축 눈금을 사용하도록 한다.
subplot_kwadd_subplot을 사용해서 서브플롯을 생성할 때 사용할 키워드를 담고 있는 사전
**fig_kwfigure를 생성할 대 사용할 추가적인 키워드 인자

서브플롯 간의 간격 조절하기

matplotlib은 서브플롯 간에 적당한 간격과 여백을 추가해준다.
이 서브플롯 간의 간격은 Figure 객체의 subplot_adjust 메서드를 사용해서 쉽게 바꿀 수 있다.

wspace와 hspace는 서브플롯 간의 간격을 위해 각각 figure의 너비와 높이에 대한 비율을 조절한다. 다음 코드는 간격을 주지 않는 그래플 생성한다.

fig,axes=plt.subplots(2,2,sharex=True,sharey=True)
for i in range(2):
    for j in range(2):
        axes[i,j].hist(np.random.randn(500),
                       bins=50,color='k',alpha=0.5)
plt.subplots_adjust(wspace=0,hspace=0) #kick

9.1.2 색상,마커,선 스타일

matplotlib에서 plot 함수는 x와 y 좌푯값이 담긴 배열과 추가적으로 색상, 선스타일 등을 나태는 '축약 문자열'을 인자로 받는다. 예를 들어, 녹색 점선으로 그려진 x,y 그래프는 아래처럼 나타낼 수 있다.

ax.plot(x,y,'g--')

g--와 같은 축약문자열로 스타일을 지정하는 방법을 편의를 위해 제공하고 있지만, 실무에서는 옵션을 좀 더 명시적으로 표현하여 사용한다.

ax.plot(x,y,linestyle='--',color='g')

선그래는 특정 지점의 실제 데이터를 돋보이게 하기 위해 마커를 추가하기도 한다. 마커도 축약 문자열에 포함시킬 수 있는데 색상 -> 마커스타일 -> 선 스타일 순서로 지정해주면 된다.

from numpy.random import randn
plt.plot(randn(30).cumsum(),'ko--')
#plt.plot(randn(30).cumsum(),color='k',marker='o',linestyle='dashed')

선 그래프를 보면 일정한 간격으로 연속된 지점이 연결되어 있다. 이것도 drawstyle 옵션을 이용해서 바꿀 수 있다.

data=np.random.randn(30).cumsum()
plt.plot(data,'k--',label='Defult')
plt.plot(data,'k--',drawstyle='steps-post',label='steps-post')
plt.legend(loc='best')

legend 메서드(범례)를 사용하기 위해서는 각각 label option을 지정해주어야한다.

9.1.3. 눈금, 라벨, 범례

그래프를 꾸미는 방법은 크게 2가지 있다.
1. pyplot 인터페이스를 사용해서 순차적으로 꾸미거나,
2. matplotlib이 제공하는 API를 사용해서 더 객체지향적인 방법으로 꾸미는 것이다.

pyplot 인터페이스는 대화형 사용에 맞추어 설계되었으며 표의 범위를 지정하거나 눈금 위치, 눈금 이름을 조절할 수 있다.

1) 아무런 인자 없이 메서드를 호출하게 되면, 현재 설정되어 있는 매개변수의 값을 반환한다.
2) 인자를 전달하면 매개변수의 값을 설정한다.

이 모든 메서드는 현재 활성화된 or 최근에 생성된 AxesSubplot 객체에 대해 동작한다.

제목, 축 이름, 눈금, 눈금 이름 설정하기

축을 꾸미는 방법을 설명하기 위해 무작위 값으로 간단한 그래프를 하나 생성해보겠다.

fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum())

x축의 눈금을 변경하기 위한 가장 쉬운 방법은 set_xticksset_xticklavels 메서드를 사용하는 것이다.

인자설명
set_xticks전체 데이터 범위에 따라 눈금을 어디에 배치할 지 지정
set_xticklabels다른 눈금 이름으로 지정
set_xlabelx축에 대한 이름을 지정

같은 메서드가 y축에도 똑같이 존재한다. figure에 각 메서드들을 적용시키며 체화하여 보자.

ticks=ax.set_xticks([0,250,500,750,1000])
labels=ax.set_xticklabels(['one','two','three','four','five'],
                         rotation=30,fontsize='small')
ax.set_title('my first matplotlib plot')
ax.set_xlabel("stage")
fig

범례 추가하기

범례는 그래프 요소를 확인하는 중요한 요소다. 범례를 표현하는 가장 쉬운 방법은 label 인자를 넘기는 것이다.

from numpy.random import randn
fig=plt.figure(); ax= fig.add_subplot(1,1,1)
ax.plot(randn(1000).cumsum(),'g',label='one')
ax.plot(randn(1000).cumsum(), 'r--', label='two')
ax.plot(randn(1000).cumsum(), 'b.', label='three')

ax.legend(loc='best')
legend 메서드에는 범례 위치를 지정하는 loc 인자를 제공한다. 최대한 방해되지 않는 곳에 두는 'best' 옵션이 이상적이다.

9.1.4 주석과 그림 추가하기

그래프에 추가로 글자나 화살표 혹은 다른 도형으로 자기만의 주석을 그리는 방법이 있다.
이 함수들은 그래프 내의 주어진 좌표(x,y)에 원하는 것을 그려준다. 2007년부터의 s&p 500 지수 데이터로 그래프를 그린 다음 text와 arrow를 함께 써서 주석을 그려보자.

from datetime import datetime
import pandas as pd

fig=plt.figure() #도화지 생성
ax=fig.add_subplot(1,1,1) #틀 생성

data=pd.read_csv('examples/spx.csv',index_col=0,parse_dates=True)
spx=data['SPX']

spx.plot(ax=ax,style='k-')

그래프를 생성하였으니, 2008년~2009년 사이에 있었던 재정 위기중 중요한 날짜를 주석으로 추가해보자.

ax.set_xlim([pd.Timestamp('2007-01-01'), pd.Timestamp('2011-01-01')])
ax.set_ylim([600, 1800])

ax.set_title('Important dates in the 2008-2009 financial crisis')
fig
set_xlim와 ylim 메서드의 시작과 끝 경계를 직접 지정하고, set_title 메서드로 그래프의 제목을 지정하였다. 해당 그래프를 통해 우리는 다음과 같은 인사이트를 얻을 수 있다. 그것을 주석으로 나타내보자.
 crisis_data=[
     (datetime(2007, 10, 11), 'Peak of bull market'),
    (datetime(2008, 3, 12), 'Bear Stearns Fails'),
    (datetime(2008, 9, 15), 'Lehman Bankruptcy')
]
for date, label in crisis_data:
    ax.annotate(label, xy=(date, spx.asof(date) + 75),
                xytext=(date, spx.asof(date) + 225),
                arrowprops=dict(facecolor='black', headwidth=4, width=2,
                                headlength=4),
                horizontalalignment='left', verticalalignment='top')

ax.annotate 메서드를 이용해서 x,y 좌표로 지정한 위치에 라벨을 추가했다.

도형을 그리려면 matplotlib의 일반 도형을 표현하기 위한 patches 객체를 이용하면 된다.
그래프에 도형을 추가하려면 patches 객체를 만든 후 서브플롯에 add_patch('객체')로 호출한다.

fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(1, 1, 1)
rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15,
				color='k', alpha=0.3)
circ = plt.Circle((0.7, 0.2), 0.15, 
				color='b', alpha=0.3)
pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]],
                color='g', alpha=0.5)
ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)
이런 도형을 잘 조합해서 여러 보기 좋은 그래프를 만들 수 있다.

9.1.5 그래프를 파일로 저장하기

활성화된 figure는 plt.savefig 메서드를 이용해서 파일로 저장할 수 있다. 이 메서드는 figure 객체의 savefig 인스턴스 메서드와 동일하다.

plt.savefig('figpath.svg')

확장자를 .svg 가 아닌 .pdf로 설정하여 PDF 파일을 얻을 수도 있다. 출판용 그래픽 파일을 생성하려 할 때 몇 가지 중요한 옵션으로 dpi와 bbox_inches가 있다. savefig 메서드의 옵션을 살펴보자.

인자설명
dpifigure의 인치당 도트 해상도.기본값은 100이며, 설정가능
bbox_inchesfigure에서 저장할 부분.'tight'를 지정하면 비어있는 공간을 모두 제거해준다.
fname파일 경로나 파이썬의 파일과 유사한 객체를 나타내는 문자열
format명시적인 파일 포맷('png','pdf','svg',...)
plt.savefig('figpath.png',dpi=400,bbox_inches='tight

9.1.6 matplotlib 설정

matplotlib은 출판물용 그래프를 만드는 데 손색이 없는데 기본 설정과 색상 스키마를 함께 제공한다. 거의 모든 기본 동작을 많은 전역 인자를 통해 설정이 가능하다.
matplotlib의 환경 설정 시스템은 두 가지 방법으로 다룰 수 있는데,
첫번째로 rc메서드를 사용해서 프로그래밍적으로 설정하는 방법이다.

plt.rc('figure',figsize=(10,10))

rc메서드의 첫 번째 인자는 설정하고자 하는 'figure','axes','xtick','ytick','grid','legend'및 다른 컴포넌트의 이름이다.
다음으로 설정할 값에 대한 키워드 인자를 넘기면 된다. 딕셔너리 객체를 이용해서 쉽게 작성할 수 있다.

font_option={
    'family':'monospace'
    'weight':'bold'
    'size':'small'
}
plt.rc('font',**font_options)

마치며

matplotlib은 사실 꽤 저수준의 라이브러리다. 데이터를 어떻게 보여줄 것인지부터 ~ 기본 컴포넌로 그래프를 작성해야 한다.
데이터를 시각화할 수 있는 다른 라이브러리로 통계 그래픽 라이브러리인 seaborn이 있다. 다음 로그에서는 seaborn 라이브러리을 살펴보자

0개의 댓글