SJ_Koding

Matplotlib 그래프 n by m 형태로 여러 개 출력하기 (subplot) 본문

Data analysis/Matplotlib

Matplotlib 그래프 n by m 형태로 여러 개 출력하기 (subplot)

성지코딩 2022. 1. 7. 01:11

Matplotlib을 사용하다보면 그래프를 세로로 나열하지 않고 아래의 그림과 같이  n by m 형태로 출력하고 싶은 경우가 대부분입니다.

4 by 4 subplot 적용 모습 (seaborn의 boxplot)

이번 게시글은 Matplotlib의 subplot에 대해 알아봅니다.

 

subplot은 plt.subplot(n, m, idx) 형태로 존재합니다. 여기서 n은 행의 개수, m은 열의 개수를 의미하며

subplot(4, 4, idx)는 4 x 4 의 형태로 그래프들을 나누어 출력하겠다! 라는 뜻이됩니다. 여기서 idx는 4x4의 바둑판이 있을때 몇 번째에 그래프를 출력할건지의 값입니다. idx가 6이라면 2행의 2번째에 올것입니다.

* 주의사항: subplot의 idx는 0이 아닌 1부터 시작입니다. 즉 1행의 1번째는 0이아닌 1입니다!.

 

plt.subplot(row, col, idx)

 

코드로 설명합니다.


import matplotlib.pyplot as plt
import numpy as np

x1 = np.arange(1, 10)
y1 = np.arange(10, 19)

x2 = np.arange(1, 10)
y2 = np.arange(20, 11, -1)

plt.subplot(2, 1, 1)
plt.plot(x1, y1)

plt.subplot(2, 1, 2)
plt.plot(x2, y2)

plt.subplot(1, 2, 1)
plt.plot(x1, y1)

plt.subplot(1, 2, 2)
plt.plot(x2, y2)

plt.subplot(2, 2, 1)
plt.plot(x1, y1)

plt.subplot(2, 2, 2)
plt.plot(x2, y2)

plt.subplot(2, 2, 3)
plt.plot(x1, y1)

plt.subplot(2, 2, 4)
plt.plot(x2, y2)

이 정도면 이해가 가셨으리 생각이 듭니다. 이제 이 subplot을 실전에서 응용해보겠습니다.

여러분들은 데이터들의 이상치를 찾기 위해서 컬럼별 boxplot을 출력할 경우가 매우 많을겁니다. 

따라서 어떠한 데이터 셋에서 각 컬럼별 이상치를 4 * 4 정도로 출력하여 보고싶다면 아래와 같이 진행하시면 됩니다.

 

for idx, col in enumerate(list(df_train)):
    plt.subplot(4, 4, idx+1)
    sns.boxplot(df_train[col])

subplot 시, 그래프가 겹쳐 출력되는 경우

 

엥? 왜 이렇게 나오나요! subplot 시, 그래프가 겹쳐 출력되는 경우입니다.

기본적으로 matplotlib은 도화지(?)의 사이즈를 한정해놓습니다. 

 

우리는 도화지의 크기를 변경하기 위해 plt.figure() 함수를 사용합니다.

기본 형태는

plt.figure(figsize = (가로 사이즈, 세로 사이즈))

입니다.

plt.figure(figsize=(15, 15))

for idx, col in enumerate(list(df_train)):
    plt.subplot(4, 4, idx+1)
    sns.boxplot(df_train[col])

4 by 4 subplot 적용 모습 (seaborn의 boxplot)

깔끔하게 출력이 잘 된 모습입니다.

 

* 주의사항 1. figure함수는 for문 안에서 진행하면 안됩니다! 아마도 한 줄로 세로로 쭉 출력될겁니다. 도화지의 크기는 한 번 지정해주면 됩니다.

 

* 주의사항 2. 만약 컬럼의 개수가 13개일땐 어떻게 해야할까요? 그냥 컬럼의 개수보다 많은 값을 subplot해주시면 됩니다. ex) plt.subplot(4, 4, idx)

 

감사합니다.

 

 

2023-11-06 추가) 오랜만이네요, 입문했을 시절 글이라 수정해봅니다.

for문을 사용할 필요 없습니다. plot의 layout인자를 사용하시면 됩니다

(참고: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html)

 

df.plot(kind='box', subplots=True, layout=(7, 5), figsize=(15, 21))
plt.show()

 

-sjkoding-