[Data Viz] Line Plot

hyunsooo·2022년 10월 6일
0

기본 Line Plot

Line Plot이란?

  • Line Plot은 연속적으로 변화하는 값을 순서대로 점으로 나타내고 이를 선으로 연결한 그래프

  • 꺽은선 그래프, 선 그래프, line chart, line graph 등으로 불리움

  • 시간/순서에 대한 변화에 적합하여 추세를 살피기 위해 사용

    • 변화 뿐만 아니라 기울기 정보도 사용 가능
  • .plot()으로 사용할 수 있다.

Line Plot의 요소

  • 5개 이하의 선을 사용하는 것을 추천

  • 이를 구별하는 요소는 아래와 같다.

    • 색상(color)
    • 마커(marker, markersize)
    • 선의 종류(linestyle, linewidth)

Line Plot을 위한 전처리

  • 시시각각 변하는 데이터는 Noise로 인해 패턴 및 추세 파악이 어려움

  • Noise의 인지적인 방해를 줄이기 위해 smoothing을 사용한다.


정확한 Line Plot

추세에 집중

  • Bar Plot과 다르게 꼭 축을 0에 초점을 둘 필요는 없음

    • 추세를 보기 위한 목적이므로
  • 너무 구체적인 line plot보다는 생략된 line plot이 더 나을 수 있다.

    • Grid, Annotate 제거
    • 디테일한 정보는 표로 제공하는 것을 추천
  • 생략되지 않는 선에서 범위를 조정하여 변화율 관찰(.set_ylim())

간격

  • 규칙적인 간격이 아니라면 오해를 줄 수 있음

    • 그래프 상에서 규칙적일 때 : 기울기 정보의 오해
    • 그래프 상에서 간격이 다를 때 : 없는 데이터를 있다고 오해

보간

  • Line은 점을 이어 만들기 때문에 점과 점 사이의 데이터가 없기에 이를 잇는 방법(보간)

  • 데이터의 error나 noise가 포함되어 있는 경우, 데이터의 이해를 돕는 방법

    • Moving Average

    • Smooth Curve with Scipy

      • scipy.interpolate.make_interp_spline()
      • scipy.interpolate.interp1d()
      • scipy.ndimage.gaussian_filter1d()
  • Presentation에는 좋은 방법이나 아래와 같은 오해를 일으킬 수 있다.

    • 없는 데이터를 있다고 착각
    • 작은 차이를 없앨 수 있음
    • 일반적인 분석에는 지양

이중 축 사용

  • 한 plot에 대해 2개의 축을 이중 축(dual axis)라고 한다.

  • 같은 시간 축에 대해 서로 다른 종류의 데이터를 표현하기 위하여

    • .twinx()
  • 한 데이터에 대해 다른 단위(ex. radian과 degree)
    - .secondary_xaxis(), .secondary_yaxis()

  • 2개의 plot을 그리는 것은 이중 축을 사용한다. 이중 축을 사용하는거보다 그래프를 2개 사용하는게 가독성이 좋은 경우가 많다.

ETC

  • 범례 대신 라인 끝 단에 레이블을 추가하면 식별에 도움이 된다.

  • min/max 정보는 추가해주면 도움이 될 수 있다.(annotation)

  • 연한색을 사용하여 uncertainty 표현(신뢰구간, 분산 등)


실습

기본 Line Plot

  • line plot은 기본적으로 왼쪽에서 오른쪽으로 그리는게 일반적이며 (x1,y1)(x_1, y_1)에서 (x2,y2)(x_2, y_2)의 점을 잇는 방식으로 그리게 된다.
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()
  • 수학적 테크닉을 사용하여 정N각형이나 원을 그릴 수 있다.
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(1, 1, 1)
x = np.sin(np.linspace(0, 2*np.pi, 4))
y = np.cos(np.linspace(0, 2*np.pi, 4))

ax.plot(x, y)
plt.show()
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, aspect=1)

n = 1000
x = np.sin(np.linspace(0, 2*np.pi, n))
y = np.cos(np.linspace(0, 2*np.pi, n))

ax.plot(x, y)

plt.show()

plot 변형하기

  • 기본
fig, ax = plt.subplots(1, 1, figsize=(5, 5))

np.random.seed(97)
x = np.arange(7)
y = np.random.rand(7)

ax.plot(x, y)

plt.show()

색, 마커, 선의 종류 변경

fig, ax = plt.subplots(1, 1, figsize=(5, 5))

np.random.seed(97)
x = np.arange(7)
y = np.random.rand(7)

ax.plot(x, y,
        color='black',
        marker='*',
        linestyle='solid', 
       )

plt.show()

line style

  • solid, dashed, dashdot, dotted, None

  • '--', -., -., :

  • 위의 2가지 방식으로 설정 가능


Line Plot을 위한 전처리

Data : New York Stock Exchange - prices.csv

  • Date 컬럼을 index로 설정하여 다룸(시간은 삭제하여 지정)

  • 편의를 위해 google, apple의 주식을 가지고 실습을 진행한다.

이동편균 사용

시시각각 변하는 데이이기 때문에 어떤 구간에 대해 평균으로 대체를 하는 방법

# window로 몇 개의 구간을 볼지 설정
google_rolling = google.rolling(window=4).mean()

# dpi: 해상도, sharex: x축 공유
fig, axes = plt.subplots(2, 1, figsize=(12, 7), dpi=300, sharex=True)

axes[0].plot(google.index,google['close'])
axes[1].plot(google_rolling.index,google_rolling['close'])

plt.show()

추세에 집중하는 방법

  • ax.xaxis.set_major_locator(MultipleLocator(1) : x축에 대한 정보

  • ax.yaxis.set_major_locator(MultipleLocator(0.5) : y축에 대한 정보

  • ax.grid(linewidth=0.3): grid 두께를 조정하여 line의 두께와 구별


보간

보간 정보


이중 축 사용

  • twinx() 사용하기 : 다른 정보를 다룰 때
fig, ax1 = plt.subplots(figsize=(12, 7), dpi=150)

# First Plot
color = 'royalblue'

ax1.plot(google.index, google['close'], color=color)
ax1.set_xlabel('date')
ax1.set_ylabel('close price', color=color)  
ax1.tick_params(axis='y', labelcolor=color)

# # Second Plot
ax2 = ax1.twinx()  
color = 'tomato'

ax2.plot(google.index, google['volume'], color=color)
ax2.set_ylabel('volume', color=color)  
ax2.tick_params(axis='y', labelcolor=color)

ax1.set_title('Google Close Price & Volume', loc='left', fontsize=15)
plt.show()
  • secondary-xaxis() 사용하기 : 같은 정보를 다룰 때
def deg2rad(x):
    return x * np.pi / 180

def rad2deg(x):
    return x * 180 / np.pi

fig, ax = plt.subplots()
x = np.arange(0, 360)
y = np.sin(2 * x * np.pi / 180)
ax.plot(x, y)
ax.set_xlabel('angle [degrees]')
ax.set_ylabel('signal')
ax.set_title('Sine wave')
secax = ax.secondary_xaxis('top', functions=(deg2rad, rad2deg))
secax.set_xlabel('angle [rad]')
plt.show()

ETC

  • 범례대신 라인 끝에 사용하기

fig = plt.figure(figsize=(12, 5))

x = np.linspace(0, 2*np.pi, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

# Ax2
ax = fig.add_subplot(111, aspect=1)
ax.plot(x, y1,
       color='#1ABDE9',
       linewidth=2,)

ax.plot(x, y2,
       color='#F36E8E',
       linewidth=2,)

ax.text(x[-1]+0.1, y1[-1], s='sin', fontweight='bold',
         va='center', ha='left', 
         bbox=dict(boxstyle='round,pad=0.3', fc='#1ABDE9', ec='black', alpha=0.3))

ax.text(x[-1]+0.1, y2[-1], s='cos', fontweight='bold',
         va='center', ha='left', 
         bbox=dict(boxstyle='round,pad=0.3', fc='#F36E8E', ec='black', alpha=0.3))


ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.show()
  • 강조 추가
fig = plt.figure(figsize=(7, 7))

np.random.seed(97)

x = np.arange(20)
y = np.random.rand(20)

ax = fig.add_subplot(111)
ax.plot(x, y,
       color='lightgray',
       linewidth=2,)

ax.set_xlim(-1, 21)

# max
ax.plot([-1, x[np.argmax(y)]], [np.max(y)]*2,
        linestyle='--', color='tomato'
       )

ax.scatter(x[np.argmax(y)], np.max(y), 
            c='tomato',s=50, zorder=20)

# min
ax.plot([-1, x[np.argmin(y)]], [np.min(y)]*2,
        linestyle='--', color='royalblue'
       )
ax.scatter(x[np.argmin(y)], np.min(y), 
            c='royalblue',s=50, zorder=20)

plt.show()
profile
지식 공유

0개의 댓글