import matplotlib as mpl
import matplotlib.pyplot as plt
항상 plt.show()를 마지막에 입력하여 지금까지 그린 그래프를 보여주라는 명령을 내려야 함
그래프 그리는 원리 : Figure라는 큰 틀에 Ax라는 Subplot을 추가해서, Ax에 그래프 그림
# 방법 1 : Ax를 하나씩 추가해 줌
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
plt.show()
"""
fig.add_subplot(abc)
Figure를 1 * 2 공간으로 쪼갠다.
이후, c번째 공간의 Ax를 할당시켜주는 것이다.
예를 들어, ax1같은 경우 1 * 2공간으로 figure를 쪼개고 첫번째 Ax를 할당 받은 것이다
"""
# 방법 2 : Ax들을 한번에 (리스트 형식으로) 만들어줌
fig, ax = plt.subplots(1,2)
"""
figure를 생성한 이후 1*2 공간으로 쪼갬. 이후 생성된 공간을 리스트 형식으로 ax에 반환
ax[0] : 121공간, ax[1] : 122공간
"""
Figure 크기 조정 : figsize 활용
fig = plt.figure(figsize=(x,y))
# Figure 크기를 x * y size로 맞춤(단위 : inch)
#방법 1 : 한 글자로 색상을 정함
ax.plot([1,1,1], color = 'r')
# 방법 2 : 미리 matplotlib에서 지정해 놓은 색상 이름 입력
ax.plot([2,2,2], color = 'forestgreen')
# 방법 3 : Hex Code를 활용해 색 표현
ax.plot([3,3,3], color='#000000')

ax = fig.add_subplot(131)
ax2 = fig.add_subplot(132)
ax2.set_xticks([0,2,4,6,8,10])
# x축의 값을 0,2,4,6,8,10로 표기
ax3 = fig.add_subplot(133)
ax3.set_xticks([0,2,4,6,8,10])
ax3.set_xticklabels(['zero','two','four','six','eight','ten'])
"""
x축의 값을 해당 Text로 바꿈. 이 때, set_xticklabels로 Text를 입력하기 전
동일한 Size List를 활용하여 set_xticks로 값을 바꿔준 이후 set_xticklabels를
사용해야 UserWarning이 발생하지 않음
"""

bbox = dict(boxstyle='round', ec = 'blue', facecolor='wheat', alpha = 0.7){figure}.suptitle("{Figure Name}") : Figure Name을 지정하는 방법{ax}.set_title("{ax Name}") : 지정한 Ax Name을 지정하는 방법fig, ax = plt.subplots(1,2,figsize=(12,5))
fig.suptitle("Figure Tite")
ax[0].set_title("Ax[0] Title")
ax[1].set_title("Ax[1] Title")

{ax}.set_xlabel("{X축 이름}") : Ax의 X축에 지정한 Text를 나타냄{ax}.set_ylabel("{Y축 이름}") : Ax의 Y축에 지정한 Text를 나타냄plt.xticks([{숫자형 list}]) : 리스트에 들어 있는 값들로 X축 값을 바꿈plt.yticks([{숫자형 list}]) : 리스트에 들어 있는 값들로 Y축 값을 바꿈ax.set_xlabel("X-label")
ax.set_ylabel("Y-label")
plt.xticks([0,1,2])

ax.plot({그래프 그릴 Data}, label="{해당 그래프를 구분할 이름}") : 해당 그래프를 설명할 Label을 지정ax.legend() : 매우 중요! 만약 이 코드가 존재하지 않는다면 설정한 Legend가 보이지 않음# 왼쪽 그래프
ax[0].plot(x,y, label="x and y1")
ax[0].plot(x,y2, label = "x and y2")
ax[0].legend()
# 오른쪽 그래프
ax[1].plot(x,y, label="x and y1")
ax[1].plot(x,y2, label = "x and y2")
ax[1].legend(
shadow = True,
title = "Label Title",
labelspacing=2.3,
loc = 'lower right'
)

bbox = dict(boxstyle='round', ec='blue', facecolor='wheat',alpha=0.7)
ax.plot(x,y)
ax.text(x = x[0],y = y[0],s="index 0")
# x : Text가 나타날 x좌표, y : Text가 나타날 y 좌표
# s : 내가 입력하고 싶은 Text
plt.annotate(xy=(x[1],y[1]),text="index 1")
# Annotation. 이것만 보면 text와 뭔 차인가 싶다
plt.annotate(xy=(x[2],y[2]),text="index 2",
xytext=(x[2], 0.9),
arrowprops=dict(arrowstyle="->"),
bbox = bbox)
"""
text : 중요한 점! Annotation은 문자 입력 시 s Parameter가
아닌 text Parameter를 활용한다
arrowprops : Dict type으로 화살표에 대한 정보 값을 전달해줌
bbox : Annotation Text를 포함하고 있는 bbox에 대한 설정을 전달해줌
"""
Text와 Annotation의 Parameter를 보면 차이가 심함을 알 수 있다.
xy 뿐만 아니라 xytext라는 값이 따로 존재함을 알 수 있다
xy : Annotation이 "가리키고 있을" 위치.
즉, Annotation은 (x[2], y[2])를 가리키고 있다
xytext : Annotation이 "존재하고 있는" 위치.
Annoation은 (x[2],0.9) 위치에 존재하며 xy로 지정된
(x[2],y[2]) Point를 가리키고 있을 것임을 알 수 있다
fig.text(x,y,s="{입력할 문자}")를 통해 전체 Figure에 대해서도 Text를 쓸 수 있다
이 경우, Figure 가로 세로 끝을 각각 1로 두어 비율로써 Text 위치를 표현한다
하지만, 어디까지나 "비율"로 표현하기 때문에 정확하게 위치를 파악하기는 어려움이 있다.

ax[0].plot(x,y)
ax[0].text(x[1],y[1],s="index 1",
va = 'center', ha='center',
family='fantasy',
style='italic', weight='bold',size = 20,
color = 'red',
alpha=0.7,
backgroundcolor='yellow'
)
ax[1].plot(x,y)
ax[1].text(x[1],y[1],s="index 1", size = 20)




fig = plt.figure(dpi=150)
fig.savefig("{저장할 파일 이름}")
fig, axes = plt.subplots(n, m, squeeze=False)
# 이 경우, n이나 m이 1이더라도 axes는 무조건 axes[i][j] 꼴로 접근해야함
# (n,m) = (1,3)일 경우 axes[2]로 접근하는 것이 아닌 axes[0][2]로 접근
axes.flatten()
# 만약 axes를 진짜로 flatten() 시키고 싶을 경우,
# axes = axes.flatten()으로 처리하면 됨
# 하지만, 굳이...? 그럴거면 첨부터 1*N으로 만들면 될 것이다
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121, aspect=1)
ax2 = fig.add_subplot(122, aspect=0.5)
ax2.set_xlim(0, 1)
ax2.set_ylim(0, 2)
# ax1의 경우 aspect = 1이므로 x축의 눈금 Range와 y축의 Range가 같을 것이다
# ax2의 경우 0.5이므로, x축의 눈금 Range가 y축의 Range의 절반(0.5)가 될 것이다

ax들의 Size를 다르게 하는 방법
fig = plt.figure(figsize=(8, 5))
gs = fig.add_gridspec(3, 3)
# fig.add_gridspec(row,col)을 통해 Grid 형태로 쪼개줌
# row : Row 수, col : Column 수. 위 예시에서는 3*3 Grid Layout으로 쪼개졌음
# 이후, add_subplot을 통해 Slicing으로 원하는 Grid 영역을 가지고 올 수 있음
ax = [None for _ in range(5)]
ax[0] = fig.add_subplot(gs[0, :])
ax[0].set_title('gs[0, :]')
# gs[0,:] : gs[0][0], gs[0][1], gs[0][2]를 모두 가지고 와 하나의 공간으로 만듦
# 이렇게 만든 하나의 공간을 ax[0]에 할당하는 것
ax[1] = fig.add_subplot(gs[1, :-1])
ax[1].set_title('gs[1, :-1]')
...
for ix in range(5):
ax[ix].set_xticks([])
ax[ix].set_yticks([])
plt.tight_layout()
plt.show()

fig = plt.figure(figsize=(8,5))
ax = [None for _ in range(6)]
"""
# plt.subplot2grid((생성할 grid의 row, 생성할 grid의 col),
(Ax의 초기점이 될 x, Ax의 초기점이 될 y),
rowspan={시작 지점부터 몇 개 Row를 합칠 것인가},
colspan={시작 지점부터 몇 개 Column을 합칠 것인가})
"""
ax[0] = plt.subplot2grid((3,4),(0,0), rowspan = 3, colspan = 2)
ax[1] = plt.subplot2grid((3,4),(0,2), colspan = 2)
ax[2] = plt.subplot2grid((3,4),(1,2), rowspan = 2)
"""
rowspan이나 colspan을 설정하지 않으면 1로 설정됨
ax[0]만 설명하겠다. 먼저, 3*4 grid로 쪼갰다.
먼저, row로 3만큼 확장했다. 따라서, 3*1 grid를 차지하고 있다
또한 col로 2만큼 확장했다. 따라서, 3*2 grid를 차지할 것이다
시작지점이 (0,0)이기 때문에 (0,0) Grid에서 시작된 3*2 Grid 모양을 가질 것이다
"""
for idx in range(3):
ax[idx].set_title("Grid"+str(idx))
# ax[i]에는 Grid{i}라는 title이 붙을 것임
fig.tight_layout() # 서로 눈금이 겹치지 않도록 하는 설정
plt.show()

기타 설정들(중요하진 않은 것 같아 코드 수행은 생략)
ax.inset_axes() : Ax 내부에 Subplot 추가make_axes_locatable(ax) : ax를 (X축 기준으로) 잘라서 Ax를 하나 추가함Grid
Grid Parameter
특별한 Data에 대한 선 추가하기
차트에서 그룹을 표현하는 면 추가하기
spines
Theme 바꾸기
mpl.style.use('seaborn')
# seaborn이라는 Theme을 Deafult 설정으로 바꾸는 방법이다
# mpl.style.available을 통해 설정 가능한 Theme List를 볼 수 있다
plt.rcParams[]from cycler import cycler
raw_light_palette = [
(0, 122, 255), # Blue
(255, 149, 0), # Orange
(52, 199, 89), # Green
(255, 59, 48), # Red
(175, 82, 222),# Purple
(255, 45, 85), # Pink
(88, 86, 214), # Indigo
(90, 200, 250),# Teal
(255, 204, 0) # Yellow
]
raw_dark_palette = [
(10, 132, 255), # Blue
(255, 159, 10), # Orange
(48, 209, 88), # Green
(255, 69, 58), # Red
(191, 90, 242), # Purple
(94, 92, 230), # Indigo
(255, 55, 95), # Pink
(100, 210, 255),# Teal
(255, 214, 10) # Yellow
]
raw_gray_light_palette = [
(142, 142, 147),# Gray
(174, 174, 178),# Gray (2)
(199, 199, 204),# Gray (3)
(209, 209, 214),# Gray (4)
(229, 229, 234),# Gray (5)
(242, 242, 247),# Gray (6)
]
raw_gray_dark_palette = [
(142, 142, 147),# Gray
(99, 99, 102), # Gray (2)
(72, 72, 74), # Gray (3)
(58, 58, 60), # Gray (4)
(44, 44, 46), # Gray (5)
(28, 28, 39), # Gray (6)
]
light_palette = np.array(raw_light_palette)/255
dark_palette = np.array(raw_dark_palette)/255
gray_light_palette = np.array(raw_gray_light_palette)/255
gray_dark_palette = np.array(raw_gray_dark_palette)/255
<설명>
Bar Plot 등을 그릴 때, 색깔을 지정해주지 않으면 Matplotlib에서 알아서
색 변경을 수행해줬다.
이 때의 색 변경이 맘에 들지 않을 경우, 내가 원하는 색 Palette로 지정하면
색 변화를 내가 원하는데로 지정해 줄 수 있다.
mpl.rcParams['axes.prop_cycle'] = cycler('color', dark_palette)
"""
왼쪽 그래프는 위 코드를 수행하기 전 Default Matplotlib 설정에서 그린 그래프이고,
오른쪽 그래프는 위 코드를 수행시켜 내가 원하는 색을 지정한 것이다.
색을 잘 살펴보면 색과 색 변화가 다르다는 것을 볼 수 있다.
(오른쪽 색이 내가 위에서 지정한 dark_palette이다)
"""

# Figure의 배경 색깔 변경
mpl.rcParams['figure.facecolor'] = gray_dark_palette[-2]
# Figure의 테두리 색 변경
mpl.rcParams['figure.edgecolor'] = gray_dark_palette[-2]
# ax의 배경색 변경
mpl.rcParams['axes.facecolor'] = gray_dark_palette[-2]
<설명>
왼쪽 차트는 Figure 및 ax 색을 변경하기 전 차트, 오른쪽 차트는 Figure 및 ax 색을
변경한 이후 차트이다.(즉, 위 코드를 수행시킨 이후 그린 차트)
gray_dark_palette[-2]에 지정된 hex code로 배경색을 지정했으므로,
ax 및 Figure 색이 어둡게 변한 것을 볼 수 있다.(Gray(5)로 색을 지정해줬음)

white_color = gray_light_palette[-2]
mpl.rcParams['text.color'] = white_color
mpl.rcParams['axes.labelcolor'] = white_color
mpl.rcParams['axes.edgecolor'] = white_color
mpl.rcParams['xtick.color'] = white_color
mpl.rcParams['ytick.color'] = white_color
<설명>
Text의 color, axes Laebl의 color, axes 테두리 color, xtick 및 ytick color를
하얀색으로 변경했다.
오른쪽 차트가 위 코드를 수행시킨 이후 그린 그래프로써, 텍스트 색 및 ax 테두리 색,
xtick과 ytick 색도 변경된 것을 볼 수 있다.
또한 예시에서는 보이지 않지만 Label의 색도 하얀색으로 변경된 것을 알 수 있다.

mplrcParamas['figure.dpi'] = 200
plt.rcParams.update(plt.rcParamsDefault)
mpl.rcParams['axes.spines.top'] = False
mpl.rcParams['axes.spines.right'] = False
"""
왼쪽 차트와 달리 오른쪽 차트는 위 코드를 실행시키고 난 뒤 그려진 차트이다.
보다시피, 오른쪽 축과 위쪽 축이 지워져있음을 확인할 수 있다.
"""

def score_distribution(f1, f2):
# f1, f2 : 어떤 Feature 끼리 Scatter Plot을 그릴지 지정해줌
fig = plt.figure(figsize=(12, 10))
gs = fig.add_gridspec(5, 6)
# 5 * 6 Grid로 Figure를 나눔
ax = fig.add_subplot(gs[:,:5])
ax.set_aspect(1)
# ax의 x축과 y축 비율을 1:1로 정함
# 즉, ax는 정사각형의 형태를 띄고 있을 것이다
sns.scatterplot(x = f'{f1} score', y = f'{f2} score', data=student,
hue_order = sorted(student['race/ethnicity'].unique()),
s=20, alpha=0.6, linewidth=0.5, hue = 'race/ethnicity')
# seaborn을 활용하여 전체 Data에 대한 Scatter Plot을 ax에 그림
# Matplotlib 설정을 그대로 따름을 알 수 있다.
sub_axes = [None] * 5
for idx,group in enumerate(sorted(student['race/ethnicity'].unique())):
sub_axes[idx] = fig.add_subplot(gs[idx,5], aspect=1)
# 현재 Group에 해당되지 않는 다른 Data들에 대한 Scatter Plot
sub_axes[idx].scatter(
x = student[student['race/ethnicity']!=group][f'{f1} score'],
y = student[student['race/ethnicity']!=group][f'{f2} score'],
s=5, alpha=0.2, color= white_color, linewidth=0.7,
label=group, zorder=5)
# 이번 ax에 주로 표현하고 싶은 Group에 대한 Scatter Plot 그리기
sub_axes[idx].scatter(
x = student[student['race/ethnicity']==group][f'{f1} score'],
y = student[student['race/ethnicity']==group][f'{f2} score'],
s=5, alpha=0.6, color= dark_palette[idx], linewidth=0.5,
label=group, zorder=10)
cnt = (student['race/ethnicity']==group).sum()
sub_axes[idx].set_title(f'{group} ({cnt})', loc='left', fontsize=9)
sub_axes[idx].set_xticks([])
sub_axes[idx].set_yticks([])
for axes in [ax] + sub_axes:
axes.set_xlim(-3, 103)
axes.set_ylim(-3, 103)
ax.set_title(
f'{f1.capitalize()} & {f2.capitalize()} Score Distribution',
loc='left', fontsize=15, fontweight='bold')
ax.set_xlabel(f'{f1.capitalize()} Score', fontweight='medium')
ax.set_ylabel(f'{f2.capitalize()} Score', fontweight='medium')
ax.legend(title='Race/Ethnicity', fontsize=10)
plt.show()
