기록하는삶

[파이썬/Python] 데이터 시각화 _ Facet, 그래프 여러 개 그리기 본문

AI/데이터 시각화

[파이썬/Python] 데이터 시각화 _ Facet, 그래프 여러 개 그리기

mingchin 2022. 2. 12. 01:47
728x90
반응형

Facet은 사전적 정의로는 다면체의 한 면을 일컫는 말로, 데이터 시각화해서는 화면을 분할하는 것을 말한다. 경우에 따라 여러 개의 그래프를 한번에 그려놓는 것이 전달력을 위해 필요할 수 있는데, matplotlib을 활용할 때는 아래의 방법들로 진행할 수 있다.

 

matplotlib과 numpy는 설치해주자.

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

1) add_subplot

fig = plt.figure(figsize=(8,6))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(2,2,2)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(2,2,4)
ax1.set_title('ax1')
ax2.set_title('ax2')
ax3.set_title('ax3')
ax4.set_title('ax4')
plt.show()

위와 같이 하나씩 지정해 원하는 그래프를 그릴 수 있다. 이때 들어가는 3개의 숫자 abc는 전체 도화지 fig를 a*b로 쪼갠 것 중 c번째 위치를 의미한다. 불편한 점이 있다면 인덱스가 0-index가 아니다. (1로 시작한다.)

2) plt.subplots(n,m)

# fig, (ax1, ax2, ax3, ax4) = plt.subplots(2, 2)

fig, axes = plt.subplots(2, 2, figsize = (8,6))
# fig.set_figwidth(8)
# fig.set_figheight(6)
for i in range(2):
    for j in range(2):
        axes[i][j].set_title((i,j))
plt.show()

n*m으로 전체 도화지 fig를 쪼개 그래프를 만든다. 이때 fig, axes의 두 가지가 반환되며, fig는 도화지 axes는 그래프들을 담은 n*m ndarray이다. 따라서 이들에 각각 접근하기 위해서는 index로 접근해야하며, figsize는 정의할 때 지정하거나 따로 변경해줄 수 있다.

# fig, (ax1, ax2, ax3, ax4) = plt.subplots(2, 2)

fig, axes = plt.subplots(2, 2, figsize = (8,6))

for i, ax in enumerate(axes.flatten()):
    ax.set_title(str(i))
plt.show()

2차원으로 배열을 받는게 싫다면, 위처럼 flatten을 활용해 1차원 배열로 받는 것처럼 생각할 수 있다.

n, m = 1, 3

# squeeze=False -> 2차원으로 배열을 받음
fig, axes = plt.subplots(n, m, squeeze=False, figsize=(m*3, n*3))
idx = 0
for i in range(n):
    for j in range(m):
        axes[i][j].set_title(idx)
        idx+=1

plt.show()

반대로 원래 1차원 배열로 axes가 반환되는 경우에도 squeeze = False로 설정하면 2차원 배열로 받을 수 있다. 이는 가변적인 그래프 구조에 대해 반복문을 구성할 때 편리하다.

 

3) add_gridspec

fig를 여러 조각으로 잘라놓고, 그 일부를 병합한 공간에 특정 그래프를 그릴 수 있는데, 그 방법 중 하나다. fig.add_gridspec()이 반환하는 2차원 공간을 슬라이싱으로 활용한다.

fig = plt.figure(figsize=(8, 5))
fig.set_facecolor('lightgray')

gs = fig.add_gridspec(3, 3) # make 3 by 3 grid (row, col)

ax = [None for _ in range(5)]

ax[0] = fig.add_subplot(gs[0, :]) 
ax[0].set_title('gs[0, :]')

ax[1] = fig.add_subplot(gs[1, :-1])
ax[1].set_title('gs[1, :-1]')

ax[2] = fig.add_subplot(gs[1:, -1])
ax[2].set_title('gs[1:, -1]')

ax[3] = fig.add_subplot(gs[-1, 0])
ax[3].set_title('gs[-1, 0]')

ax[4] = fig.add_subplot(gs[-1, -2])
ax[4].set_title('gs[-1, -2]')

for ix in range(5):
    ax[ix].set_xticks([])
    ax[ix].set_yticks([])

plt.tight_layout()
plt.show()

4) subplot2grid

위와 유사한 구현을 할 수 있는 또 다른 방법이다. 슬라이싱이 아닌 쪼개는 방법, 시작 위치, 차지할 공간을 인자로 각각 던져주며 그래프를 그리는 방법이다. 개인적으로는 위의 방법이 더 쉽게 느껴진다.

fig = plt.figure(figsize=(8, 5)) # initialize figure
fig.set_facecolor('lightgray')

ax = [None for _ in range(6)] # list to save many ax for setting parameter in each

ax[0] = plt.subplot2grid((3,4), (0,0), colspan=4) # 순서대로 (전체를 어떤 shape으로 쪼개는가, 시작 위치, 차지할 공간의 수)
ax[1] = plt.subplot2grid((3,4), (1,0), colspan=1)
ax[2] = plt.subplot2grid((3,4), (1,1), colspan=1)
ax[3] = plt.subplot2grid((3,4), (1,2), colspan=1)
ax[4] = plt.subplot2grid((3,4), (1,3), colspan=1,rowspan=2)
ax[5] = plt.subplot2grid((3,4), (2,0), colspan=3)


for ix in range(6): 
    ax[ix].set_title('ax[{}]'.format(ix)) # make ax title for distinguish:)
    ax[ix].set_xticks([]) # to remove x ticks
    ax[ix].set_yticks([]) # to remove y ticks
    
fig.tight_layout()
plt.show()

5) add_axes

직접 축을 원하는 위치에 넣는 방식으로 그래프를 여러 개 그릴 수도 있다. 이때 list에 담아 던져주는 인자들은 전체 fig의 사이즈의 가로, 세로에 대한 비율 정보를 의미한다. 

fig = plt.figure(figsize=(8, 5))
fig.set_facecolor('lightgray')

ax = [None for _ in range(3)]

ax[0] = fig.add_axes([0.1,0.1,0.8,0.4]) # x, y, dx, dy
ax[1] = fig.add_axes([0.15,0.6,0.25,0.6])
ax[2] = fig.add_axes([0.5,0.6,0.4,0.3])

for ix in range(3):
    ax[ix].set_title('ax[{}]'.format(ix))
    ax[ix].set_xticks([])
    ax[ix].set_yticks([])

plt.show()

6) inset_axes

fig 내에 미니맵 등 작은 subplot을 추가하고 싶을 때 사용할 수 있다. 대표적인 사용 예시는 아래와 같다.

fig, ax = plt.subplots(figsize=(8,6))

color=['royalblue', 'tomato']
ax.bar(['A', 'B'], [1, 2],
       color=color
      )

ax.margins(0.2) # 양 옆 공간 확보를 위한 margins
axin = ax.inset_axes([0.8, 0.8, 0.2, 0.2])
axin.pie([1, 2], colors=color, 
         autopct='%1.0f%%')
plt.show()

fig, ax = plt.subplots(1, 1)

# 이미지를 보여주는 시각화
# 2D 배열을 색으로 보여줌
im = ax.imshow(np.arange(100).reshape((10, 10)))

divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)

fig.colorbar(im, cax=cax)
plt.show()

 

728x90
반응형