[TS] ์‹œ๊ณ„์—ด ์ด์ƒํƒ์ง€ ์‹œ๊ฐํ™”

Posted by Euisuk's Dev Log on November 13, 2023

[TS] ์‹œ๊ณ„์—ด ์ด์ƒํƒ์ง€ ์‹œ๊ฐํ™”

์›๋ณธ ๊ฒŒ์‹œ๊ธ€: https://velog.io/@euisuk-chung/TS-์‹œ๊ณ„์—ด-์ด์ƒํƒ์ง€-์‹œ๊ฐํ™”

์˜ค๋Š˜์˜ ์ฝ”๋“œ

์‹œ๊ณ„์—ด ์ „๋ฌธ๊ฐ€๋กœ์„œ, ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ถ„์„๊ฐ€๋กœ์„œ ๋‹ค๋ณ€๋Ÿ‰ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๊ณ  ์ด๋ฅผ ์‚ดํŽด๋ณด๋Š” ์ž‘์—…์€ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด์— ์˜ค๋Š˜์€ ์ œ๊ฐ€ ์ฃผ๋กœ ์—ฐ๊ตฌ/์—…๋ฌด์— ์‚ฌ์šฉํ•˜๋Š” ์ด์ƒํƒ์ง€ ์‹œ๊ฐํ™” ์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np

def plot_mul_ad(df, df_w_result, model_name='IForest'):
    # Define a color palette with enough colors
    colors = plt.cm.viridis(np.linspace(0, 1, df.shape[1]))

    # Create a figure with GridSpec
    fig = plt.figure(figsize=(12, 2 * df.shape[1]))  # Adjust the figure size
    gs = gridspec.GridSpec(df.shape[1], 1, fig, 0, 0, 1, 1, hspace=0.5)

    for i, (col, color) in enumerate(zip(df.columns, colors)):
        ax = fig.add_subplot(gs[i, 0])

        ax.plot(df.index.values, df[col].values, label=col, color=color)

        # Mark anomalies with red dots
        anomalies = df[df_w_result[f'{model_name}'] == -1]
        ax.scatter(anomalies.index, anomalies[col], color='red', label='Anomaly', zorder=5)

        ax.set_ylabel(col)
        ax.legend()

    # Set common labels
    plt.xlabel('Time (Index)')
    plt.xticks(rotation=45)
    fig.suptitle('Feature Values Over Time With Anomalies (Unique Colors)', fontsize=16, y=1.05)

    plt.show()

์ฃผ์š”๊ธฐ๋Šฅ1. cm.viridis

matplotlib์—์„œ plt.cm.viridis(np.linspace(0, 1, df.shape[1])) ์ฝ”๋“œ๋Š” viridis ์ปฌ๋Ÿฌ๋งต์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„(df)์˜ ์—ด ์ˆ˜์— ๋”ฐ๋ผ ์ƒ‰์ƒ ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ๋ถ„ํ•ดํ•˜์—ฌ ๊ฐ ๋ถ€๋ถ„์˜ ์˜๋ฏธ๋ฅผ ์ดํ•ดํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. plt.cm.viridis

  • plt.cm์€ matplotlib.pyplot์˜ ์ปฌ๋Ÿฌ๋งต ๋ชจ๋“ˆ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ปฌ๋Ÿฌ๋งต์€ ์—ฐ์†์ ์ธ ์ƒ‰์ƒ์˜ ๋ฒ”์œ„๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๊ฐํ™”ํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • viridis๋Š” matplotlib์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ์ปฌ๋Ÿฌ๋งต ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ด ์ปฌ๋Ÿฌ๋งต์€ ๋ฐ์€ ๋…ธ๋ž€์ƒ‰์—์„œ ์‹œ์ž‘ํ•˜์—ฌ, ๋ฐ์€ ๋…น์ƒ‰์„ ๊ฑฐ์ณ ์–ด๋‘์šด ํŒŒ๋ž€์ƒ‰์œผ๋กœ ๋๋‚˜๋Š” ์ƒ‰์ƒ ๋ฒ”์œ„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • viridis ์ปฌ๋Ÿฌ๋งต์€ ๋†’์€ ๊ฐ€๋…์„ฑ๊ณผ ์ƒ‰๋งน ์ ‘๊ทผ์„ฑ์„ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉฐ, ๋ฐ์ดํ„ฐ์˜ ์„ธ๋ฐ€ํ•œ ๋ถ€๋ถ„๊นŒ์ง€ ๊ตฌ๋ณ„ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

2. np.linspace(0, 1, df.shape[1])

  • np.linspace๋Š” NumPy ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ•จ์ˆ˜๋กœ, ์ง€์ •๋œ ๋ฒ”์œ„ ๋‚ด์—์„œ ๊ท ๋“ฑํ•œ ๊ฐ„๊ฒฉ์˜ ์ˆซ์ž๋“ค์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ๊ฒฝ์šฐ np.linspace(0, 1, df.shape[1])๋Š” 0๊ณผ 1 ์‚ฌ์ด์˜ ๊ฐ’์„ df.shape[1] (๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„์˜ ์—ด ์ˆ˜)๋งŒํผ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„ํ• ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ์—ด์— ๋Œ€ํ•ด ๊ณ ์œ ํ•œ ์ƒ‰์ƒ์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์˜ ๋ฐฐ์—ด์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๊ฒฐํ•ฉ๋œ ์‚ฌ์šฉ

์ด ์ฝ”๋“œ์˜ ๊ฒฐํ•ฉ๋œ ์‚ฌ์šฉ์€ ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„์˜ ๊ฐ ์—ด์— ๋Œ€ํ•ด ๊ณ ์œ ํ•˜๊ณ  ๊ตฌ๋ณ„ ๊ฐ€๋Šฅํ•œ ์ƒ‰์ƒ์„ ํ• ๋‹นํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. viridis ์ปฌ๋Ÿฌ๋งต์— np.linspace๋ฅผ ์ ์šฉํ•จ์œผ๋กœ์จ, ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„์˜ ๊ฐ ์—ด์— ํ•ด๋‹นํ•˜๋Š” ๊ณ ์œ ํ•œ ์ƒ‰์ƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์‹œ๊ฐํ™”ํ•  ๋•Œ ์œ ์šฉํ•˜๋ฉฐ, ๊ฐ ์—ด์ด๋‚˜ ๋ฐ์ดํ„ฐ ์‹œ๋ฆฌ์ฆˆ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

์ฃผ์š”๊ธฐ๋Šฅ2. GridSpec

GridSpec์€ matplotlib์—์„œ ๊ณ ๊ธ‰ ๊ทธ๋ฆฌ๋“œ ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ๋ณต์žกํ•œ ์ฐจํŠธ ๋ ˆ์ด์•„์›ƒ์„ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์ธ ์„œ๋ธŒํ”Œ๋กฏ ๋ ˆ์ด์•„์›ƒ๋ณด๋‹ค ๋” ๋งŽ์€ ์œ ์—ฐ์„ฑ๊ณผ ์„ธ๋ฐ€ํ•œ ์ œ์–ด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

GridSpec์˜ ์ฃผ์š” ๊ธฐ๋Šฅ๊ณผ ํŠน์ง•

  1. ์„ธ๋ฐ€ํ•œ ๋ ˆ์ด์•„์›ƒ ์ œ์–ด: GridSpec์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฐ ์„œ๋ธŒํ”Œ๋กฏ์˜ ํฌ๊ธฐ์™€ ์œ„์น˜๋ฅผ ํ–‰๊ณผ ์—ด ๋‹จ์œ„๋กœ ์ •ํ™•ํ•˜๊ฒŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ‘œ์ค€ subplots ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ์„ธ๋ฐ€ํ•œ ์ œ์–ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋น„๊ท ์ผ ์„œ๋ธŒํ”Œ๋กฏ ํฌ๊ธฐ: ์„œ๋ธŒํ”Œ๋กฏ๋“ค์ด ๋ชจ๋‘ ๋™์ผํ•œ ํฌ๊ธฐ๋ฅผ ๊ฐ€์งˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•œ ํ–‰์— ํฐ ์„œ๋ธŒํ”Œ๋กฏ ํ•˜๋‚˜์™€ ์ž‘์€ ์„œ๋ธŒํ”Œ๋กฏ ๋‘ ๊ฐœ๋ฅผ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด, ๋‹ค์–‘ํ•œ ํฌ๊ธฐ์™€ ๋น„์œจ์˜ ์„œ๋ธŒํ”Œ๋กฏ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ํ–‰๊ณผ ์—ด์˜ ์กฐ์ •: GridSpec์„ ์‚ฌ์šฉํ•˜๋ฉด, ํ–‰๊ณผ ์—ด์˜ ์ˆ˜, ์„œ๋ธŒํ”Œ๋กฏ ๊ฐ„์˜ ๊ฐ„๊ฒฉ(hspace, wspace), ๊ทธ๋ฆฌ๊ณ  ํ”Œ๋กฏ์˜ ์ƒ๋Œ€์ ์ธ ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GridSpec ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

GridSpec์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค:

  1. GridSpec ๊ฐ์ฒด ์ƒ์„ฑ: ๋จผ์ € matplotlib.gridspec.GridSpec ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ํ–‰๊ณผ ์—ด์˜ ์ˆ˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

    1
    2
    
    import matplotlib.gridspec as gridspec
    gs = gridspec.GridSpec(nrows, ncols)
    
  2. Figure ๊ฐ์ฒด ์ƒ์„ฑ: matplotlib์˜ figure ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด๋Š” ๋ชจ๋“  ์„œ๋ธŒํ”Œ๋กฏ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

    1
    
    fig = plt.figure()
    
  3. ์„œ๋ธŒํ”Œ๋กฏ ์ถ”๊ฐ€: fig.add_subplot์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ์„œ๋ธŒํ”Œ๋กฏ์„ GridSpec์— ๋”ฐ๋ผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์„œ๋ธŒํ”Œ๋กฏ์˜ ์œ„์น˜๋Š” GridSpec ๊ฐ์ฒด์˜ ์Šฌ๋ผ์ด์‹ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

    1
    2
    
    ax1 = fig.add_subplot(gs[0, 0]) # ์ฒซ ๋ฒˆ์งธ ํ–‰, ์ฒซ ๋ฒˆ์งธ ์—ด
    ax2 = fig.add_subplot(gs[1, :]) # ๋‘ ๋ฒˆ์งธ ํ–‰, ๋ชจ๋“  ์—ด
    
  4. ์„œ๋ธŒํ”Œ๋กฏ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•: ์ด์ œ ๊ฐ ์„œ๋ธŒํ”Œ๋กฏ(ax1, ax2, โ€ฆ)์— ๋Œ€ํ•ด ํ•„์š”ํ•œ ๊ทธ๋ž˜ํ”ฝ ์ž‘์—…(ํ”Œ๋กฏ, ๋ ˆ์ด๋ธ” ์ถ”๊ฐ€ ๋“ฑ)์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  5. ๋ Œ๋”๋ง ๋ฐ ํ‘œ์‹œ: ๋งˆ์ง€๋ง‰์œผ๋กœ plt.show()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์™„์„ฑ๋œ ๊ทธ๋ฆผ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

GridSpec์€ ๋ณต์žกํ•œ ๋ ˆ์ด์•„์›ƒ์„ ํ•„์š”๋กœ ํ•˜๋Š” ๊ณ ๊ธ‰ ๊ทธ๋ž˜ํ”ฝ ์ž‘์—…์— ๋งค์šฐ ์œ ์šฉํ•˜๋ฉฐ, matplotlib์˜ ๊ฐ•๋ ฅํ•œ ์‹œ๊ฐํ™” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ 

๐Ÿฅ ์ œ๋ชฉ์ด ๊ทธ๋ž˜ํ”„๋ฅผ ์นจ๋ฒ”ํ–ˆ๋‹ค๊ณ ์š”? ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ด๋ณด์„ธ์š”.

์ œ๋ชฉ์ด ๊ทธ๋ž˜ํ”„์— ์นจ๋ฒ”ํ•˜๋Š” ๋ฌธ์ œ๋Š” matplotlib์—์„œ ์ข…์ข… ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. suptitle์˜ y ๋งค๊ฐœ๋ณ€์ˆ˜ ์กฐ์ •: fig.suptitle ๋ฉ”์†Œ๋“œ์—๋Š” ์ „์ฒด ๊ทธ๋ฆผ ์ œ๋ชฉ์˜ ์œ„์น˜๋ฅผ ์กฐ์ •ํ•˜๋Š” y ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ฆ๊ฐ€์‹œ์ผœ ์ œ๋ชฉ์„ ๋†’์ด ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1
    
    fig.suptitle('Feature Values Over Time With Anomalies (Unique Colors)', fontsize=16, y=1.05)
    
  2. ์„œ๋ธŒํ”Œ๋กฏ๊ณผ์˜ ์—ฌ๋ฐฑ ์กฐ์ •: subplots_adjust ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ธŒํ”Œ๋กฏ๊ณผ์˜ ์ƒ๋‹จ ์—ฌ๋ฐฑ์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ œ๋ชฉ๊ณผ ์„œ๋ธŒํ”Œ๋กฏ ์‚ฌ์ด์˜ ๊ณต๊ฐ„์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1
    
    plt.subplots_adjust(top=0.85)
    
  3. tight_layout์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์กฐ์ •: tight_layout ๋ฉ”์†Œ๋“œ๋Š” ์„œ๋ธŒํ”Œ๋กฏ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์ž๋™์œผ๋กœ ์กฐ์ •ํ•˜์ง€๋งŒ, ๋•Œ๋•Œ๋กœ ์ด๋กœ ์ธํ•ด ์ œ๋ชฉ์ด ์„œ๋ธŒํ”Œ๋กฏ๊ณผ ๊ฒน์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. pad ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์กฐ์ •ํ•˜์—ฌ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1
    
    plt.tight_layout(pad=3)
    
  4. Figure ํฌ๊ธฐ ์กฐ์ •: Figure์˜ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ ค์„œ ์„œ๋ธŒํ”Œ๋กฏ๊ณผ ์ œ๋ชฉ ๊ฐ„์˜ ๊ณต๊ฐ„์„ ํ™•๋ณดํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” figure ํ•จ์ˆ˜์—์„œ figsize ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์กฐ์ •ํ•จ์œผ๋กœ์จ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

    1
    
    fig = plt.figure(figsize=(12, 24))  # ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ์ ์ ˆํžˆ ์กฐ์ •
    

์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•๋“ค์„ ์กฐํ•ฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด, ์ œ๋ชฉ์ด ๊ทธ๋ž˜ํ”„์— ์นจ๋ฒ”ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜ํ”„์˜ ๋ ˆ์ด์•„์›ƒ๊ณผ ์„œ๋ธŒํ”Œ๋กฏ์˜ ์ˆ˜์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•˜๊ณ  ์กฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.



-->