matplotlib에서 fig, ax = plt.subplots()를 사용하는 이유
퍼온글입니다. 출처는 밑에..
Matplotlib을 활용한 데이터 시각화 방법 중 가장 처음으로 배우게 된 것은 plt.subplots()를 활용한 방식이었다. Datacamp의 예제를 그대로 가져올 수 없는 관계로 Google Trends에서 지난 1년간의 오버워치와 롤의 검색량 csv 파일을 다운로드해 간단히 연습해 볼 겸 시각화를 해 보기로 했다.
# Make the date as an index for both DataFrames
overwatch = overwatch.set_index('date')
lol = lol.set_index('date')
print(overwatch.head())
print(lol.head())
search
date
2019-11-17 75
2019-11-24 66
2019-12-01 73
2019-12-08 71
2019-12-15 72
search
date
2019-11-17 68
2019-11-24 54
2019-12-01 48
2019-12-08 52
2019-12-15 44
# Creating a plot with time as x-axis and search on y-axis
fig, ax = plt.subplots()
ax.plot(overwatch.index.values, overwatch['search'])
ax.plot(lol.index.values, lol['search'])
ax.set_xlabel('Date')
ax.set_ylabel('Number of Searches')
ax.legend(['Overwatch', 'LoL'])
plt.show()
의문의 발생

X축을 보기 좋게 정리할 필요는 있겠지만, 우선 큰 트렌드를 볼 수 있는 그래프를 그려볼 수 있다. 이 부분을 배우며 내가 가지게 되었던 의문은 다음과 같다. 코드를 돌아보면 분명 plt.subplots를 통해 두 개의 변수를 설정했는데, 실질적으로 시각화에 사용되는 것은 ax 변수였다. 왜 그런 것일까?
시각화를 하는 과정에서 주로 사용하는 변수는 ax 하나인데, 왜 우리는 fig, ax = plt.subplots()라는 수식을 활용해 fig라는 변수를 넣는 걸까?
# Creating a plot with time as x-axis and search on y-axis
fig, ax = plt.subplots()
ax.plot(overwatch.index.values, overwatch['search'])
ax.plot(lol.index.values, lol['search'])
ax.set_xlabel('Date')
ax.set_ylabel('Number of Searches')
ax.legend(['Overwatch', 'LoL'])
plt.show()
fig, ax 각각의 정의에 대하여
다음 사이트(Towards Data Science)에서는 fig, 와 ax에 대해서 이와 같이 설명하고 있다.

간단한 도식으로 그려 기억하고자 한다
fig = figure
|
데이터가 담기는 프레임. 크기, 모양을 변형할 수 있지만 실제로 프레임 위에 글씨를 쓸 수는 없다. 즉, 여러 그래프가 담길 수 있는 액자 같은 역할을 한다.
|
ax = axes
|
실제 데이터가 그려지는 캔버스. 그렇기에 모든 plot은 이 axes 위에서 이루어져야 하는 것이다.
|
이 정의만 보아도, 왜 실제 plot을 그릴 때 내가 ax라는 변수만 사용했는지는 명확해진다. 실제로 데이터가 그려지는 그래프와 관련해서는 당연히 프레임과 무관하게 캔버스 위에서만 조작을 하게 될 것이다.
그렇다면 fig 변수는 왜 만들고, 언제 활용할 수 있을까?
실제 완성한 하나의 figure (하나 혹은 여러 개의 플롯을 포함한 개체)를 저장할 때는 fig 변수를 활용하게 된다. savefig 함수를 활용하여 png, jpg, svg 세 가지 형태 중 하나로 저장할 수 있으며, 저장 화질 역시 설정할 수 있게 된다. 이 외에도 figsize(width, height) 등으로 조금 더 적합한 크기의 프레임을 구축하는 데에 활용되기도 한다.
fig.savefig('yourfilename.png', dpi = 300)
fig.savefig('yourfilename.jpg', quality = 50)
아마 향후에도 가장 보편적인 형태인 fig, ax = plt.subplots(n, m)의 형태를 활용하게 될 것이지만, 한 발짝 더 나아가 그렇다면 fig와 ax를 각각 다른 변수로 활용하여 플롯을 그리는 방법에 대해서 알아보았다.
fig, ax를 각각 활용해 플롯을 그리는 방법
이 의문을 해결하기 위해서는 나와 똑같은 궁금증을 가졌던 사람의 질문 스레드를 참조했다.
예를 들자면, 우리가 지금은 한 그래프 안에 함께 표현된 오버워치와 롤 검색량 트렌드를 위 아래로 놓인 두 개의 그래프로 비교해보고 싶다고 가정하자. 그렇다면 우리는 다음과 같은 공간이 필요하게 될 것이다. 이런 공간을 만들어내는 방법은 두 가지가 있다.

① 보편적인 fig, ax = subplots()을 활용하는 방법
fig, ax = plt.subplots(2, 1)
plt.show()
② fig, ax를 별개로 활용하는 방법
# axes가 담길 수 있는 figure 객체를 만들기
fig = plt.figure()
# figure에 담길 axes를 만들기 [행, 열, 몇 번째 axes인가?]
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2)
plt.show()
여기서 fig.add_subplot 함수는 (2 = 2개의 행, 1 = 1개의 열, 1 = 그 중 첫 번째 그래프)를 ax1에 부여한다는 뜻을 가지고 있다. 만일, 하나의 그래프만 그리고 싶다면 (1, 1, 1)의 값을 입력하면 될 것이다.
그렇다면 이렇게 각각의 경우, 플롯을 어떻게 그려야 하는지에 대한 의문이 남는다. 그에 대해 간단히 동일한 예제를 통해 연습해보고자 한다.
① 보편적인 fig, ax = subplots()을 활용하는 방법
# Creating a plot with time as x-axis and search on y-axis
fig, ax = plt.subplots(2, 1)
ax[0].plot(overwatch.index.values, overwatch['search'], linestyle = '--', marker = 'o', color = 'b')
ax[1].plot(lol.index.values, lol['search'], linestyle = '--', marker = 'v', color = 'r')
ax[0].set_title('Overwatch Search Record')
ax[1].set_title('LoL Search Record')
plt.show()
② fig, ax를 별개로 활용하는 방법
# Creating a plot with time as x-axis and search on y-axis
fig = plt.figure()
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2)
ax1.plot(overwatch.index.values, overwatch['search'], linestyle = '--', marker = 'o', color = 'b')
ax2.plot(lol.index.values, lol['search'], linestyle = '--', marker = 'v', color = 'r')
ax1.set_title('Overwatch Search Record')
ax2.set_title('LoL Search Record')
plt.show()

X 축 정렬은 다음... 포스트에
1번의 방법으로는 ax[0]으로 첫 번째 그래프를 불러오고, 2번의 방법은 처음 설정했던 그대로 ax1을 통해 첫 번째 그래프를 불러오는 것이 차이점이다. 지금은 단순히 두 개의 그래프를 그리기 때문에 코드 길이에 큰 영향이 가지 않지만, 그래프가 많아질 경우 1번 방식이 가진 이점이 명백히 드러난다.
궁극적으로 그려야 할 그래프의 수가 늘어날수록 fig, ax = plt.subplots()의 위력이 드러난다.
1. ax1, ax2, ax3등 개별의 그래프와 그 좌표를 일일히 그릴 필요가 없다.
2. figure 객체를 별도로 설정하는 단계를 건너뛸 수 있다
3. 유의할 점!
1) fig, ax = plt.subplots(1, 2)의 경우, 좌우로 하나의 그래프가 나타나지만
2) 이 그래프를 불러낼 땐 Python의 인덱싱 법칙에 따라 ax[0], ax[1]을 활용해야만 제대로 불러낼 수 있다.
출처: https://m.blog.naver.com/allieverwanted/222146678032
matplotlib에서 fig, ax = plt.subplots()를 사용하는 이유
Matplotlib을 활용한 데이터 시각화 방법 중 가장 처음으로 배우게 된 것은 plt.subplots()를 활용한 방식...
blog.naver.com
추가
fig, ax 없이 아래와 같이 subplot()을 사용하는 방법도 있다.
import numpy as np
x = np.random.rand(5)
y = np.random.rand(5)
plt.subplot(221)
plt.scatter(x, y, s=80, c='r', marker=">")
plt.subplot(222)
plt.scatter(x, y, s=80, c='b', marker=(5, 0))
verts = np.array([[-1, -1], [1, -1], [1, 1], [-1, -1]])
plt.subplot(223)
plt.scatter(x, y, s=80, c='k', marker=verts)
plt.subplot(224)
plt.scatter(x, y, s=80, c='y', marker=(5, 1))
plt.show()
출처: elice