코딩하는 해맑은 거북이
[데이터시각화] Grid, 선/면 추가, 테두리 설정, Setting 변경 본문
본 게시물의 내용은 '부스트캠프 AI Tech - Data Visualization(안수빈)' 강의를 듣고 작성하였다.
해당 글은 아래의 5가지를 다룬다.
🍀 Grid
🚩 Student Score Dataset
🍀 선 추가하기 : Line
🍀 면 추가하기 : Span
🍀 테두리 설정하기 : Spines
🍀 Setting 변경
- 기본적인 Grid는 축과 평행한 선을 사용하여 거리 및 값 정보를 보조적으로 제공
- 색은 다른 표현들을 방해하지 않도록 무채색 (color)
- 항상 Layer 순서 상 맨 밑에 오도록 조정 (zorder)
- 큰 격자/세부 격자 (which=‘major’ | ‘minor’ | ‘both’)
- X축, Y축 따로 하거나, 동시에 설정할 수 있음 (axis=‘x’ | ‘y’ | ‘both’)
- 선의 스타일과 두께 설정 (linestyle, linewidth)
fig, ax = plt.subplots()
ax.grid()
plt.show()
np.random.seed(970725)
x = np.random.rand(20)
y = np.random.rand(20)
fig = plt.figure(figsize=(16, 7))
ax = fig.add_subplot(1, 1, 1, aspect=1)
ax.scatter(x, y, s=150,
c='#1ABDE9',
linewidth=1.5,
edgecolor='black', zorder=10)
ax.set_xticks(np.linspace(0, 1.1, 12, endpoint=True), minor=True)
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 1.1)
ax.grid(zorder=0, linestyle='--')
# ax.grid(zorder=0, linestyle='--', which='minor') # minor에만 grid
# ax.grid(zorder=0, linestyle='--', which='both') # 둘다 grid
ax.set_title(f"Default Grid", fontsize=15, va='center', fontweight='semibold')
plt.tight_layout()
plt.show()
np.random.seed(970725)
x = np.random.rand(20)
y = np.random.rand(20)
fig = plt.figure(figsize=(16, 7))
ax = fig.add_subplot(1, 1, 1, aspect=1)
ax.scatter(x, y, s=150,
c='#1ABDE9',
linewidth=1.5,
edgecolor='black', zorder=10)
ax.set_xticks(np.linspace(0, 1.1, 12, endpoint=True), minor=True)
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 1.1)
ax.grid(zorder=0, linestyle='--', axis='x', linewidth=2)
# ax.grid(zorder=0, linestyle='--', which='minor') # minor에만 grid
# ax.grid(zorder=0, linestyle='--', which='both') # 둘다 grid
ax.set_title(f"Default Grid", fontsize=15, va='center', fontweight='semibold')
plt.tight_layout()
plt.show()
- 전형적인 Grid는 아니지만 여러 형태의 Grid가 존재
🟨 두 변수의 합이 중요하다면 (x+y = c)
- X+Y = C를 사용한 Grid
- 회색 선에 걸치는 값은 X+Y 값이 동일
- Feature의 절대적 합이 중요한 경우 사용 (ex. 공격 + 수비 합으로 평가 / 국어+수학 비중 평가)
fig = plt.figure(figsize=(16, 7))
ax = fig.add_subplot(1, 1, 1, aspect=1)
ax.scatter(x, y, s=150,
c=['#1ABDE9' if xx+yy < 1.0 else 'darkgray' for xx, yy in zip(x, y)],
linewidth=1.5,
edgecolor='black', zorder=10)
## Grid Part
x_start = np.linspace(0, 2.2, 12, endpoint=True)
for xs in x_start:
ax.plot([xs, 0], [0, xs], linestyle='--', color='gray', alpha=0.5, linewidth=1)
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 1.1)
ax.set_title(r"Grid ($x+y=c$)", fontsize=15,va= 'center', fontweight='semibold')
plt.tight_layout()
plt.show()
🟨 비율이 중요하다면 (y = cx)
- Y = CX를 사용한 Grid
- 가파를 수록 Y/X가 커짐
- Feature의 비율이 중요한 경우
fig = plt.figure(figsize=(16, 7))
ax = fig.add_subplot(1, 1, 1, aspect=1)
ax.scatter(x, y, s=150,
c=['#1ABDE9' if yy/xx >= 1.0 else 'darkgray' for xx, yy in zip(x, y)],
linewidth=1.5,
edgecolor='black', zorder=10)
## Grid Part
radian = np.linspace(0, np.pi/2, 11, endpoint=True)
for rad in radian:
ax.plot([0,2], [0, 2*np.tan(rad)], linestyle='--', color='gray', alpha=0.5, linewidth=1)
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 1.1)
ax.set_title(r"Grid ($y=cx$)", fontsize=15,va= 'center', fontweight='semibold')
plt.tight_layout()
plt.show()
🟨 두 변수의 곱이 중요하다면 (xy = c)
🟨 특정 데이터를 중심으로 보고 싶다면 ( (x-x')^2 + (y-y')^2 = c )
- 동심원을 사용
- 특정 지점에서 거리를 살펴볼 수 있음
- 가장 가까운 포인트를 찾거나, 한 데이터에서 특정 범위의 데이터
fig = plt.figure(figsize=(16, 7))
ax = fig.add_subplot(1, 1, 1, aspect=1)
ax.scatter(x, y, s=150,
c=['darkgray' if i!=2 else '#1ABDE9' for i in range(20)] ,
linewidth=1.5,
edgecolor='black', zorder=10)
## Grid Part
rs = np.linspace(0.1, 0.8, 8, endpoint=True)
for r in rs:
xx = r*np.cos(np.linspace(0, 2*np.pi, 100))
yy = r*np.sin(np.linspace(0, 2*np.pi, 100))
ax.plot(xx+x[2], yy+y[2], linestyle='--', color='gray', alpha=0.5, linewidth=1)
ax.text(x[2]+r*np.cos(np.pi/4), y[2]-r*np.sin(np.pi/4), f'{r:.1}', color='gray')
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 1.1)
ax.set_title(r"Grid ($(x-x')^2+(y-y')^2=c$)", fontsize=15,va= 'center', fontweight='semibold')
plt.tight_layout()
plt.show()
- 전형적이지 않고, 구현도 까다롭지만 numpy + matplotlib으로 쉽게 구현 가능
(다양한 예시: https://medium.com/nightingale/gotta-gridem-all-2f768048f934)
import pandas as pd
student = pd.read_csv('./StudentsPerformance.csv')
student.head()
- axvline() : 수직으로 선 그리기
- axhline() : 수평으로 선 그리기
fig, ax = plt.subplots()
ax.set_aspect(1)
ax.axvline(0, color='red')
ax.axhline(0, color='green')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
plt.show()
- ax의 전체 구간을 [0, 1]로 생각하여 특정 부분에만 선을 그릴 수 있다.
fig, ax = plt.subplots()
ax.set_aspect(1)
ax.axvline(0, ymin=0.3, ymax=0.7, color='red')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
plt.show()
fig, ax = plt.subplots(figsize=(10, 10))
ax.set_aspect(1)
math_mean = student['math score'].mean()
reading_mean = student['reading score'].mean()
ax.axvline(math_mean, color='gray', linestyle='--')
ax.axhline(reading_mean, color='gray', linestyle='--')
ax.scatter(x=student['math score'], y=student['reading score'],
alpha=0.5,
color=['royalblue' if m>math_mean and r>reading_mean else 'gray' for m, r in zip(student['math score'], student['reading score'])],
zorder=10,
)
ax.set_xlabel('Math')
ax.set_ylabel('Reading')
ax.set_xlim(-3, 103)
ax.set_ylim(-3, 103)
plt.show()
- axvspan : 수직으로 면 그리기
- axhspan : 수평으로 면 그리기
fig, ax = plt.subplots()
ax.set_aspect(1)
ax.axvspan(0,0.5, color='red')
ax.axhspan(0,0.5, color='green')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
plt.show()
- 선 그리는 것과 같이 특정 부분에만 면을 그릴 수 있다.
fig, ax = plt.subplots()
ax.set_aspect(1)
ax.axvspan(0,0.5, ymin=0.3, ymax=0.7, color='red')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
plt.show()
- 특정 부분을 강조할 수 있지만, 오히려 특정 부분의 주의를 없앨 수도 있다.
fig, ax = plt.subplots(figsize=(8, 8))
ax.set_aspect(1)
math_mean = student['math score'].mean()
reading_mean = student['reading score'].mean()
ax.axvspan(-3, math_mean, color='gray', linestyle='--', zorder=0, alpha=0.3)
ax.axhspan(-3, reading_mean, color='gray', linestyle='--', zorder=0, alpha=0.3)
ax.scatter(x=student['math score'], y=student['reading score'],
alpha=0.4, s=20,
color=['royalblue' if m>math_mean and r>reading_mean else 'gray' for m, r in zip(student['math score'], student['reading score'])],
zorder=10,
)
ax.set_xlabel('Math')
ax.set_ylabel('Reading')
ax.set_xlim(-3, 103)
ax.set_ylim(-3, 103)
plt.show()
- 대표적인 3가지
- set_visible : 보일지 말지를 설정
- set_linewidth : 테두리 두께 설정
- set_position : 테두리의 위치 설정
- 'center' -> ('axes', 0.5)
- 'zero' -> ('data', 0.0)
fig = plt.figure(figsize=(12, 6))
_ = fig.add_subplot(1,2,1)
ax = fig.add_subplot(1,2,2)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_linewidth(1.5)
ax.spines['bottom'].set_linewidth(1.5)
plt.show()
fig = plt.figure(figsize=(12, 6))
_ = fig.add_subplot(1,2,1)
ax = fig.add_subplot(1,2,2)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
plt.show()
fig = plt.figure(figsize=(12, 6))
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
for ax in [ax1, ax2]:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax1.spines['left'].set_position('center')
ax1.spines['bottom'].set_position('center')
ax2.spines['left'].set_position(('data', 0.3)) # 비율
ax2.spines['bottom'].set_position(('axes', 0.2)) # 비율
ax2.set_ylim(-1, 1)
plt.show()
fig = plt.figure(figsize=(12, 9))
ax = fig.add_subplot(aspect=1)
x = np.linspace(-np.pi, np.pi, 1000)
y = np.sin(x)
ax.plot(x, y)
ax.set_xlim(-np.pi, np.pi)
ax.set_ylim(-1.2, 1.2)
ax.set_xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
ax.set_xticklabels([r'$\pi$', r'-$-\frac{\pi}{2}$', r'$0$', r'$\frac{\pi}{2}$', r'$\pi$'],)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
plt.show()
- mpl을 rcParams로 커스터마이징하기
# 방법 1
plt.rcParams['lines.linewidth'] = 2
plt.rcParams['lines.linestyle'] = ':'
# plt.rcParams['figure.dpi'] = 150
# 방법 2
plt.rc('lines', linewidth=2, linestyle=':')
plt.plot([1, 2, 3])
plt.rcParams.update(plt.rcParamsDefault) # Default 값으로 되돌리기
- mpl의 스타일 Theme를 변경하기
- 대표적으로 많이 사용하는 테마는 fivethirtyeight, ggplot 이 있다. 없으면 default
print(mpl.style.available)
mpl.style.use('seaborn')
# mpl.style.use('./CUSTOM.mplstyle') # 커스텀을 사용하고 싶다면
plt.plot([1, 2, 3])
with plt.style.context('fivethirtyeight'):
plt.plot(np.sin(np.linspace(0, 2 * np.pi)))
plt.show()
plt.plot(np.sin(np.linspace(0, 2 * np.pi)))
'Data Analysis & Viz' 카테고리의 다른 글
[데이터시각화] Polar Coordinate - Polar, Radar Plot (0) | 2023.03.27 |
---|---|
[데이터시각화] Seaborn (0) | 2023.03.27 |
[데이터시각화] Facet (0) | 2023.03.22 |
[데이터시각화] Color (0) | 2023.03.22 |
[데이터시각화] Text (0) | 2023.03.22 |
Comments