시계열 전문가로서, 시계열 데이터분석가로서 다변량 시계열 데이터를 시각화하고 이를 살펴보는 작업은 매우 중요합니다. 이에 오늘은 제가 주로 연구/업무에 사용하는 이상탐지 시각화 코드
를 정리하고자 합니다.
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()
matplotlib
에서 plt.cm.viridis(np.linspace(0, 1, df.shape[1]))
코드는 viridis
컬러맵을 사용하여 데이터 프레임(df)의 열 수에 따라 색상 배열을 생성하는 방법입니다. 이 코드를 분해하여 각 부분의 의미를 이해해 보겠습니다.
plt.cm.viridis
plt.cm
은 matplotlib.pyplot
의 컬러맵 모듈을 의미합니다. 컬러맵은 연속적인 색상의 범위를 제공하며, 다양한 데이터를 시각화할 때 유용하게 사용됩니다.viridis
는 matplotlib
에서 제공하는 기본 컬러맵 중 하나입니다. 이 컬러맵은 밝은 노란색에서 시작하여, 밝은 녹색을 거쳐 어두운 파란색으로 끝나는 색상 범위를 가집니다.viridis
컬러맵은 높은 가독성과 색맹 접근성을 위해 설계되었으며, 데이터의 세밀한 부분까지 구별하기 쉽게 만들어져 있습니다.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
를 적용함으로써, 데이터 프레임의 각 열에 해당하는 고유한 색상을 얻을 수 있습니다. 이는 복잡한 데이터 세트를 시각화할 때 유용하며, 각 열이나 데이터 시리즈를 쉽게 구별할 수 있도록 도와줍니다.
GridSpec
은 matplotlib
에서 고급 그리드 레이아웃을 만드는 데 사용되는 클래스입니다. 이 클래스는 복잡한 차트 레이아웃을 생성하고 관리하는 데 유용하며, 일반적인 서브플롯 레이아웃보다 더 많은 유연성과 세밀한 제어를 제공합니다.
세밀한 레이아웃 제어: GridSpec
을 사용하면, 각 서브플롯의 크기와 위치를 행과 열 단위로 정확하게 지정할 수 있습니다. 이는 표준 subplots
함수를 사용하는 것보다 더 세밀한 제어를 가능하게 합니다.
비균일 서브플롯 크기: 서브플롯들이 모두 동일한 크기를 가질 필요가 없습니다. 예를 들어, 한 행에 큰 서브플롯 하나와 작은 서브플롯 두 개를 배치하는 것과 같이, 다양한 크기와 비율의 서브플롯을 생성할 수 있습니다.
행과 열의 조정: GridSpec
을 사용하면, 행과 열의 수, 서브플롯 간의 간격(hspace, wspace), 그리고 플롯의 상대적인 너비와 높이를 조정할 수 있습니다.
GridSpec
은 일반적으로 다음과 같은 단계로 사용됩니다:
GridSpec 객체 생성: 먼저 matplotlib.gridspec.GridSpec
클래스로부터 객체를 생성합니다. 이 때 행과 열의 수를 지정합니다.
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(nrows, ncols)
Figure 객체 생성: matplotlib
의 figure
객체를 생성합니다. 이 객체는 모든 서브플롯을 포함합니다.
fig = plt.figure()
서브플롯 추가: fig.add_subplot
을 사용하여 각 서브플롯을 GridSpec
에 따라 추가합니다. 여기서 서브플롯의 위치는 GridSpec
객체의 슬라이싱을 사용하여 지정합니다.
ax1 = fig.add_subplot(gs[0, 0]) # 첫 번째 행, 첫 번째 열
ax2 = fig.add_subplot(gs[1, :]) # 두 번째 행, 모든 열
서브플롯 커스터마이징: 이제 각 서브플롯(ax1
, ax2
, ...)에 대해 필요한 그래픽 작업(플롯, 레이블 추가 등)을 진행합니다.
렌더링 및 표시: 마지막으로 plt.show()
를 호출하여 완성된 그림을 표시합니다.
GridSpec
은 복잡한 레이아웃을 필요로 하는 고급 그래픽 작업에 매우 유용하며, matplotlib
의 강력한 시각화 기능 중 하나입니다.
🍥 제목이 그래프를 침범했다고요? 다음과 같이 해보세요.
제목이 그래프에 침범하는 문제는 matplotlib
에서 종종 발생하는 문제입니다. 이 문제를 해결하기 위해 몇 가지 접근 방법을 사용할 수 있습니다:
suptitle
의 y
매개변수 조정: fig.suptitle
메소드에는 전체 그림 제목의 위치를 조정하는 y
매개변수가 있습니다. 이 매개변수의 값을 증가시켜 제목을 높이 배치할 수 있습니다.
fig.suptitle('Feature Values Over Time With Anomalies (Unique Colors)', fontsize=16, y=1.05)
서브플롯과의 여백 조정: subplots_adjust
메소드를 사용하여 서브플롯과의 상단 여백을 조정할 수 있습니다. 이를 통해 제목과 서브플롯 사이의 공간을 확보할 수 있습니다.
plt.subplots_adjust(top=0.85)
tight_layout
의 매개변수 조정: tight_layout
메소드는 서브플롯의 레이아웃을 자동으로 조정하지만, 때때로 이로 인해 제목이 서브플롯과 겹칠 수 있습니다. pad
매개변수를 조정하여 이 문제를 해결할 수 있습니다.
plt.tight_layout(pad=3)
Figure 크기 조정: Figure의 크기를 늘려서 서브플롯과 제목 간의 공간을 확보할 수도 있습니다. 이는 figure
함수에서 figsize
매개변수를 조정함으로써 가능합니다.
fig = plt.figure(figsize=(12, 24)) # 너비와 높이를 적절히 조정
이러한 방법들을 조합하여 사용하면, 제목이 그래프에 침범하는 문제를 해결할 수 있습니다. 그래프의 레이아웃과 서브플롯의 수에 따라 적절한 방법을 선택하고 조정해야 합니다.