데이터를 불러오고 그 데이터로 학습을 수행하는 것만큼이나 데이터의 시각화도 중요하다. 시각화가 잘 이루어져야 그 데이터에서 insight를 얻기가 쉬워진다.
당연하게도 데이터 시각화는 데이터에서 출발한다. 데이터가 무엇인지, 데이터의 종류에는 무엇이 있는지를 알아야 한다.
데이터 종류에는 다음과 같은 것들이 있다.
파이썬에는 시각화를 위한 라이브러리인 matplotlib가 존재한다.
시각화를 위해 대개 다음 네줄의 코드로 시작하곤 한다.
import numpy as np
import pandas as pd
import matplotlib as mpl
import matploblib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
figure()
는 큰 틀을 만든다. 시각화의 준비 단계라고 볼 수 있다.
fig.add_subplot(111)
로 subplot을 만들 수 있다.
111은 세로 방향으로 1개, 가로 방향으로 1개의 subplot을 만들어 그 중 첫번째 subplot을 ax에 할당하겠다는 의미이다.
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
위와 같은 코드는 2x2 행렬의 각 원소 위치에 subplot을 각각 만들고 axn에 n번째 subplot을 배정하겠다는 말과 같다.
만약 하나의 subplot에 두가지 데이터를 같이 표현하고 싶다면?
fig = plt.figure()
ax = fig.add_subplot(111)
x1 = [1,2,3,4,5]
x2 = [5,4,3,2,1]
plt.plot(x1)
plt.plot(x2)
plt.show()
이런 방식도 가능하다.
fig, ax = plt.subplots(1,1)
ax.plot(x1)
ax.plot(x2)
plt.show()
(subplots
에 주의! 뒤에 s가 붙는다. add_subplot
과 비교)
만약 여러개의 subplot에 나눠서 시각화하고 싶다면?
fig, axes = plt.subplots(1,2)
axes[0].plot(x1)
axes[1].plot(x2)
plt.show()
(plt.subplots(1,2)
의 output값을 찍어보면 위처럼 나온다.)
막대 모양의 차트를 본 적이 있을 것이다. .bar()
는 데이터를 그러한 방식으로 시각화할 수 있다.
(.bar()
는 인덱스가 x축, 해당 인덱스에 대한 값이 y축에 표현된다. 인덱스를 y축에 표현하는 수평적 시각화를 원한다면 .barh()
를 사용하면 된다,)
해당 함수는 파라미터로 x축 값들, y축 값들을 기본적으로 받고 color
, width
, label
등을 받는다.
이 부분에서는 pandas
에서의 데이터 전처리 테크닉과 둘 이상의 데이터를 하나의 subplot에 표현하는 기법이 중요했다.
하나의 플롯에 동시에 서로 다른 데이터들을 나타내는 방법에는 다음과 같은 것들이 존재한다.
2개 이상의 그룹을 쌓아서 표현. 하나의 데이터를 시각화하는 막대 위에 다른 데이터 막대가 쌓인다.
.bar()
: bottom
파라미터로 아래에 쌓일 데이터를 표시.barh()
: left
파라미터로 왼쪽에 쌓일 데이터를 표시fig, ax = plt.subplots(1,1)
idx = [i for i in range(5)]
x1 = [1,8,3,2,5]
x2 = [5,7,3,2,2]
ax.bar(idx, x1)
ax.bar(idx, x2, bottom=x1)
ax.set_ylim(0,17) # y축에 표현되는 값 0부터 17
plt.show()
이를 응용하고 .text()
, .spine[ ].set_visible()
등의 함수들을 이용하면 다음처럼 percentage stacked bar plot을 구현할 수 있다.
겹쳐서 만들 수도 있다. alpha
라는 투명도를 나타내는 파라미터를 이용한다.
fig, axes = plt.subplots(1,2)
idx = [i for i in range(5)]
x1 = [1,8,3,2,5]
x2 = [5,7,3,2,2]
axes[0].bar(idx, x1, alpha=0.5)
axes[0].bar(idx, x2, alpha=0.5)
axes[1].bar(idx, x1, alpha=0.7)
axes[1].bar(idx, x2, alpha=0.7)
plt.show()
보통 0.5나 0.7을 사용한다고 한다. 물론 원하는대로 바꿀 수 있다.
막대를 이웃되게 배치할 수 있다. 개인적으로 가장 보기에 좋아보이는데 위의 두 방법보다는 구현이 살짝 더 까다롭다.
x축이 index, y축이 해당 index에 따른 값이라고 해보자. indices가 [0,1,2,3,4]라고 한다면 지금까지는 막대의 중심이 정확히 0,1,2,3,4에 있었다. 하지만 두개 이상의 데이터에 대해 해당 데이터를 표현하는 막대들이 이웃하게 시각화하려면 막대의 중심을 이동시키고, 막대가 겹치지 않게 width를 조정하는 작업이 필요하다. 이와 관련해서는 다음과 같은 규칙을 생각해볼 수 있다.
이를 이용하여 코드를 짜면 다음과 같다.
width를 적당한 값으로 설정해야 한다. (강의 자료를 보다보니)N개의 데이터를 이웃한 막대로 동시에 표현하고자 한다면 N\*width
가 대략 0.7
정도 되게 값을 설정하는 것 같다.
fig, ax = plt.subplots(1,1)
x1 = np.random.rand(8)
x2 = np.random.rand(8)
x3 = np.random.rand(8)
x4 = np.random.rand(8)
x_idx=np.arange(8)
width = 0.15
x_values = [x1, x2, x3, x4]
for i in range(4):
ax.bar(x_idx+(-4+1+2*i)*width/2, x_values[i],
width=width,
label=f'x{i+1}')
ax.legend() # 정해놓은 label들을 범례로 보여줌.
plt.show()
line plot은 대개 데이터를 점으로 찍은 후 순서대로 선으로 연결한 그래프 형태의 시각화 방법이다.
시간/순서에 대한 변화에 적합하여 trend를 살피기 좋다. 때문에 시계열 분석에 특화되어 있다.
.plot()
으로 구현한다.
순서대로 데이터를 연결하기 때문에 데이터 순서에 따라 아래와 같은 형태를 보이기도 한다.
fig, axes = plt.subplots(1,2, figsize=(12,7))
x1 = [1,2,3,4,5]
x2 = [1,3,2,4,5]
y = [1,3,2,1,5]
axes[0].plot(x1, y)
axes[1].plot(x2,y)
plt.show()
A_rolling = A.rolling(window=~).mean()
와 같은 방식으로 n-(*window*-1)번째 데이터
부터 n번째 데이터
까지 window 개수만큼의 데이터들의 평균값으로 그래프를 그린다. 그래프는 noise가 좀더 감소한 형태를 띄게 된다. trend 등에 집중하기 좋다.
.twinx()
.secondary_xaxis()
, .secondary_yaxis()
점으로 데이터를 표현한다. 관계를 파악하기에 좋다.
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111, aspect=1) # aspect는 각 축의 scale을 맞춤. 1이면 1:1을 의미.
x = np.random.rand(20)
y = np.random.rand(20)
ax.scatter(x,y)
plt.show()
scatter
의 파라미터로는 다음과 같은 것들이 존재한다.
ax1.scatter(x,y,
s=s, # s = np.arange(~)
c='white',
marker='^',
linewidth=1,
edgecolor='black') # s: size, c:color
s는 각 점의 size인데 위처럼 순차적으로 사이즈를 적용할 수도 있다.
.bar()
, .plot()
등에서 파라미터로 c는 안되고 color만 됐던걸로 기억하는데 scatter는 c도 사용할 수 있다.
ax.scatter(x=iris['SepalLengthCm'],
y = iris['SepalWidthCm'],
c = ['blue' if yy <= swc_mean else 'gray' for yy in iris['SepalWidthCm']])
이런 식으로 color parameter에 조건을 달 수도 있다. 그러면 다음과 같은 이미지를 얻을 수 있다.
앞서 배운 방식들을 응용하면 여러 데이터를 동시에 표현하는 것도 가능하다.