[부동산 | Phase3] 아파트 현황조사(고양시) - matplotlib 기본 (3부)



 지난 포스팅에서 예고했던 행정동별 세대수 수직막대그래프와 행정동별 건령 선형그래프를 한 개의 chart에 그리는 방법을 살펴 보도록 하겠습니다.


 우선 행정동별 세대수 막대그래프는 지난 시간에 수평막대그래프로 그려 보았습니다. 그런데, 선형 그래프를 수평막대그래프와 매치하는 것은 최종 결과물의 시인성을 추정해 보았을 때 그리 좋지 못합니다. 해서 행정동별 세대수 그래프는 수직막대그래프로 다시 고쳐 그려 보겠습니다.


x1 = b1['행정동']
y1 = b1['세대수']

plt.bar(x1, height=y1, width=0.5, align='center', color='blue', alpha=1.0, edgecolor='grey', linewidth=0.3)
plt.tick_params(axis="y", labelsize=7)
plt.grid(axis='y', linestyle='-.', linewidth=0.5, color='black', alpha=0.3)
plt.tick_params(axis="x", labelsize=7, labelrotation=90)
plt.show()


결과는 다음과 같습니다.



plt.plot()   matplotlib lineplot 그리기



 이제 이어서 선형 그래프를 그려보겠습니다. 

x1 = b1['행정동']
y2 = b1['건령']

plt.plot(x1, y2, linestyle='dashdot', marker='.', linewidth=1.5)
plt.tick_params(axis="x", labelsize=7, labelrotation=90)
plt.tick_params(axis="y", labelsize=7)
plt.show()

 선형 그래프는 plt.plot()으로 그릴 수 있습니다. 단순하게 x축 변수와 y축 변수를 배분하면 되며, 다른 plot들과 마찬가지로 각 종의 옵션으로 그래프를 충분히 꾸밀 수 있습니다. 아래 공식문서의 링크를 타고 들어가 보시면 다양한 옵션 사용 방법에 대한 내용을 확인하실 수 있습니다.


링크 : matplolib.pyplot.plot 공식문서 





matplotlib lineplot과 barplot 동시에 그리기



 이제 x축의 값은 동일하게 x1값이 배분된 두 개의 그래프를 별도의 차트에 그렸습니다. 그렇다면 어떻게 한 개의 차트에 그릴 수 있는지 아래의 코드를 보시겠습니다.

x1 = b1['행정동']
y1 = b1['세대수']
y2 = b1['건령']

# 수평막대 그래프
plt.bar(x1, height=y1, width=0.5, align='center', color='blue', alpha=1.0, edgecolor='grey', linewidth=0.3)
# 선형 그래프
plt.plot(x1, y2, linestyle='dashdot', marker='.', linewidth=1.5, color='red')
plt.tick_params(axis="x", labelsize=7, labelrotation=90)
plt.tick_params(axis="y", labelsize=7)
plt.grid(axis='y', linestyle='-.', linewidth=0.5, color='black', alpha=0.3)
plt.show()


 그렇습니다. plt.show()로 그래프를 돌리기 전 얹어 놓고 싶은 모든 종류의 plot에 대한 함수를 중복해서 올려 주기만 하면 됩니다. 그럼 결과를 보실까요.



정상적으로 막대그래프와 선형그래프가 동시에 표출되었습니다. 그런데, 이게 무슨 말이냐고 생각하실 겁니다. 막대 그래프 밖에 보이지 않는데요.. 이를 해명하기 위해 y축을 확대해서 보시겠습니다.




 보시다시피 dot marker가 찍힌 선이 0의 grid선상에 표출되어 보입니다. 확실히 나오긴 나온건데.. 문제는 y축을 단위차이가 현격한 두 series가 공유하고 있기 때문에 50이하의 값을 갖고 있는 선형그래프는 정상적으로 식별하기 불가능한 수준으로 나온 것입니다. 그렇다면, 이를 어떻게 해결해야 할까요? 엑셀에서는 이런 2종 결합 그래프를 유형화 시켜 사용자에게 선택하도록 기능화 해놨습니다. 그리고 y축을 왼쪽 y축과 오른쪽 y축을 배분하여 상호간에 y축 tick설정을 달리하도록 옵션을 제공합니다. 그렇다면, matplotlib에서는 이를 어떻게 구현해야 할까요?




axis.twinx()    matplotlib Plots with different scalses. 오른쪽 y축 라벨 꾸미기



 여기서는 matplotlib 공식 사이트의 'Plots with different scales' 문서를 참조하여 코딩해 보도록 하겠습니다.



 링크 : Plots with different scales 공식문서



 해당 문서에서는 Axes.twinx()라는 메소드를 제공한다고 언급하고 있습니다. 이제 제공된 예제문에 맞추어 우리의 코딩을 수정해 보도록 하겠습니다.


x1 = b1['행정동']
y1 = b1['세대수']
y2 = b1['건령']

fig, ax1 = plt.subplots()

color1 = 'tab:blue'
ax1.set_xlabel('행정동')
ax1.set_ylabel('세대수', color=color1)
ax1.bar(x1, height=y1, width=0.5, align='center', color=color1, alpha=1.0, edgecolor='grey', linewidth=0.3)
ax1.tick_params(axis='x',labelcolor='black', labelsize=7, labelrotation=90)
ax1.tick_params(axis='y', labelcolor=color1, labelsize=8)
plt.grid(axis='y', linestyle='-.', linewidth=0.5, color='black', alpha=0.3)
plt.grid(axis='x', linestyle='-.', linewidth=0.5, color='black', alpha=0.3)

ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis

color2 = 'tab:red'
ax2.set_ylabel('건령', color=color2) # we already handled the x-label with ax1
ax2.plot(x1, y2, linestyle='--', marker='.', linewidth=1.0, color=color2)
ax2.tick_params(axis='y', labelcolor=color2, labelsize=8)
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.show()


  중요 코드를 한줄 한줄 살펴 보시겠습니다.



 1) fig, ax1 = plt.subplots()


 나중에 심도 있게 다시 다루겠지만, subplots()함수는 한번의 call로 도표를 몇개를 그릴 것인지 지정할 수 있습니다. subplots()함수에 인자로서, int인 숫자를 배분하면 해당 숫자만큼의 도표를 한번의 call로 그려 낼 수 있습니다. 예를 들어, plt.subplots(2,2)라고 하면 횡으로 2개, 종으로 2개인 즉, 총 4개의 도표를 하나의 canvas위에 그려 냅니다. 동일하거나 서로 다른 x축, y축 값을 갖는 여러개의 데이터를 한 눈에 비교해 보기에 적합한 형식의 도표를 그릴 때 사용됩니다.

 우리는 plt.subplots()라고 했기 때문에 횡으로 1개, 종으로 1개인 즉, 총 1개의 도표를 하나의 canvas 위에 그린 것입니다. 

 한편, 우리가 그릴 첫번째 도표를 ax1이라는 변수에 배정하였고, 이제 ax1변수에 대해 하나의 plot유형으로서 메소드를 붙여 줌으로서 어떤 그래프를 그릴 것인지 정의할 수 있게 됩니다. 



 2) ax1. set_xlabel ('행정동')


 ax1 그래프의 x축 라벨 이름을 정의 합니다.



 3) ax1.set_ylabel('세대수', color=color1)


 ax1 그래프의 y축 라벨 이름을 정의 합니다.  한편으로, color1이라는 변수에 blue라는 색을 지정해 주었습니다. 이 변수를 인자에 그대로 대입함으로서 이제 y축 라벨 값은 파란색을 띄게 됩니다.



 4) ax1.bar(x1, height=y1, width=0.5, align='center', color=color1, alpha=1.0, edgecolor='grey', linewidth=0.3) 


  드디어, ax1 그래프는 bar()메소드에 의해 막대 그래프를 그리겠다고 정의 합니다. 앞서 정의한 데로, 인자값을 주어 막대그래프의 모양을 꾸며 줍니다. 단, color는 y축 라벨값과 맞춰 주기 위해 color1 변수에 지정된 값을 대입해 줍니다.



 5) ax2 = ax1.twinx()


 이 작업의 가장 중요한 코드가 되겠습니다. 공식문서에서는 twinx() 메소드는 x축을 공유하면서 2개의 y축 tick들을 독립적으로 정의해 사용할 수 있도록 해준다고 설명하고 있습니다. ax2변수에 ax1에 대한 twinx()에 의한 x축 공유 및 y2축의 독립적 사용을 정의하였습니다.




fig.tight_layout()   그래프 여백 줄이기



 6) fig.tight_layout()


  이 코드는 하나의 canvas위에 여러개의 도표가 그려질 때, 도표간의 사이즈 충돌로 인해 겹침 현상이 발생되는 것을 없애 줍니다. 예제문에서는 tight_layout() 메소드를 사용해야만 y2축(오른쪽 y축)이 잘리지 않고 잘 나온다고 합니다.



 이제 결과 확인을 위해 코드를 실행해 보겠습니다.


x축, y1축, y2축 라벨의 표시와 색깔 뿐만 아니라, grid()메소드를 통해 x축, y축 방향 grid 모두 잘 표현된 것이 확인 되었습니다.


이제 2개의 그래프를 하나의 canvas에 표현하는 방법을 배움으로서 우리는 데이터간의 시각적 비교 방법도 터득하였습니다.


다음 포스팅에서는 질문 (3)번으로 넘어가서 matplotlib의 사용을 계속해서 배워 보도록 하겠습니다.




# 이번 포스팅에서 배운 내용


a. matplotlib lineplot 그리기

b. matplotlib lineplot과 barplot 한번에 그리기

c. matplotlib Plots with different scalses. 오른쪽 y축 라벨 꾸미기. axis.twinx()

d. matplotlib fig.tight_layout()으로 그래프 여백 줄이기



(4부에서 계속..)

반응형

+ Recent posts