[Matplotlib] 03. Axes Setup: Text, Label, and Annotation
kr-dev·@dj-on-steem·
0.000 HBD[Matplotlib] 03. Axes Setup: Text, Label, and Annotation
"""
제 개인적 목표는
1. Object-Oriented Programming과 친해지기
2. Github와 친해지기 입니다.
이 목표에 닿기 위해 일단 제가 나름 좀 아는 Python, 그 중에서도 _**Numpy**_와 _**Matplotlib**_로부터 시작하려 합니다.
"""

## 03. Axes Setup: Text, Label, and Annotation
그림의 x축 혹은 y축의 Label이름표와 임의의 장소에 Text표시, 그리고 Annotation에 대하여 다뤄보겠습니다.
### 03.1. Axes Label
x축과 y축의 Label이름표를 다는 명령어는
[Axes.set_xlabel(xlabel, fontdict=None, labelpad=None, **kwargs)](https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.set_xlabel.html#matplotlib.axes.Axes.set_xlabel)
[Axes.set_ylabel(ylabel, fontdict=None, labelpad=None, **kwargs)](https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.set_ylabel.html#matplotlib.axes.Axes.set_ylabel)
가 있습니다.
사용법은 간단하며, 일단 예제 코드를 보시겠습니다.
```
import sys
import numpy as np
import matplotlib.pyplot as plt
###--- Synthesizing data to be plotted ---###
x = np.arange(5) # Same as x = np.array(range(5))
y = x**2 # Basically item-wise calculation for numpy arrays
###--- Plotting Start ---###
##-- Page Setup --##
fig = plt.figure() # Define "figure" instance
fig.set_size_inches(6,4.5) # Physical page size in inches, (lx,ly)
suptit="Label, Text, and Annotation"
fig.suptitle(suptit,fontsize=15) # Title for the page
fig.subplots_adjust(left=0.12,right=0.95,bottom=0.15,top=0.91)
##-- Plotting for axis1 --##
ax1 = fig.add_subplot(1,1,1) # subplot(# of rows, # of columns, indicater)
ax1.plot(x,y) # plotting line graph
##-- Label, Text, and Annotation --##
ax1.set_xlabel('Left\nTop',ha='left',va='top',x=0.,fontsize=12)
ax1.set_ylabel('Left\nTop',ha='left',va='top',y=0.,fontsize=12)
#ax1.set_xlabel('Center\nCenter',ha='center',va='center',x=0.5,fontsize=12)
#ax1.set_ylabel('Center\nCenter',ha='center',va='center',y=0.5,fontsize=12)
#ax1.set_xlabel('Right\nBottom',ha='right',va='bottom',x=1.,fontsize=12)
#ax1.set_ylabel('Right\nBottom',ha='right',va='bottom',y=1.,fontsize=12)
ax1.text(0.5,15.,'Normal Text')
pos1=ax1.get_position().bounds ##<= (left,bottom,width,height)
plt.figtext(pos1[0]+pos1[2]*0.05,pos1[1]+pos1[3]*0.85,'Text in Pink Box',backgroundcolor='pink',color='k',fontsize=12)
ax1.annotate(r'$y=x^2$', xy=(3., 9.), xycoords='data',
xytext=(3.5,4.), textcoords='data', size=12,
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=0.5"),
)
##-- Seeing or Saving Pic --##
#plt.show() #- If want to see on screen -#
outdir = "./"
outfnm = outdir+"03_axes_setup.textlabel1a.png" # File format is decided by the file name, eg. png here
#fig.savefig(outfnm,dpi=100,facecolor='0.9',bbox_inches='tight') # dpi: pixels per inch
fig.savefig(outfnm,dpi=100,facecolor='0.9') # dpi: pixels per inch
sys.exit()
```
<br>
위 코드에서 Label의 정렬 방법을 각각 세 가지로 설정하였을 때 아래 그림과 같이 정렬이 됩니다.

x축에서는 "Center & Top"이, y축에서는 "Center & Bottom"이 적당해보이는군요. 여기서 "Top"과 "Bottom"은 각각 기준점에 글자의 상단 그리고 하단이 위치한다는 의미입니다.
만약 y축 이름표를 오른쪽에 붙이고 싶으면 어떻게 할까요?
위 예제 코드의 "ax1.set_ylabel(..." 부분을 다음과 같이 고치면 됩니다.
```
ax1.set_ylabel('Y Label on Right',fontsize=12,rotation=-90,labelpad=15)
ax1.yaxis.set_label_position('right')
```
더하여, 사실 그림 좌우 여백도 좀 손을 봤습니다. (```fig.subplots_adjust(left=0.07,right=0.9,bottom=0.15,top=0.91)```)
그럼 아래와 같은 그림이 나옵니다.

그림 오른쪽에 표시하는 핵심은 ```ax1.yaxis.set_label_position('right')```인데, ```ax1.set_ylabel()```에도 약간의 수정이 가해졌습니다. 오른쪽으로 갔으니 글자를 돌려야 해서 ```rotation=-90```이 들어갔고 (이게 없으면 기본은 "rotation=90"입니다.), 그렇게 돌렸더니 축에 너무 붙어서 ```lablepad=12```로 여백을 줬습니다. y축 이름표를 오른쪽으로 보내면 "va='Top' or 'Bottom'"이 작동을 안합니다. 그래서 "labelpad"를 이용하여 위치를 조정해주어야 합니다. "labelpad"의 숫자는 픽셀 포인트를 의미합니다.
### 03.2. Text and Figtext
Text는 Axes에 속한 함수입니다. 따라서,
```ax1.test(0.5,15.,'Normal Text')```
이렇게 실행됩니다. Axes에 속한 함수들은 대부분 위치를 데이타 기준으로 잡습니다. 즉, 위 예는 x=0.5, y=15인 좌표를 기준으로 Text를 표시한다는 뜻입니다. 위 그림을 자세히 보면, ```ha="left", va="bottom"```이 기본으로 설정되었음을 알 수 있습니다.
Figtext는 plt(=matplotlib.pyplot)레벨의 함수입니다. Figtext의 가장 큰 특징은 글 테두리 상자를 자동으로 생성한다는 점입니다. 위 예에서는 상자의 색깔도 지정해보았습니다. 색 이름은 HTML에 사용되는 색 이름은 거의 다 바로 쓸 수 있습니다.
```
pos1=ax1.get_position().bounds ##<= (left,bottom,width,height)
plt.figtext(pos1[0]+pos1[2]*0.05,pos1[1]+pos1[3]*0.85,'Text in Pink Box',backgroundcolor='pink',color='k',fontsize=12)
```
Figtext는 plt의 함수이기 때문에, Axes와 상관없이 종이 전체의 비율값에 글자를 쓰고 테두리 상자를 그립니다. 그림 상에서 임의의 위치를 비율로 정확히 집어내기는 어렵기 때문에, 여기서는 일단 정의된 Axes의 모서리 값을 불러옵니다. 그 후 그 모서리를 기준으로 적당한 비율을 움직여 위치를 잡아보았습니다.
### 03.3. Annotation
Matplotlib에서 제공되는 함수 중에 이렇게 화살표를 이용하여 그림에 주석을 달 수 있는 도구가 있습니다.
```
ax1.annotate(r'$y=x^2$', xy=(3., 9.), xycoords='data',
xytext=(3.5,4.), textcoords='data', size=12,
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=0.5"),
)
```
Anotate는 기본적으로 2개의 위치가 필요합니다. 하나는 Text가 위치할 장소이고, 다른 하나는 화살표가 가리킬 장소입니다. 위 예에서는 두 위치 모두 데이타 기준으로 설정되었습니다. ("xycoords='data'"; 그 외 다양한 방식이 가능합니다.) 화살표도 다양한 형식이 이미 정의되어 있습니다. 자세한 내용은
[Annotation](https://matplotlib.org/users/annotations.html)
[Axes.annotate(*args, **kwargs)](https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.annotate.html#matplotlib.axes.Axes.annotate)
[matplotlib.patches.FancyArrowPatch](https://matplotlib.org/api/_as_gen/matplotlib.patches.FancyArrowPatch.html#matplotlib.patches.FancyArrowPatch)
를 참조하시길 바랍니다.
위 Annotation 예제페이지에 있는 그림 몇 장 보시면 어떤 것들이 가능한지 감이 잡힐 것 같습니다.

