Figure라는 모든 그래프 구성 요소를 담고 있는 최상위 객체가 있다. scatter() 함수로 산점도를 그릴 때 자동으로 피겨 객체가 생성된다! figuer() 함수로 명시적으로 피겨 객체를 만들어 활용하면 다양한 그래프 옵션을 조절할 수 있다.
import gdown
gdown.download('https://bit.ly/3pK7iuu', 'ns_book7.csv', quiet=False)
# 실습 데이터 불러오기
import pandas as pd
ns_book7 = pd.read_csv('ns_book7.csv', low_memory=False)
ns_book7.head()
>>> 번호 도서명 저자 출판사 발행년도 ISBN 세트 ISBN 부가기호 권 주제분류번호 도서권수 대출건수 등록일자
0 1 인공지능과 흙 김동훈 지음 민음사 2021 9788937444319 NaN NaN NaN NaN 1 0 2021-03-19
1 2 가짜 행복 권하는 사회 김태형 지음 갈매나무 2021 9791190123969 NaN NaN NaN NaN 1 0 2021-03-19
2 3 나도 한 문장 잘 쓰면 바랄 게 없겠네 김선영 지음 블랙피쉬 2021 9788968332982 NaN NaN NaN NaN 1 0 2021-03-19
3 4 예루살렘 해변 이도 게펜 지음, 임재희 옮김 문학세계사 2021 9788970759906 NaN NaN NaN NaN 1 0 2021-03-19
4 5 김성곤의 중국한시기행 : 장강·황하 편 김성곤 지음 김영사 2021 9788934990833 NaN NaN NaN NaN 1 0 2021-03-19
산점도를 그려보자. 맷플롯립을 임포트하고 scatter() 함수로 '도서권수' 열을 x축, '대출건수' 열을 y축으로 그려진다. 투명도를 0.1로 지정하자.
import matplotlib.pyplot as plt
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
>>>
figure() 함수를 사용하여 피겨 객체를 만들면 그래프 옵션을 조절할 수 있다. figsize 매개변수에 그래프의 크기를 튜플로 지정할 수 있다. 기본 그래프 크기는 (6,4)이고 각각 너비와 높이에 해당한다. 단위는 인치(inch)이다.
# figsize 매개변수를 (9,6)으로 지정하여 산점도를 크게 더 그려보자.
print(plt.rcParams['figure.figsize']) → 너비가 9인치, 높이가 6인치인 피겨 객체를 생성한다.
>>> [6.4, 4.8]
plt.figure(figsize=(9, 6))
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
>>>
+ 기본 그래프 크기는 맷플롯립의 버전과 플랫폼에 따라 달라질 수 있다. 현재 설치된 맷플롯립의 기본 그래프 크기를 확인하려면 다음 명령 사용하자!
처음 그래프보다 그래프가 훨씬 커졌다!! plt.show() 함수가 호출되면 figure() 함수로 만들어진 피겨 객체는 자동으로 소멸된다. 그렇지만 9인치면 23센치미터에 가까운 길이인데 실제로 화면에 그려진 이미지는 이보다 작다. 화면상에 그려진 그래프의 실제 크기를 확인해보자.
화면에 그려진 그래프에 마우스 오른쪽 버튼을 클릭하면 팝업 메뉴가 나타난다. [새 탭에서 이미지 열기]를 선택한 후 간단하게 모니터 화면에 실제로 자를 대고 그래프 크기를 확인해보자.
보통 컴퓨터 화면의 해상도를 말할 때 픽셀 수와 DPI를 사용한다. DPI는 dot per inch의 약자로 1인치를 몇 개의 점(픽셀(pixel))으로 표현하는지 나타낸다.
다시 말해 DPI에 따라 화면에 그려지는 그래프 크기가 달라진다. 맷플롯립의 기본 DPI는 72이다.
figsize 매개변수는 인치 단위로 값을 지정해야 한다. 인치 값은 먼저 원하는 픽셀 값을 정한 다음 픽셀 값을 DPI로 나누면 구할 수 있다. 예를 들어 900 X 600 픽셀 크기의 그래프를 그리고 싶다고 가정해보자. 맷플롯립의 DPI 기본값은 72이므로 다음처럼 두 픽셀 값을 72로 나누어 figsize 매개변수에 전달한다.
print(plt.rcParams['figure.dpi'])
>>>100.0
plt.figure(figsize=(900/72, 600/72))
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
>>>
그래프가 훨씬 크게 그려진다!!
그래프에서 마우스 오른쪽 버튼을 클릭하면 팝업 메뉴가 나타나는데 [이미지를 다른 이름으로 저장...]을 선택하여 이미지를 다운로드한다. 그리고 다운로드한 이미지 파일에서 마우스 오른쪽 버튼을 클릭한 후 [속성] - [자세히]를 클릭하면 픽셀 크기를 확인할 수 있다.
하지만 900x600 픽셀보다 조금 작다. 코랩 노트북은 기본적으로 맷플롯립 그래프를 출력할 때 그래프 주변에 공백을 최소화하는 타이트(tight) 레이아웃을 사용하기 때문이다.
# 타이트 레이아웃 사용하지 않으려면 맷플롯립 그래프를 그릴 때 bbox_inches 옵션을 None으로 지정한다.
%config InlineBackend.print_figure_kwargs = {'bbox_inches': None}
plt.figure(figsize=(900/72, 600/72))
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
>>>
이미지 다운로드하여 다시 픽셀을 확인해보면 900x600인 것을 확인할 수 있다.
원하는 크기의 이미지를 얻었지만, 사실 노트북에서는 그래프 주변에 공백이 많으면 출력된 그래프와 코드를 나란히 놓고 보기 불편하다. 크기를 조정하는 방법을 알았으니 원래대로 타이트한 레이아웃으로 되돌아가자.
%config InlineBackend.print_figure_kwargs = {'bbox_inches': 'tight'}
이번에는 figsize 매개변수는 기본값 그대로 두고 dpi 매개변수를 지정해보자.
# DPI 기본값 72에서 두 배인 144로 늘리기.
plt.figure(dpi=144)
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
>>>
dpi 매개변수를 두 배로 늘리면 인치당 픽셀 수가 두 배로 늘어나기 때문에 그래프가 두 배 커진다. 또한 그래프 안의 모든 구성 요소도 함께 커진다. x축과 y축의 숫자가 커졌고, 데이터 포인트를 나타내는 동그라미 마커(marker)의 크기도 커졌다.
rcParams는 맷플롯립 그래프의 기본값을 관리하는 객체이다. 앞서 figure 객체의 figsize와 dpi 기본값을 확인할 때 사용해봤다. rcParams 객체는 객체에 담긴 값을 출력하는 것뿐만 아니라 새로운 값으로 바꿀 소도 있다. 이렇게 하면 이후에 그려지는 모든 그래프에 바뀐 설정이 적용된다.
먼저 기본 그래프 해상도를 높이기 위해 DPI 기본값을 바꾸어준다. figure 객체의 DPI 기본값을 100으로 바꾸려면 다음과 같이 작성한다.
plt.rcParams['figure.dpi'] = 100
산점도 그래프의 마커 기본값을 확인하려면 rcParams 객체의 속성을 scatter.marker로 지정한다. 객체를 그냥 출력하면 기본값인 동그라미를 나타내는 'o'가 출력된다.
plt.rcParams['scatter.marker']
>>> 'o'
마커를 별 모양으로 그리려면 값을 다음과 같이 '*'로 지정해준다.
plt.rcParams['scatter.marker'] = '*'
# 별 모양으로 그려지는지 확인!
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
plt.show()
>>>
하지만 여러 개의 산점도가 있고, 산점도마다 마커를 다르게 그려야 한다면 매번 scatter.marker 설정을 바꾸어야 하기에 너무 번거롭다. 이럴 때 기본값 수정하는 것 대신 scatter() 함수의 marker 매개변수로 마커의 모양을 지정하면 된다. 이렇게 하면 rcParams 객체의 scatter.marker 속성에 지정된 기본값을 무시하고 marker 매개변수에 지정된 값을 사용한다.
marker 매개변수를 '+'로 설정하여 덧셈 기호를 마커로 사용하면 다음과 같다.
plt.scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1, marker='+')
plt.show()
+ 맷플롯립 마커 옵션 : https://matplotlib.org/stable/api/markers_api.html#module-matplotlib.markers
성공!!!! 이처럼 객체의 기본값을 바꾸지 않아도 맷플롯립의 함수에서 제공하는 매개변수를 사용하면 그래프 설정 중 일부를 바로 바꿀 수 있다.
하나의 피겨 객체 안에는 여러 개의 서브플롯(subplot) 을 담을 수 있다. 서브플롯이란 맷플롯립의 Axes 클래스의 객체를 말하며 하나의 서브플롯은 두 개 이상의 축(axis)을 포함한다. 일반적으로 2차원 그래프의 수평축을 x축이라고 부르고 수직축을 y축으로 부른다. 3차원 그래프라면 세 개의 축이 있다. 각 축에는 눈금 또는 틱(tick)이 표시된다. 또한 축의 이름을 나타내는 레이블(label)이 있다.
[294 그림삽입]
서브플롯 정의하려면 subplots() 함수에 원하는 서브플롯 개수를 지정하면 된다.
subplots() 함수로 두 개의 서브플롯을 그리고 싶다면 매개변수에 2를 넣어준다. 그 다음 이 배열의 원소에서 각각 scatter() 함수와 hist() 함수를 호출한다. 첫 번째 그래프인 산점도의 x축은 '도서권수' 열이고 y축은 '대출건수' 열이다. 두 번째 그래프는 히스토그램으로 x축은 '대출건수' 열이고 y축은 대출건수의 빈도에 해당한다. 이때 히스토그램의 y축은 로그 스케일로 지정해 주자.
fig, axs = plt.subplots(2)
axs[0].scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
axs[1].hist(ns_book7['대출건수'], bins=100)
axs[1].set_yscale('log')
fig.show()
>>>
+figure 클래스 객체인 fig에 Axis 클래스 객체인 axs[0], axs[1]을 서브플롯으로 추가한다고 생각하자.
산점도와 히스토그램이 두 개의 그래프가 위아래로 나누어져 그려졌다. 그런데 피겨 크기의 기본값인 (6,4) 안에서 두 개의 서브플롯을 배치하기 때문에 각 그래프의 높이가 많이 줄어버렸다.
subplots() 함수도 피겨 크기를 지정할 수 있는 figsize 매개변수를 제공한다. 피겨 크기를 (6,8)로 지정하여 높이를 조절해보자. 또한 set_title() 메서드를 사용해서 각 그래프에 제목도 넣어보자.
fig, axs = plt.subplots(2, figsize=(6, 8))
axs[0].scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
axs[0].set_title('scatter plot')
# 'set_title' : 서브플롯의 제목을 넣는다.
axs[1].hist(ns_book7['대출건수'], bins=100)
axs[1].set_title('histogram')
axs[1].set_yscale('log')
fig.show()
>>>
y축이 훨씬 잘 보여서 그래프의 특징이 더 잘 들어난다!! 게다가 그래프 위에 제목이 있어 어떤 그래프를 그린 것인지 더 잘 알 수 있다.
서브플롯의 두 그래프를 가로로 날나히 놓으려면 어떻게 해야할까?? subplots() 함수에 행과 열을 지정하면 원하는 서브플롯 개수의 피겨를 만들 수 있다. 사실 subplots() 함수의 첫 번째 매개 변수는 서브플롯 행의 개수이고 두 번째 매개변수 열의 개수이다.
[297 그림삽입]
그래서 앞서 작성해 본 subplots(2)에서 2는 행을 의미한다. 두 번째 매개변수를 지정하지 않아 열에 기본값 1이 적용되엉 세로로 놓인 두 개의 서브플롯이 만들어진 것이다!
그럼 subplots(1,2)와 같이 써서 하나의 행에 두 개의 열을 가지 피겨를 만들어보자. set_title() 메서드로 각 서브플롯의 이름을 지정하고 set_xlabel() 메서드와 set_ylabel() 메서드를 사용해 두 서브플롯의 축 이름도 각각 지정해보자.
fig, axs = plt.subplots(1, 2, figsize=(10, 4))
# '(1, 2, figsize=(10, 4)' :
axs[0].scatter(ns_book7['도서권수'], ns_book7['대출건수'], alpha=0.1)
axs[0].set_title('scatter plot')
axs[0].set_xlabel('number of books')
axs[0].set_ylabel('borrow count')
axs[1].hist(ns_book7['대출건수'], bins=100)
axs[1].set_title('histogram')
axs[1].set_yscale('log')
axs[1].set_xlabel('borrow count')
axs[1].set_ylabel('frequency')
fig.show()
>>>
가로로 나란히 놓였고, x축, y축 이름도 생겼다!!