Python

[Python] 데이터 시각화 - Matplotlib

라딘 2022. 8. 3. 12:02

데이터 시각화 - Matplotlib

 

0. Matplotlib

- 파이썬의 대표적인 과학 계산용 그래프 라이브러리입니다.

- 판다스에 연계되어있어 사용하기 편리합니다.

 

Matplotlib 라이브러리는 보통 아래와 같은 코드로 불러옵니다.

#기본 import 라이브러리
import matplotlib as mpl  # 기본 설정 만지는 용도
import matplotlib.pyplot as plt  # 그래프 그리는 용도
import matplotlib.font_manager as fm  # 폰트 관련 용도

 

- 한글 폰트 설정

Matplotlib는 기본적으로 한글 폰트를 지원하지 않기 때문에 따로 설정해주어야 합니다.

 

1) matplotlib에서 사용할 수 있는 폰트를 담아두는 위치를 찾아 해당 위치에 사용할 한글폰트 ttf파일을 넣어줍니다.

    일반적으로 나눔고딕 폰트를 많이 사용합니다.

print(mpl.matplotlib_fname())

 

2) 변경된 내용이 인식될 수 있도록 아래 경로에 있는 fontlist 파일을 삭제해줍니다.

print(mpl.get_cachedir())

 

3) matplotlib의 기본 설정을 한글 폰트로 바꿔주는 코드를 실행합니다.

#한글 폰트 설정
plt.rc('font', family='NanumGothic') 
#-기호 깨짐 현상 방지를 위한 설정
plt.rc('axes', unicode_minus=False)

 

- 그래프 기본 구성

그래프는 기본적으로 배경(figure)과 축(axes)으로 구성되어 있습니다.


plt.figure: 축과 그래픽, 텍스트, 레이블을 표시하는 모든 객체를 포함하는 컨테이너
plt.axes: 눈금과 레이블이 있는 테두리 박스

plt.figure()  #도화지를 만들고
plt.axes()  #축을 그 위에 그립니다.

 

1. Line graph

x축과 y축에 대응하는 값을 넣어주면 각 점을 선으로 연결해서 선 그래프를 그려줍니다.

plt.plot(x, y)

x = [0, 2, 4, 6, 8]
y = [1, 2, 3, 4, 5]

plt.plot(x, y);  # x축과 y축에 대응하는 값을 넣으면 선으로 연결해줌
                 #세미콜론을 넣으면 주소를 출력하지 않음

 

선 위에 입력한 각각의 점을 도형으로 찍어주는 marker 옵션을 이용할 수 있습니다.

지정할 수 있는 값들은 's', 'o', '^' 등이 있습니다.

 

마커와 관련된 추가적인 옵션들은 다음과 같습니다.

 

markersize, ms : 마커사이즈

markeredgecolor, mec: 마커 선 색깔

markeredgewidth, mew: 마커 선 굵기

markerfacecolor, mfc: 마커 내부 색깔

plt.plot(x, y, marker='s');  #선 위에 각각의 점을 'square'로 찍어줌

 

선의 종류를 지정해주는 linestype 옵션도 사용할 수 있습니다.

'-'(solid), '--'(dashed), '-.'(dashdot), '.'(dotted) 등으로 선의 종류를 선택할 수 있습니다.

plt.plot(x, y, linestyle = 'dashed');  #linestype = '--'와 동일

 

그래프를 작성하는 코드를 여러개 넣고 동시에 실행하면 한 도화지에 해당 그래프들이 모두 그려지게 됩니다.

그래프마다 옵션을 다르게 두고 어떻게 그려지는지 하나의 도화지에서 확인해볼 수 있습니다.

#30개의 수를 랜덤으로 선정하고 누적합을 그래프로 나타냄
plt.plot(np.random.randn(30).cumsum(), linestyle='--', marker='^')  #파란색 그래프
plt.plot(np.random.randn(30).cumsum(), linestyle='--', marker='x')  #노란색 그래프
plt.plot(np.random.randn(30).cumsum(), linestyle='--')  #초록색 그래프

 

그래프의 색을 지정해주는 옵션도 존재합니다.

color 옵션을 통해 지정할 수 있으며 약자나 full name, 컬러코드를 통해 지정할 수 있습니다.

plt.plot(np.random.randn(30).cumsum(), color='g') # 자체적으로 지정한 컬러의 약자
plt.plot(np.random.randn(30).cumsum(), color='green') # full name
plt.plot(np.random.randn(30).cumsum(), color='#DC7761') # 컬러코드로도 표현할 수 있습니다

 

지금까지 사용했던 옵션들을 모두 한꺼번에 적용한 그래프를 그려봅니다.

plt.plot(np.random.randn(30).cumsum(), 'r^-')  
#marker, color, linestyle을 한꺼번에 지정해줘도 알아서 인식해서 그래프를 그려줌

 

2. Scatter Plot

산점도는 데이터의 좌표를 점으로 표현하는 그래프로서, 두 변수 사이의 관계를 확인할 때 적절합니다.

plt.scatter에도 plot에서 사용했던 marker와 color 옵션을 동일하게 사용할 수 있습니다.

 

plt.scatter(x, y)

 

x1 = [2, 3, 4]
y1 = [5, 5, 5]

x2 = [1, 2, 3, 4, 5]
y2 = [2, 3, 2, 3, 4]
y3 = [6, 8, 7, 8, 7]

plt.scatter(x1, y1)
plt.scatter(x2, y2, marker = 'v', color = 'r')
plt.scatter(x2, y3, marker = '^', color = 'm')
plt.title('Scatter Plot Example')
plt.show()

 

iris데이터를 불러와서 변수간의 관계를 산점도로 간단하게 시각화해 보겠습니다.

#데이터 불러오기
import seaborn as sns
iris = sns.load_dataset('iris')

#데이터셋을 종별로 분류
iris1 = iris[iris['species'] == 'setosa']
iris2 = iris[iris['species'] == 'virginica']
iris3 = iris[iris['species'] == 'versicolor']

#sepal_length와 sepal_width의 관계를 종별로 나눠서 시각화
plt.scatter(iris1['petal_length'], iris1['petal_width'], marker = '^', color = 'r')
plt.scatter(iris2['petal_length'], iris2['petal_width'], marker = 's', color = 'g')
plt.scatter(iris3['petal_length'], iris3['petal_width'], color = 'b')

petal_length가 길어질수록 petal_width도 넓어지는 관계가 존재하는 것을 확인할 수 있습니다.

또한 종별로 petal_length와 petal_width에 뚜렷한 차이가 존재함을 대략적으로 확인할 수 있습니다.

 

3. Bar Graph

바 그래프는 범주형 변수에서 각각의 범주가 나타난 빈도를 표시하기에 적합한 그래프입니다.

x축에 있는 값들을 y축에 있는 숫자(빈도)만큼의 막대로 보여줍니다.

plt.bar(x, y)

#데이터 생성
x1 = [1, 3, 4, 5, 6, 7, 9]
y1 = [4, 7, 2, 4, 7, 8, 3]  #빈도를 표시

x2 = [2, 4, 6, 8, 10]
y2 = [5, 6, 2, 6, 2]

plt.bar(x1, y1)

x1 = [1, 3, 4, 5, 6, 7, 9]
y1 = [4, 7, 2, 4, 7, 8, 3]

x2 = [2, 4, 6, 8, 10]  #6에는 두 값이 모두 들어가기 때문에 바그래프가 겹치게 됨
y2 = [5, 6, 2, 6, 2]

plt.bar(x1, y1, color='b')
plt.bar(x2, y2, color='g');

 

4. Histogram

바 그래프는 연속형 변수의 분포를 나타낼 수 있는 그래프입니다.

bin 옵션을 통해 막대(구간)의 수를 정할 수 있습니다.

plt.hist(x, y)

n = np.random.randn(1000)  #랜덤 함수로 숫자 1000개 선정
plt.hist(n)

plt.hist(n, bins = 50);  #구간의 개수를 50개로 지정

plt.hist(n, cumulative = True, bins = 20);  #누적그래프

 

5. Stack Plot

idxes = [ 1,  2,  3,  4,  5,  6,  7,  8,  9]
arr1  = [23, 40, 28, 43,  8, 44, 43, 18, 17]
arr2  = [17, 30, 22, 14, 17, 17, 29, 22, 30]
arr3  = [15, 31, 18, 22, 18, 19, 13, 32, 39]

plt.stackplot(idxes, arr1, arr2, arr3, colors= ['r', 'g', 'b'])
plt.title('Stack Plot Example')

 

6. Pie Chart

labels = 'S1', 'S2', 'S3'
sections = [56, 66, 24]
colors = ['c', 'g', 'y']

plt.pie(sections, labels=labels, colors=colors,
        startangle=90,  #첫 조각의 시작 각도
        explode = (0, 0, 0.1), # 틈새 설정
        autopct = '%1.2f%%' # autopercent - 소수점 둘째짜리까지 비율 출력 
        )

plt.axis('equal')
plt.title('Pie Chart Example')
plt.show()

 

7. 그래프 꾸미기 옵션

1) 축 지정

plt.xlim(시작지점, 끝지점)

plt.ylim(시작지점, 끝지점)

plt.axis([x_min, x_max, y_min, y_max])

 

위 옵션들로 그래프의 x축과 y축의 범위를 지정할 수 있습니다.

plt.plot(np.random.randn(30).cumsum())
plt.xlim(0, 10); # x축의 범위
plt.ylim(0, 10); # y축의 범위

 

plt.axis('tight')를 사용하면 그래프가 가득 차도록 축을 알아서 조정하여 보여줍니다.

plt.axis('equal')을 사용하면 그래프가 대칭처럼 보이도록 축을 조정해줍니다.

plt.plot(np.random.randn(30).cumsum())
plt.axis('tight')

 

2) 레이블 지정

그래프의 제목을 지정하거나, x축과 y축의 이름을 지정해줄 수 있습니다.

또한 각 점이나 선에도 무엇을 의미하는지 이름을 달아줄 수 있습니다.

plt.plot(np.random.randn(30).cumsum())
plt.title('제목')  #제목 
plt.xlabel('x축')  #x축 이름
plt.ylabel('y축');  #y축 이름

plt.plot(np.random.randn(30).cumsum(), label='A')  #각 라인에 label을 달아줍니다.
plt.plot(np.random.randn(30).cumsum(), label='B')
plt.plot(np.random.randn(30).cumsum(), label='C')
plt.plot(np.random.randn(30).cumsum(), label='d')
plt.plot(np.random.randn(30).cumsum(), label='e')
plt.title('범례를 달아준 그래프')
plt.xlabel('x축')
plt.ylabel('y축')
plt.legend() # 범례를 통해 라인의 label을 보여줍니다

점이나 선에 label을 달아 명시해줄 경우 plt.legend()를 통해 범례를 달아줄 수 있습니다.

범례의 위치는 loc이라는 옵션을 통해 'upper', 'lower', 'left', 'right'로 지정할 수 있고,

frameon = True, False 라는 옵션을 통해 범례의 테두리 유무를 지정할 수 있습니다.

 

3) fill_between & alpha

fill_between은 선 아래의 영역을 채워주는 옵션입니다.

alpha를 지정하면 도형의 투명도를 조정할 수 있습니다.

n = np.random.randn(100)
x = range(100)

plt.plot(x, n)
plt.fill_between(x, n, -3, where = (n > -3), alpha = 0.4)

 

8. 그래프 여러개 그리기

하나의 도화지에 여러개의 그래프를 나누어 그리는 옵션은 plt.subplot으로 지정할 수 있습니다.

plt.subplot(row, column, index)

각 그래프를 그리기 전에 subplot을 통해 그래프가 들어갈 좌표를 넣어주시면 됩니다.

#가로에 2개, 세로에 2개의 그래프 그리기
plt.subplot(2, 2, 1)
plt.plot(np.random.randn(30).cumsum(), 'g--')

plt.subplot(2, 2, 2)
plt.plot(np.random.randn(30).cumsum(), 'r')

plt.subplot(2, 2, 3)
plt.plot(np.random.randn(30).cumsum(), '^-')

plt.subplot(2, 2, 4)
plt.plot(np.random.randn(30).cumsum(), 's--', color = 'orange')

 

그래프를 여러개 그릴 때 축을 공유하여 그리고싶다면

plt.subplot(row, column, index, sharex = 기준 subplot)

#x축을 공유하여 그래프 그리기
ax1 = plt.subplot(2,1,1)
plt.plot(np.random.randn(30).cumsum(), 'g--')
plt.xticks(visible = False)  #축을 동일하게 사용하기 때문에 위 그래프의 축을 가림

ax2 = plt.subplot(2,1,2, sharex = ax1)
plt.plot(np.random.randn(30).cumsum(), 's--', color = 'orange');