데이터 시각화에서는 단일 그림 (figure) 에 여러 개의 플롯 (plot) 을 표시하는 것이 유용한 경우가 많습니다. 이를 통해 서로 다른 데이터셋 간 또는 동일한 데이터의 서로 다른 뷰 간의 비교를 쉽게 할 수 있습니다. Matplotlib 은 서브플롯 (subplots) 을 사용하여 이러한 그림을 생성하는 강력하고 편리한 방법을 제공합니다.
서브플롯을 생성하는 가장 일반적인 방법은 plt.subplots() 함수를 사용하는 것입니다. 이 함수는 단일 호출로 그림과 서브플롯 그리드를 생성하며, Figure 객체와 각 개별 서브플롯을 나타내는 Axes 객체의 배열을 반환합니다.
이 실습에서는 다음을 배우게 됩니다.
여러 개의 서브플롯을 포함하는 그림 생성하기
특정 서브플롯에 데이터 플롯하기
플롯이 겹치지 않도록 레이아웃 조정하기
더 명확한 비교를 위해 서브플롯 간 축 공유하기
WebIDE 에서 Python 스크립트를 작성하고 실행하게 됩니다. 이 환경은 대화형 GUI 창을 지원하지 않으므로, 플롯을 이미지 파일로 저장하고 편집기에서 직접 확인하게 됩니다.
이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 100%입니다.학습자들로부터 100%의 긍정적인 리뷰율을 받았습니다.
plt.subplots() 를 사용하여 그림 (figure) 과 축 (axes) 생성하기
이 단계에서는 한 행과 두 열로 배열된 두 개의 빈 서브플롯을 포함하는 그림을 생성하는 것으로 시작합니다. 이는 다중 플롯 시각화를 구축하는 기초 단계입니다.
plt.subplots() 함수를 사용할 것입니다. plt.subplots(nrows, ncols)를 호출하면 두 가지 항목이 반환됩니다.
Figure 객체: 모든 것이 그려지는 전체 창 또는 페이지입니다. 일반적으로 fig라는 변수에 할당합니다.
Axes 객체의 배열: 각 Axes 객체는 그리드의 서브플롯 중 하나를 나타냅니다. 인덱스로 접근할 수 있습니다. (1, 2) 그리드의 경우 이 배열을 ax1 및 ax2 두 변수로 언패킹 (unpack) 할 수 있습니다.
코드를 작성해 보겠습니다. 왼쪽에 있는 파일 탐색기에서 main.py 파일을 열고 다음 내용을 추가하세요. 이 스크립트는 필요한 라이브러리를 가져오고, 두 개의 서브플롯이 있는 그림을 생성하고, 이를 plot1.png라는 이미지 파일로 저장합니다.
import matplotlib.pyplot as plt
import numpy as np
## 그림 및 서브플롯 세트 생성
## 1 행, 2 열
fig, (ax1, ax2) = plt.subplots(1, 2)
## 그림을 파일로 저장
## 파일은 /home/labex/project 디렉토리에 생성됩니다.
plt.savefig('plot1.png')
print("Figure saved as plot1.png")
이제 터미널에서 스크립트를 실행하여 플롯을 생성합니다.
python3 main.py
터미널에서 다음과 같은 출력을 볼 수 있습니다.
Figure saved as plot1.png
plot1.png라는 새 파일이 파일 탐색기에 나타납니다. 이 파일을 더블 클릭하여 두 개의 빈 서브플롯이 있는 첫 번째 그림을 확인하세요.
ax1.plot() 를 사용하여 첫 번째 서브플롯에 플로팅하기
이 단계에서는 생성한 특정 Axes 객체 중 하나에 플롯을 그리는 방법을 배우게 됩니다. 각 Axes 객체는 plot(), bar(), scatter() 등과 같이 메인 plt 인터페이스의 함수와 유사한 자체 플로팅 메서드를 가지고 있습니다.
ax1 변수로 표현되는 첫 번째 서브플롯에 간단한 사인파 (sine wave) 를 플롯할 것입니다. 또한 set_title() 메서드를 사용하여 이 서브플롯에 제목을 추가할 것입니다.
main.py 파일을 다음 코드로 업데이트하세요. NumPy 를 사용하여 데이터를 생성한 다음 ax1에 플롯하는 코드를 추가합니다.
import matplotlib.pyplot as plt
import numpy as np
## 데이터 생성
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
## 그림 및 서브플롯 세트 생성
fig, (ax1, ax2) = plt.subplots(1, 2)
## 첫 번째 서브플롯 (ax1) 에 플롯
ax1.plot(x, y)
ax1.set_title('Sine Wave')
## 그림을 새 파일로 저장
plt.savefig('plot2.png')
print("Figure saved as plot2.png")
이제 터미널에서 업데이트된 스크립트를 실행합니다.
python3 main.py
다음 출력을 볼 수 있습니다.
Figure saved as plot2.png
plot2.png라는 새 파일이 이제 프로젝트 디렉토리에 있습니다. 결과를 보려면 파일을 엽니다. 왼쪽 서브플롯에는 사인파 플롯이 포함되어야 하며, 오른쪽 서브플롯은 비어 있어야 합니다.
ax2.plot() 를 사용하여 두 번째 서브플롯에 플로팅하기
이 단계에서는 두 번째 서브플롯에 플롯을 추가하여 그림을 완성합니다. 이전 단계와 동일한 과정이지만, 이번에는 ax2 객체에서 plot() 메서드를 호출합니다.
사인파와 비교하기 위해 두 번째 서브플롯에 코사인파 (cosine wave) 를 플롯할 것입니다. 또한 제목도 지정합니다.
두 번째 축에 플롯을 포함하도록 main.py 파일을 수정하세요.
import matplotlib.pyplot as plt
import numpy as np
## 데이터 생성
x = np.linspace(0, 2 * np.pi, 400)
y1 = np.sin(x ** 2)
y2 = np.cos(x ** 2)
## 그림 및 서브플롯 세트 생성
fig, (ax1, ax2) = plt.subplots(1, 2)
## 첫 번째 서브플롯 (ax1) 에 플롯
ax1.plot(x, y1)
ax1.set_title('Sine Wave')
## 두 번째 서브플롯 (ax2) 에 플롯
ax2.plot(x, y2, 'tab:orange')
ax2.set_title('Cosine Wave')
## 그림을 새 파일로 저장
plt.savefig('plot3.png')
print("Figure saved as plot3.png")
위 코드에서 ax2.plot() 호출에 'tab:orange'를 추가하여 선 색상을 변경함으로써 플롯을 시각적으로 구분했습니다.
터미널에서 스크립트를 다시 실행합니다.
python3 main.py
출력은 다음과 같습니다.
Figure saved as plot3.png
이제 plot3.png를 엽니다. 나란히 두 개의 플롯이 있는 완성된 그림을 볼 수 있습니다. 하지만 제목이나 축 레이블이 약간 빽빽하게 보일 수 있습니다. 다음 단계에서 이를 수정할 것입니다.
plt.tight_layout() 를 사용하여 서브플롯 레이아웃 조정하기
이 단계에서는 제목과 레이블이 겹치는 것을 방지하기 위해 서브플롯 간의 간격을 자동으로 조정하는 방법을 배우게 됩니다. Matplotlib 는 이를 위한 간단한 함수인 plt.tight_layout()을 제공합니다.
이 함수는 그림의 모든 아티스트 (제목, 레이블, 플롯 자체 등) 의 경계 상자를 검사하고 서브플롯 매개변수를 조정하여 모든 것이 겹치지 않고 깔끔하게 맞도록 합니다. 플롯을 저장하거나 표시하기 직전에 호출하는 것이 좋습니다.
스크립트에 plt.tight_layout()을 추가해 보겠습니다. main.py를 다음과 같이 업데이트하세요.
import matplotlib.pyplot as plt
import numpy as np
## 데이터 생성
x = np.linspace(0, 2 * np.pi, 400)
y1 = np.sin(x ** 2)
y2 = np.cos(x ** 2)
## 그림 및 서브플롯 세트 생성
fig, (ax1, ax2) = plt.subplots(1, 2)
## 첫 번째 서브플롯 (ax1) 에 플롯
ax1.plot(x, y1)
ax1.set_title('Sine Wave')
## 두 번째 서브플롯 (ax2) 에 플롯
ax2.plot(x, y2, 'tab:orange')
ax2.set_title('Cosine Wave')
## 겹침 방지를 위해 레이아웃 조정
plt.tight_layout()
## 그림을 새 파일로 저장
plt.savefig('plot4.png')
print("Figure saved as plot4.png")
변경된 부분은 plt.tight_layout() 줄이 추가된 것뿐입니다. 이제 스크립트를 실행합니다.
python3 main.py
출력:
Figure saved as plot4.png
plot4.png를 열고 plot3.png와 비교해 보세요. 두 서브플롯 간의 간격이 최적화되어 더 깔끔하고 전문적인 그림을 볼 수 있을 것입니다.
sharex=True 또는 sharey=True 를 사용하여 축 공유하기
이 단계에서는 공통 축을 공유하는 서브플롯을 만드는 방법을 배우게 됩니다. 이는 x 축 또는 y 축 스케일이 동일한 데이터셋을 비교할 때 특히 유용합니다. 축이 공유되면 한 서브플롯에서 확대/축소 또는 이동하면 다른 서브플롯도 자동으로 업데이트됩니다. 또한 중복되는 눈금 레이블을 제거하여 그림을 깔끔하게 만드는 데 도움이 됩니다.
plt.subplots()에 sharex=True 또는 sharey=True 인수를 전달하여 축 공유를 활성화할 수 있습니다.
이를 시연하기 위해 새 스크립트를 만들어 보겠습니다. 프로젝트 디렉터리에 shared_axes.py라는 파일을 만들고 다음 코드를 추가하세요. 이 예제는 동일한 x 축을 공유하는 두 개의 서브플롯을 수직으로 쌓아 (nrows=2, ncols=1) 만듭니다.
import matplotlib.pyplot as plt
import numpy as np
## 데이터 생성
t = np.arange(0.01, 5.0, 0.01)
s1 = np.exp(t)
s2 = np.sin(2 * np.pi * t)
## x 축을 공유하는 그림과 두 개의 서브플롯 생성
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
## 첫 번째 서브플롯에 플롯
ax1.plot(t, s1, 'tab:blue')
ax1.set_ylabel('Exponential')
## 두 번째 서브플롯에 플롯
ax2.plot(t, s2, 'tab:orange')
ax2.set_ylabel('Sinusoidal')
ax2.set_xlabel('time (s)')
## 레이아웃 조정
plt.tight_layout()
## 그림 저장
plt.savefig('plot5.png')
print("Figure saved as plot5.png")
이제 터미널에서 이 새 스크립트를 실행합니다.
python3 shared_axes.py
출력:
Figure saved as plot5.png
plot5.png를 엽니다. 아래쪽 서브플롯 (ax2) 에만 x 축 눈금 레이블이 있는 것을 알 수 있습니다. 이는 sharex=True가 깔끔한 모양을 만들기 위해 내부 x 축 레이블을 자동으로 숨기기 때문입니다. 두 플롯 모두 x 축을 따라 완벽하게 정렬되어 비교하기 쉽습니다.
요약
실험을 완료하신 것을 축하드립니다! Matplotlib 에서 서브플롯을 생성하고 관리하는 필수적인 기술들을 익히셨습니다.
이번 실험에서 연습한 내용은 다음과 같습니다:
plt.subplots()를 사용하여 서브플롯 그리드가 있는 그림을 생성했습니다.
개별 Axes 객체에 접근하고 해당 메서드를 사용하여 데이터를 플롯했습니다.
특정 서브플롯에 제목을 추가했습니다.
plt.tight_layout()을 사용하여 간격을 자동으로 조정하고 요소 겹침을 방지했습니다.
sharex=True를 사용하여 서브플롯의 축을 공유하여 더 명확한 데이터 비교와 깔끔한 그림을 만들었습니다.
이러한 기술들은 복잡하고 유익한 데이터 시각화를 만드는 데 기본이 됩니다. 이제 단일하고 일관된 보기에서 여러 데이터셋을 효과적으로 비교하는 그림을 만들 수 있습니다.