본문 바로가기
SW 프로그래밍/파이썬

범례

by N2info 2020. 9. 27.

범례

여러개의 라인 플롯을 동시에 그리는 경우에는 각 선이 무슨 자료를 표시하는지를 보여주기 위해 legend 명령으로 범례(legend)를 추가할 수 있다. 범례의 위치는 자동으로 정해지지만 수동으로 설정하고 싶으면 loc 인수를 사용한다. 인수에는 문자열 혹은 숫자가 들어가며 가능한 코드는 다음과 같다.

loc 문자열숫자

best 0
upper right 1
upper left 2
lower left 3
lower right 4
right 5
center left 6
center right 7
lower center 8
upper center 9
center 10

표 : plt.legend의 loc 인수 목록

In [15]:

X = np.linspace(-np.pi, np.pi, 256) C, S = np.cos(X), np.sin(X) plt.title("legend를 표시한 플롯") plt.plot(X, C, ls="--", label="cosine") plt.plot(X, S, ls=":", label="sine") plt.legend(loc=2) plt.show()

x축, y축 라벨, 타이틀

플롯의 x축 위치와 y축 위치에는 각각 그 데이터가 의미하는 바를 표시하기 위해 라벨(label)를 추가할 수 있다. 라벨을 붙이려면 xlabel. ylabel 명령을 사용한다. 또 플롯의 위에는 title 명령으로 제목(title)을 붙일 수 있다.

In [16]:

X = np.linspace(-np.pi, np.pi, 256) C, S = np.cos(X), np.sin(X) plt.plot(X, C, label="cosine") plt.xlabel("time") plt.ylabel("amplitude") plt.title("Cosine Plot") plt.show()

연습 문제 1

여러가지 함수를 사용하여 아래 조건에 맞는 그래프를 그린다.

  • xlabel, ylabel, title을 모두 갖추고 있어야 한다.
  • 하나의 Figure(일단, 그림이라고 이해한다. 아래에 자세한 설명이 있다.)에 3개 이상의 Plot을 그린다.
  • 각 Plot은 다른 선, 마크, 색 스타일을 가진다.
  • legend는 그래프와 겹치지 않는 곳에 위치 시키도록 한다.

그림의 구조

Matplotlib가 그리는 그림은 Figure 객체, Axes 객체, Axis 객체 등으로 구성된다. Figure 객체는 한 개 이상의 Axes 객체를 포함하고 Axes 객체는 다시 두 개 이상의 Axis 객체를 포함한다. 다음 그림은 이 구조를 설명하고 있다.

Figure는 그림이 그려지는 캔버스나 종이를 뜻하고 Axes는 하나의 플롯, 그리고 Axis는 가로축이나 세로축 등의 축을 뜻한다. Axes와 Axis의 철자에 주의한다.

Figure 객체

모든 그림은 Figure 객체. 정식으로는 Matplotlib.figure.Figure 클래스 객체에 포함되어 있다. 내부 플롯(inline plot)이 아닌 경우에는 하나의 Figure는 하나의 아이디 숫자와 윈도우(Window)를 가진다. 주피터 노트북에서는 윈도우 객체가 생성되지 않지만 파이썬을 독립 실행하는 경우에는 하나의 Figure당 하나의 윈도우를 별도로 가진다. Figure 객체에 대한 자세한 설명은 다음 웹사이트를 참조한다.

원래 Figure를 생성하려면 figure 명령을 사용하여 그 반환값으로 Figure 객체를 얻어야 한다. 그러나 일반적인 plot 명령 등을 실행하면 자동으로 Figure를 생성해주기 때문에 일반적으로는 figure 명령을 잘 사용하지 않는다. figure 명령을 명시적으로 사용하는 경우는 여러개의 윈도우를 동시에 띄워야 하거나(line plot이 아닌 경우), Jupyter 노트북 등에서(line plot의 경우) 그림의 크기를 설정하고 싶을 때이다. 그림의 크기는 figsize 인수로 설정한다.

In [17]:

np.random.seed(0) f1 = plt.figure(figsize=(10, 2)) plt.title("figure size : (10, 2)") plt.plot(np.random.randn(100)) plt.show()

현재 사용하고 있는 Figure 객체를 얻으려면(다른 변수에 할당할 수도 있다.) gcf 명령을 사용한다.

In [18]:

f1 = plt.figure(1) plt.title("현재의 Figure 객체") plt.plot([1, 2, 3, 4], 'ro:') f2 = plt.gcf() print(f1, id(f1)) print(f2, id(f2)) plt.show()

Figure(2400x1500) 139884724187208 Figure(2400x1500) 139884724187208

Axes 객체와 subplot 명령

때로는 다음과 같이 하나의 윈도우(Figure)안에 여러개의 플롯을 배열 형태로 보여야하는 경우도 있다. Figure 안에 있는 각각의 플롯은 Axes 라고 불리는 객체에 속한다. Axes 객체에 대한 자세한 설명은 다음 웹사이트를 참조한다.

Figure 안에 Axes를 생성하려면 원래 subplot 명령을 사용하여 명시적으로 Axes 객체를 얻어야 한다. 그러나 plot 명령을 바로 사용해도 자동으로 Axes를 생성해 준다.

subplot 명령은 그리드(grid) 형태의 Axes 객체들을 생성하는데 Figure가 행렬(matrix)이고 Axes가 행렬의 원소라고 생각하면 된다. 예를 들어 위와 아래 두 개의 플롯이 있는 경우 행이 2 이고 열이 1인 2x1 행렬이다. subplot 명령은 세개의 인수를 가지는데 처음 두개의 원소가 전체 그리드 행렬의 모양을 지시하는 두 숫자이고 세번째 인수가 네 개 중 어느것인지를 의미하는 숫자이다. 따라서 위/아래 두개의 플롯을 하나의 Figure 안에 그리려면 다음처럼 명령을 실행해야 한다. 여기에서 숫자 인덱싱은 파이썬이 아닌 Matlab 관행을 따르기 때문에 첫번째 플롯을 가리키는 숫자가 0이 아니라 1임에 주의하라.

subplot(2, 1, 1) # 여기에서 윗부분에 그릴 플롯 명령 실행 subplot(2, 1, 2) # 여기에서 아랫부분에 그릴 플롯 명령 실행

tight_layout 명령을 실행하면 플롯간의 간격을 자동으로 맞춰준다.

In [19]:

x1 = np.linspace(0.0, 5.0) x2 = np.linspace(0.0, 2.0) y1 = np.cos(2 * np.pi * x1) * np.exp(-x1) y2 = np.cos(2 * np.pi * x2) ax1 = plt.subplot(2, 1, 1) plt.plot(x1, y1, 'yo-') plt.title('A tale of 2 subplots') plt.ylabel('Damped oscillation') print(ax1) ax2 = plt.subplot(2, 1, 2) plt.plot(x2, y2, 'r.-') plt.xlabel('time (s)') plt.ylabel('Undamped') print(ax2) plt.tight_layout() plt.show()

AxesSubplot(0.125,0.536818;0.775x0.343182) AxesSubplot(0.125,0.125;0.775x0.343182)

만약 2x2 형태의 네 개의 플롯이라면 다음과 같이 그린다. 이 때 subplot 의 인수는 (2,2,1)를 줄여서 221 라는 하나의 숫자로 표시할 수도 있다. Axes의 위치는 위에서 부터 아래로, 왼쪽에서 오른쪽으로 카운트한다.

In [20]:

np.random.seed(0) plt.subplot(221) plt.plot(np.random.rand(5)) plt.title("axes 1") plt.subplot(222) plt.plot(np.random.rand(5)) plt.title("axes 2") plt.subplot(223) plt.plot(np.random.rand(5)) plt.title("axes 3") plt.subplot(224) plt.plot(np.random.rand(5)) plt.title("axes 4") plt.tight_layout() plt.show()

subplots 명령으로 복수의 Axes 객체를 동시에 생성할 수도 있다. 이때는 2차원 ndarray 형태로 Axes 객체가 반환된다.

In [21]:

fig, axes = plt.subplots(2, 2) np.random.seed(0) axes[0, 0].plot(np.random.rand(5)) axes[0, 0].set_title("axes 1") axes[0, 1].plot(np.random.rand(5)) axes[0, 1].set_title("axes 2") axes[1, 0].plot(np.random.rand(5)) axes[1, 0].set_title("axes 3") axes[1, 1].plot(np.random.rand(5)) axes[1, 1].set_title("axes 4") plt.tight_layout() plt.show()

연습 문제 2

여러가지 함수를 사용하여 위와 같이 subplot들로 구성된 그림을 그려보자. 모든 subplot에 대해 xlabel, ylabel, title이 있어야 한다.

Axis 객체와 축

하나의 Axes 객체는 두 개 이상의 Axis 객체를 가진다. Axis 객체는 플롯의 가로축이나 세로축을 나타내는 객체이다. 보다 자세한 내용은 다음 웹사이트를 참조한다.

여러가지 플롯을 하나의 Axes 객체에 표시할 때 y값의 크기가 달라서 표시하기 힘든 경우가 있다. 이 때는 다음처럼 twinx 명령으로 대해 복수의 y 축을 가진 플롯을 만들수도 있다. twinx 명령은 x 축을 공유하는 새로운 Axes 객체를 만든다.

In [22]:

fig, ax0 = plt.subplots() ax1 = ax0.twinx() ax0.set_title("2개의 y축 한 figure에서 사용하기") ax0.plot([10, 5, 2, 9, 7], 'r-', label="y0") ax0.set_ylabel("y0") ax0.grid(False) ax1.plot([100, 200, 220, 180, 120], 'g:', label="y1") ax1.set_ylabel("y1") ax1.grid(False) ax0.set_xlabel("공유되는 x축") plt.show()