Matplotlib 기초 튜토리얼
데이터 시각화는 데이터를 이해하고 분석 결과를 효과적으로 전달하는 데 필수적인 과정입니다. Python 생태계에서 Matplotlib는 가장 널리 사용되는 데이터 시각화 라이브러리 중 하나입니다. 유연하고 강력하며 다양한 종류의 그래프를 그릴 수 있는 기능을 제공합니다. 이 튜토리얼에서는 Matplotlib의 기본 개념부터 시작하여 간단한 그래프를 그리고 사용자 정의하는 방법까지 자세히 살펴보겠습니다.
1. Matplotlib란 무엇인가?
Matplotlib는 Python에서 정적, 애니메이션 및 대화형 시각화를 만들기 위한 포괄적인 라이브러리입니다. NumPy와 SciPy 같은 과학 계산 라이브러리와 잘 통합되어 있으며, 다양한 운영 체제와 그래픽 백엔드를 지원합니다.
Matplotlib는 크게 두 가지 인터페이스 스타일을 제공합니다.
- pyplot 인터페이스: MATLAB과 유사한 상태 기반의 인터페이스입니다. 간단한 플롯을 빠르게 생성할 때 편리하지만, 여러 개의 플롯을 관리하거나 복잡한 레이아웃을 다룰 때는 코드가 장황해질 수 있습니다.
matplotlib.pyplot
모듈을 사용하여plt
라는 별칭으로 임포트하는 것이 관례입니다. - 객체 지향(Object-Oriented, OO) 인터페이스: Matplotlib의 핵심 기능을 나타내는
Figure
와Axes
객체를 직접 다루는 방식입니다. 초기에는 조금 더 복잡해 보일 수 있지만, 그래프의 각 요소를 세밀하게 제어하고 복잡한 레이아웃을 구성할 때 훨씬 유용하며 코드의 가독성과 유지보수성을 높여줍니다.
이 튜토리얼에서는 두 가지 인터페이스를 모두 소개하지만, 특히 복잡한 그래프나 여러 개의 그래프를 다룰 때는 객체 지향 인터페이스를 사용하는 것이 권장됩니다.
2. 설치
Matplotlib는 파이썬 패키지 관리자인 pip 또는 Anaconda를 통해 쉽게 설치할 수 있습니다.
pip 사용 시:
bash
pip install matplotlib
Anaconda 사용 시:
bash
conda install matplotlib
3. Matplotlib 임포트하기
Matplotlib를 사용하기 위해서는 일반적으로 matplotlib.pyplot
모듈을 임포트합니다. 관례적으로 plt
라는 별칭을 사용합니다.
python
import matplotlib.pyplot as plt
import numpy as np # 그래프 예제를 위해 numpy도 임포트합니다.
4. 기본 개념: Figure와 Axes
Matplotlib의 객체 지향 인터페이스를 이해하는 데 가장 중요한 두 가지 기본 구성 요소는 Figure
와 Axes
입니다.
- Figure: 전체 창 또는 페이지를 나타냅니다. 이
Figure
안에 하나 이상의Axes
객체가 포함될 수 있습니다. 제목, 전체 크기 등을 설정할 수 있습니다. - Axes: 실제 데이터를 표시하는 개별 플롯 영역입니다.
Figure
객체 안에 위치하며, x축, y축, 데이터 플롯, 제목, 레이블, 범례 등 그래프의 대부분 요소가Axes
객체에 속합니다. 혼동하기 쉽지만, 복수형인 ‘Axes’가 단일 플롯 영역을 의미합니다. (‘Axis’는 축 하나를 의미합니다.)
객체 지향 방식으로 그래프를 시작할 때 가장 흔하게 사용하는 함수는 plt.subplots()
입니다. 이 함수는 Figure
객체와 하나 이상의 Axes
객체를 반환합니다.
python
fig, ax = plt.subplots() # 하나의 Figure와 하나의 Axes를 생성합니다.
만약 여러 개의 서브플롯을 만들고 싶다면 plt.subplots(nrows, ncols)
형태로 호출할 수 있으며, 이 경우 ax
는 Axes
객체의 NumPy 배열이 됩니다.
“`python
fig, axes = plt.subplots(nrows=2, ncols=2) # 2×2 그리드의 Axes 객체를 생성합니다.
axes는 axes[0, 0], axes[0, 1], axes[1, 0], axes[1, 1]로 접근 가능한 2차원 배열입니다.
“`
5. 첫 번째 그래프 그리기 (pyplot 인터페이스)
가장 간단하게 선 그래프를 그려보겠습니다. pyplot 인터페이스를 사용하면 몇 줄의 코드로 빠르게 결과를 확인할 수 있습니다.
“`python
데이터 생성
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])
선 그래프 그리기
plt.plot(x, y)
그래프 보여주기
plt.show()
“`
이 코드는 x
와 y
데이터를 사용하여 선 그래프를 그립니다. plt.plot()
함수는 기본적으로 선 그래프를 그리며, 다양한 옵션을 통해 선의 스타일, 색상, 마커 등을 지정할 수 있습니다. plt.show()
함수는 생성된 그래프를 화면에 표시합니다. 주피터 노트북이나 IPython 환경에서는 마지막 plt.show()
호출 없이도 그래프가 자동으로 표시되는 경우가 많습니다.
6. 첫 번째 그래프 그리기 (객체 지향 인터페이스)
동일한 그래프를 객체 지향 인터페이스로 그려보겠습니다.
“`python
데이터 생성
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])
Figure와 Axes 객체 생성
fig, ax = plt.subplots()
Axes 객체에 선 그래프 그리기
ax.plot(x, y)
그래프 보여주기
plt.show()
“`
plt.subplots()
로 fig
와 ax
를 얻은 후, ax.plot()
메서드를 사용하여 데이터를 그립니다. 이후 그래프에 대한 모든 설정(제목, 레이블, 눈금 등)은 ax
객체의 메서드를 호출하여 수행하게 됩니다.
7. 라인 스타일, 색상, 마커 설정
plot()
함수는 선의 모양을 다양하게 설정할 수 있는 매개변수를 제공합니다.
color
: 선의 색상 (‘red’, ‘blue’, ‘green’, ‘#FF5733’ 등)linestyle
: 선의 스타일 (‘-‘, ‘–‘, ‘-.’, ‘:’)marker
: 데이터 포인트에 표시할 마커 스타일 (‘o’, ‘s’, ‘^’, ‘*’)linewidth
: 선의 두께markersize
: 마커의 크기
pyplot 또는 객체 지향 인터페이스 모두 동일한 매개변수를 사용합니다.
“`python
x = np.linspace(0, 10, 100) # 0부터 10까지 100개의 균등 간격 데이터 생성
y1 = np.sin(x)
y2 = np.cos(x)
fig, ax = plt.subplots()
다양한 스타일 적용
ax.plot(x, y1, color=’blue’, linestyle=’-‘, label=’sin(x)’)
ax.plot(x, y2, color=’red’, linestyle=’–‘, marker=’o’, markersize=5, label=’cos(x)’)
plt.show()
“`
plot()
함수의 세 번째 매개변수로 포맷 문자열을 사용하여 색상, 마커, 선 스타일을 짧게 지정할 수도 있습니다. 예: 'r--o'
는 ‘빨간색(–) 선에 o 마커’를 의미합니다.
python
fig, ax = plt.subplots()
ax.plot(x, y1, 'b-', label='sin(x)') # 파란색 실선
ax.plot(x, y2, 'ro--', label='cos(x)') # 빨간색 점선에 원 마커
plt.show()
8. 산점도 그리기
데이터 포인트의 분포를 확인하기 위해 산점도를 그릴 수 있습니다. plt.scatter()
또는 ax.scatter()
함수를 사용합니다.
“`python
무작위 데이터 생성
np.random.seed(0)
x = np.random.rand(50)
y = np.random.rand(50)
colors = np.random.rand(50) # 색상 값을 위한 데이터
sizes = 1000 * np.random.rand(50) # 크기 값을 위한 데이터
fig, ax = plt.subplots()
산점도 그리기
scatter = ax.scatter(x, y, c=colors, s=sizes, alpha=0.7, cmap=’viridis’) # c: 색상, s: 크기, alpha: 투명도, cmap: 컬러맵
컬러바 추가 (산점도에 사용된 색상 데이터의 의미를 설명)
fig.colorbar(scatter, ax=ax, label=’Color Value’)
plt.show()
“`
scatter()
함수는 c
매개변수로 각 점의 색상을, s
매개변수로 각 점의 크기를 지정할 수 있습니다. alpha
는 투명도를 조절합니다. cmap
은 색상 값을 어떤 컬러맵으로 표현할지 지정합니다.
9. 제목, 축 레이블, 범례 추가
그래프를 명확하게 이해하기 위해서는 제목, 축 레이블, 범례가 필수적입니다.
- 제목:
plt.title()
또는ax.set_title()
- x축 레이블:
plt.xlabel()
또는ax.set_xlabel()
- y축 레이블:
plt.ylabel()
또는ax.set_ylabel()
- 범례:
plt.legend()
또는ax.legend()
(각plot()
또는scatter()
호출 시label
매개변수를 지정해야 합니다.)
“`python
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
fig, ax = plt.subplots()
ax.plot(x, y1, label=’sin(x)’)
ax.plot(x, y2, label=’cos(x)’)
제목, 축 레이블 추가
ax.set_title(‘Sine and Cosine Functions’)
ax.set_xlabel(‘X-axis’)
ax.set_ylabel(‘Y-axis’)
범례 추가
ax.legend()
plt.show()
“`
10. 축 범위 및 눈금 설정
그래프의 특정 영역을 확대하거나 축의 최소/최대 값을 설정하려면 축 범위를 조절해야 합니다. 또한, 축 눈금의 위치나 레이블을 사용자 정의할 수 있습니다.
- 축 범위 설정:
plt.xlim()
,plt.ylim()
또는ax.set_xlim()
,ax.set_ylim()
- 축 눈금 설정:
plt.xticks()
,plt.yticks()
또는ax.set_xticks()
,ax.set_yticks()
- 축 스케일 변경 (선형, 로그 등):
plt.xscale()
,plt.yscale()
또는ax.set_xscale()
,ax.set_yscale()
“`python
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, ax = plt.subplots()
ax.plot(x, y)
y축 범위를 -1.5에서 1.5로 설정
ax.set_ylim(-1.5, 1.5)
x축 눈금을 특정 위치에 설정 (0, pi, 2*pi, …)
ax.set_xticks(np.arange(0, 11, 2)) # 0부터 10까지 2 간격으로 눈금 설정
x축 눈금 레이블을 문자열로 설정
ax.set_xticklabels([‘0’, ‘2’, ‘4’, ‘6’, ‘8’, ’10’]) # 위 set_xticks와 함께 사용
ax.set_title(‘Sine Function with Adjusted Y-limit and X-ticks’)
ax.set_xlabel(‘X’)
ax.set_ylabel(‘sin(X)’)
plt.show()
“`
11. 여러 개의 서브플롯 생성
하나의 Figure 안에 여러 개의 그래프를 나란히 표시하고 싶을 때 서브플롯 기능을 사용합니다.
plt.subplot()
사용 (pyplot 인터페이스):
plt.subplot(nrows, ncols, index)
형태로 사용합니다. index
는 1부터 시작하며, 그래프가 그려질 서브플롯의 위치를 지정합니다 (왼쪽 위부터 오른쪽으로 순서대로 번호가 매겨집니다).
“`python
데이터 생성
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = x**2
2×2 그리드 생성
plt.figure() # 새로운 Figure 생성 (필수는 아니지만 명시적으로)
plt.subplot(2, 2, 1) # 왼쪽 위
plt.plot(x, y1)
plt.title(‘sin(x)’)
plt.subplot(2, 2, 2) # 오른쪽 위
plt.plot(x, y2, ‘r–‘)
plt.title(‘cos(x)’)
plt.subplot(2, 2, 3) # 왼쪽 아래
plt.plot(x, y3, ‘g.-‘)
plt.title(‘tan(x)’)
plt.ylim(-5, 5) # tan 함수는 범위 제한 필요
plt.subplot(2, 2, 4) # 오른쪽 아래
plt.plot(x, y4, ‘k:’)
plt.title(‘x^2’)
plt.tight_layout() # 서브플롯 간 간격 자동 조절
plt.show()
“`
이 방식은 각 서브플롯을 그릴 때마다 plt.subplot()
을 호출하여 현재 활성 상태인 Axes를 변경하는 방식입니다.
plt.subplots()
사용 (객체 지향 인터페이스):
plt.subplots(nrows, ncols)
를 사용하여 Figure와 Axes 객체의 배열을 얻는 방식입니다. 이 방식이 더 유연하고 객체를 직접 다루기 때문에 복잡한 서브플롯 관리에 유리합니다.
“`python
데이터는 위와 동일
2×2 그리드 Axes 생성
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 6)) # Figure 크기 지정 가능
axes는 2차원 NumPy 배열이므로 인덱싱으로 접근
axes[0, 0].plot(x, y1)
axes[0, 0].set_title(‘sin(x)’)
axes[0, 1].plot(x, y2, ‘r–‘)
axes[0, 1].set_title(‘cos(x)’)
axes[1, 0].plot(x, y3, ‘g.-‘)
axes[1, 0].set_title(‘tan(x)’)
axes[1, 0].set_ylim(-5, 5)
axes[1, 1].plot(x, y4, ‘k:’)
axes[1, 1].set_title(‘x^2’)
plt.tight_layout()
plt.show()
“`
이 방식은 각 Axes 객체(axes[i, j]
)의 메서드를 호출하여 해당 서브플롯에 그림을 그립니다. axes
가 1차원 배열이 되는 경우(plt.subplots(1, 2)
또는 plt.subplots(2, 1)
), 인덱싱은 axes[0]
, axes[1]
등으로 이루어집니다. 하나의 서브플롯만 만들 경우(plt.subplots()
), ax
는 단일 Axes
객체이므로 ax.plot()
와 같이 사용합니다.
12. 그래프 저장하기
생성한 그래프를 파일로 저장하려면 plt.savefig()
함수를 사용합니다.
“`python
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title(“Sample Plot”)
현재 Figure를 파일로 저장
plt.savefig(‘sample_plot.png’) # PNG 형식으로 저장
plt.savefig(‘sample_plot.pdf’) # PDF 형식으로 저장
plt.savefig(‘sample_plot.jpg’, dpi=300) # JPG 형식, 해상도 300dpi로 저장
파일 저장 후에도 plt.show()를 호출하여 화면에 표시 가능
plt.show()
“`
savefig()
함수는 파일 경로와 이름을 첫 번째 인자로 받습니다. 파일 확장자에 따라 형식이 결정됩니다 (png, jpg, pdf, svg 등). dpi
매개변수를 사용하여 해상도를 조절할 수 있으며, bbox_inches='tight'
를 사용하면 그래프 주변의 여백을 최소화하여 저장할 수 있습니다.
13. 다양한 그래프 유형 (간단 소개)
Matplotlib는 선 그래프와 산점도 외에도 다양한 종류의 그래프를 지원합니다. 몇 가지 기본적인 그래프 유형을 소개합니다.
-
막대 그래프 (Bar Plot): 범주형 데이터의 빈도나 값을 비교할 때 사용합니다.
plt.bar()
또는ax.bar()
.python
categories = ['A', 'B', 'C', 'D']
values = [23, 45, 56, 12]
fig, ax = plt.subplots()
ax.bar(categories, values)
ax.set_title('Bar Chart Example')
plt.show() -
히스토그램 (Histogram): 연속형 데이터의 분포를 보여줄 때 사용합니다.
plt.hist()
또는ax.hist()
.python
data = np.random.randn(1000) # 표준 정규 분포 데이터 1000개
fig, ax = plt.subplots()
ax.hist(data, bins=30) # 데이터를 30개의 구간으로 나누어 빈도 계산
ax.set_title('Histogram Example')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
plt.show() -
파이 차트 (Pie Chart): 전체에 대한 각 범주의 비율을 보여줄 때 사용합니다.
plt.pie()
또는ax.pie()
.python
sizes = [15, 30, 45, 10]
labels = ['A', 'B', 'C', 'D']
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90)
ax.set_title('Pie Chart Example')
plt.show()
14. 스타일 적용
Matplotlib는 미리 정의된 다양한 스타일을 제공하여 그래프의 전체적인 모양을 쉽게 변경할 수 있습니다. plt.style.use()
함수를 사용합니다.
어떤 스타일이 있는지 확인하려면 plt.style.available
속성을 확인하세요.
python
print(plt.style.available)
몇 가지 스타일을 적용해 보겠습니다.
“`python
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
‘seaborn-v0_8-darkgrid’ 스타일 적용
plt.style.use(‘seaborn-v0_8-darkgrid’)
fig, ax = plt.subplots()
ax.plot(x, y1, label=’sin(x)’)
ax.plot(x, y2, label=’cos(x)’)
ax.set_title(‘Styled Plot (seaborn-darkgrid)’)
ax.legend()
plt.show()
스타일 재설정 또는 다른 스타일 적용 가능
plt.style.use(‘default’) # 기본 스타일로 돌아가기
fig, ax = plt.subplots()
ax.plot(x, y1, label=’sin(x)’)
ax.plot(x, y2, label=’cos(x)’)
ax.set_title(‘Styled Plot (default)’)
ax.legend()
plt.show()
“`
스타일을 사용하면 최소한의 코드로도 미적으로 개선된 그래프를 얻을 수 있습니다.
15. Figure와 Axes 객체 활용의 장점
튜토리얼 전반에 걸쳐 객체 지향(fig, ax = plt.subplots()
) 방식을 사용하는 것이 더 좋다고 언급했습니다. 그 이유는 다음과 같습니다.
- 명확성: 어떤 객체(Figure 또는 특정 Axes)에 작업을 수행하는지 코드를 통해 명확하게 알 수 있습니다. 이는 특히 서브플롯이 많거나 복잡한 레이아웃을 다룰 때 중요합니다.
- 유연성: Axes 객체는 그래프의 모든 요소를 제어하는 다양한 메서드를 가지고 있습니다. 이 메서드들은 Figure 객체나 다른 Axes 객체의 상태에 영향을 받지 않고 해당 Axes에만 독립적으로 적용됩니다.
- 프로그래밍 용이성: 여러 개의 Axes 객체를 배열 형태로 관리할 수 있으므로 반복문 등을 사용하여 여러 서브플롯에 동일한 작업을 적용하기 편리합니다.
- 재사용성: Figure나 Axes 객체를 변수에 저장하고 필요에 따라 다시 사용할 수 있습니다.
간단한 한두 개의 그래프를 빠르게 그릴 때는 pyplot 인터페이스가 편리할 수 있지만, 데이터 분석 파이프라인의 일부로 그래프를 생성하거나, 복잡한 시각화를 만들거나, 코드를 재사용할 계획이라면 객체 지향 인터페이스를 사용하는 것을 강력히 권장합니다.
마무리
이 튜토리얼에서는 Matplotlib의 기본 개념, 설치 및 임포트 방법, Figure와 Axes의 역할, pyplot 및 객체 지향 인터페이스를 사용한 기본 그래프(선 그래프, 산점도) 그리기, 제목/레이블/범례 추가, 축 범위/눈금 설정, 여러 개의 서브플롯 생성, 그래프 저장, 그리고 몇 가지 다른 그래프 유형과 스타일 적용 방법까지 살펴보았습니다.
Matplotlib는 매우 강력하고 유연한 라이브러리이므로 이 튜토리얼에서 다룬 내용은 기본적인 기능의 일부에 불과합니다. 더 깊이 있는 학습을 위해서는 Matplotlib 공식 갤러리(Gallery)를 둘러보며 다양한 그래프 예제 코드를 참고하거나, 공식 문서를 통해 특정 함수나 객체의 자세한 사용법을 익히는 것이 좋습니다.
데이터 분석 및 시각화 여정에서 Matplotlib가 유용한 도구가 되기를 바랍니다!