파이썬・ML/matplotlib・seaborn

matplotlib 사용법 기초(add_subplot/subplots/subplot2grid/add_axes)

truezero 2023. 7. 26. 23:11

파이썬 데이터 시각화 관련 첫 포스팅입니다! 🤗

이번 포스팅에서는 matplotlib 라이브러리로 레이아웃을 구성하는 방법에 대해 알아보도록 하겠습니다.

import matplotlib.pyplot as plt

plt.figure

fig = plt.figure()

plt.figure 메서드는 그래프를 그리기 위한 전체 영역을 확보합니다.

단, 영역만 확보할 뿐 아직 아무것도 그려지지는 않습니다.

이렇게 인스턴스화 한 figure 객체는 그래프를 그릴 수 있는 넓은 도화지라고 생각하면 됩니다.

fig.add_subplot

fig.add_subplot 메서드는 확보된 영역에 차트를 그릴 수 있는 영역인 ax 객체를 생성합니다.

전달 가능한 매개변수의 목록은 다음과 같습니다.

  • nrows (fig 객체의 행 개수)
  • ncols (fig 객체의 열 개수)
  • index (fig 객체에서 subplot별 인덱스)

 

fig = plt.figure(figsize=(7, 7), facecolor='gray')

# ax1 = fig.add_subplot(311)과 동일합니다.
ax1 = fig.add_subplot(3, 1, 1)

# ax2 = fig.add_subplot(312)과 동일합니다.
ax2 = fig.add_subplot(3, 1, 2)

# ax3 = fig.add_subplot(313)과 동일합니다.
ax3 = fig.add_subplot(3, 1, 3)

위 예제코드는 3행1열 형태의 fig 객체를 인스턴스화합니다.

ax1, ax2, ax3은 각각 첫번째, 두번째, 세번째 subplot을 의미합니다.

add_subplot 예제1

 

fig2 = plt.figure(figsize=(7, 7), facecolor='linen')

ax1 = fig2.add_subplot(2, 2, 1)
ax2 = fig2.add_subplot(2, 2, 2)
ax3 = fig2.add_subplot(2, 1, 2)

fig2

변형된 차트 레이아웃을 구성할 수도 있습니다.

이때 필요한 점은 차트의 그리드 시스템을 바라보는 관점에 변화를 주는 것입니다.

위 예제코드를 실행하면 불규칙적인 레이아웃을 리턴합니다.

ax1, ax2는 그리드 시스템을 2행2열로 바라보지만 마지막 ax3는 2행1열 형태로 바라봅니다.

2행1열 중 두번째이므로 수평 방향으로 긴 차트 레이아웃이 나타나게 됩니다.

add_subplot 예제2

plt.subplots

# fig, (ax1, ax2) = plt.subplots(2, 1)
fig, axes = plt.subplots(2, 1, figsize=(7, 7), facecolor='linen')

plt.subplots는 앞서 정리한 plt.figure과 fig.add_subplot 메서드를 합친 메서드입니다.

한 가지 특징은 불규칙적인 차트 레이아웃을 구성할 수 없다는 점입니다.

다음 예제코드는 2행 1열의 레이아웃을 그립니다.

 

print(type(axes))
# <class 'numpy.ndarray'>

print(axes[0])
# Axes(0.125,0.53;0.775x0.35)

print(axes[1])
Axes(0.125,0.11;0.775x0.35)

위 코드에서 axes의 타입은 넘파이 배열(ndarray)입니다.

따라서 인덱싱을 통해 각 원소에 접근이 가능합니다.

 

fig, axes = plt.subplots(2, 2, figsize=(7, 7), facecolor='linen')

print(axes.shape)
# (2, 2)

print(axes)
# [[<Axes: > <Axes: >]
#  [<Axes: > <Axes: >]]

for ax in axes.flat:
    print(ax)
    # Axes(0.125,0.53;0.352273x0.35)
    # Axes(0.547727,0.53;0.352273x0.35)
    # Axes(0.125,0.11;0.352273x0.35)
    # Axes(0.547727,0.11;0.352273x0.35)

for idx, ax in enumerate(axes.flat):
    print(idx, ax)
    # 0 Axes(0.125,0.53;0.352273x0.35)
    # 1 Axes(0.547727,0.53;0.352273x0.35)
    # 2 Axes(0.125,0.11;0.352273x0.35)
    # 3 Axes(0.547727,0.11;0.352273x0.35)

다음 예제코드는 2행2열 형태의 그래프 레이아웃을 생성합니다.

총 4개의 그래프를 그리는데 모든 그래프는 axes를 구성하게 됩니다.

이때 axes는 2차원 배열의 형태를 띕니다.

따라서 각 차트에 접근하기 위해서는 axes 배열을 평탄화하는 과정이 필요합니다.

2차원 배열을 1차원으로 바꾸기 위해 ndarray 객체의 flat 속성을 사용합니다.

plt.subplots 예제

plt.subplot2grid

💡 plt.subplot2grid(shape, loc, rowspan, colspan, fig)

plt.subplot2grid는 plt.subplots 메서드에 비해 복잡한 형태의 그래프 레이아웃을 그릴 수 있습니다.

한 가지 주의할 점은 매개변수 fig의 인수로 인스턴스화 한 fig 객체를 전달해야 한다는 점입니다.

각 매개변수의 의미를 살펴보겠습니다.

  • shape (차트를 그릴 공간의 형태를 지정)
  • loc (차트를 그릴 인덱스 또는 위치를 지정)
  • rowspan (차트가 행 방향으로 차지할 칸 수)
  • colspan (차트가 열 방향으로 차지할 칸 수)

 

fig = plt.figure(figsize=(7, 7), facecolor='lightgreen')

ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3, fig=fig)
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2, fig=fig)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2, fig=fig)
ax4 = plt.subplot2grid((3, 3), (2, 0), fig=fig)
ax5 = plt.subplot2grid((3, 3), (2, 1), fig=fig)

아래 예제코드는 3행3열 형태의 그래프 레이아웃을 그립니다.

예를 들면 ax1은 열 방향으로 3칸을 차지하고, ax2는 열 방향으로 2칸을 차지합니다.

참고로 loc 매개변수의 시작 인덱스는 0입니다.

plt.subplot2grid 예제

 

# fig.add_subplot()
fig = plt.figure(figsize=(7, 7), facecolor='gray')
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 2, 3)
ax3 = fig.add_subplot(2, 2, 4)

# plt.subplot2grid()
fig2 = plt.figure(figsize=(7, 7), facecolor='lightgreen')
ax4 = plt.subplot2grid((2, 2), (0, 0), colspan=2, fig=fig2)
ax5 = plt.subplot2grid((2, 2), (1, 0), fig=fig2)
ax6 = plt.subplot2grid((2, 2), (1, 1), fig=fig2)

다음 예제코드는 fig.add_subplotplt.subplot2grid 메서드를 사용해서 동일한 레이아웃을 그립니다.

plt.subplot2grid 예제2
plt.subplot2grid
fig.add_subplot 예제2
fig.add_subplot

fig.add_axes

fig.add_axes 메서드를 사용하면 원하는 위치에 자유자재로 그래프를 그릴 수 있습니다.

우선 사용 가능한 매개변수의 목록을 살펴보겠습니다.

  • left (왼쪽으로부터 떨어진 거리)
  • right (오른쪽으로부터 떨어진 거리)
  • width (가로 길이 비율)
  • height (세로 길이 비율)

 

fig = plt.figure(figsize=(7, 7), facecolor='skyblue')

rect1 = [0.1, 0.1, 0.5, 0.5]
rect2 = [0.7, 0.1, 0.2, 0.5]
rect3 = [0.1, 0.7, 0.8, 0.2]

ax1 = fig.add_axes(rect1)
ax2 = fig.add_axes(rect2)
ax3 = fig.add_axes(rect3)

기본적인 메서드 사용법입니다.

fig.add_axes 예제1

 

fig = plt.figure(figsize=(7, 7), facecolor='skyblue')

left, bottom = 0.1, 0.1
spacing = 0.05
width1, height1 = 0.5, 0.5
width2 = 1 - (2*left + spacing + width1)
height2 = 1 - (2*bottom + spacing + height1)

rect1 = [left, bottom , width1, height1]
rect2 = [left, bottom + height1 + spacing, 1 - left*2, height2]
rect3 = [left + width1 + spacing, bottom, width2, height1]

ax1 = fig.add_axes(rect1)
ax2 = fig.add_axes(rect2)
ax3 = fig.add_axes(rect3)

바로 직전 코드를 개선한 코드입니다.

기준 수치를 변수로 선언하면 해당 변수의 값만 수정할 수 있기 때문에 그래프 레이아웃의 스케일을 다채롭게 구현할 수 있습니다.

fig.add_axes 예제2
width1=0.5, height1=0.5
fig.add_axes 예제2
width1=0.3, height1=0.3

 

fig = plt.figure(figsize=(7, 7), facecolor='skyblue')

left, bottom = 0.1, 0.1
spacing = 0.005
width1, height1 = 0.65, 0.65
width2 = 1 - (2*left + spacing + width1)
height2 = 1 - (2*bottom + spacing + height1)

rect1 = [left, bottom, width1, height1]
rect2 = [left + width1 + spacing, bottom, width2, height1]
rect3 = [left, bottom + height1 + spacing, width1, height2]

ax1 = fig.add_axes(rect1)
ax2 = fig.add_axes(rect2)
ax3 = fig.add_axes(rect3)

수치를 조절하면 다음 형태의 그래프 레이아웃도 구현이 가능합니다.

fig.add_axes 예제3

 

fig = plt.figure(figsize=(7, 7), facecolor='skyblue')

ax = fig.add_subplot(111)
ax_zoom = fig.add_axes([0.4, 0.4, 0.45, 0.45])

fig.add_axes 메서드의 장점으로, 중첩 레이아웃을 구현할 수 있습니다.

이때 ax를 선언하는 순서에 유의해야 합니다.

먼저 선언한 ax가 나중에 선언한 ax의 뒤에 위치하기 때문입니다.

fig.add_axes 예제4

마치며

이상으로 차트를 시각화하기 위한 사전 작업들에 대한 정리를 마치도록 하겠습니다.

  • fig = plt.figure() 👉🏻 ax = fig.add_subplot() & ax = fig.add_axes() & ax = plt.subplot2grid(fig=fig)
  • fig, axes = plt.subplots()

각 레이아웃 구성법의 장단점에 대해 숙지하고 상황에 따라 요구되는 바를 구현하면 좋을 것 같습니다.

다음 포스팅부터는 본격적으로 그래프를 시각화하는 기법들에 대해 알아보도록 하겠습니다.