Skip to Content

시계열 차트

중급

학습 목표

이 레시피를 완료하면 다음을 할 수 있습니다:

  • 기본 라인 차트 생성
  • 다중 시계열 비교
  • 이동 평균과 트렌드 표시
  • Plotly로 인터랙티브 차트 만들기

0. 사전 준비 (Setup)

데이터 실습을 위해 CSV 파일을 로드합니다.

import pandas as pd import matplotlib.pyplot as plt # Load Data orders = pd.read_csv('src_orders.csv', parse_dates=['created_at']) items = pd.read_csv('src_order_items.csv') products = pd.read_csv('src_products.csv') # Merge for Analysis df = orders.merge(items, on='order_id').merge(products, on='product_id') # Ensure datetime conversion df['created_at'] = pd.to_datetime(df['created_at'], format='mixed')

1. 기본 라인 차트

Matplotlib 기본

import pandas as pd import matplotlib.pyplot as plt # 일별 매출 데이터 daily_sales = df.groupby(df['created_at'].dt.date)['sale_price'].sum() # 기본 라인 차트 plt.figure(figsize=(14, 6)) plt.plot(daily_sales.index, daily_sales.values, linewidth=2, color='steelblue') plt.title('Daily Sales Trend', fontsize=16, fontweight='bold') plt.xlabel('Date', fontsize=12) plt.ylabel('Sales ($)', fontsize=12) plt.grid(True, alpha=0.3) plt.xticks(rotation=45) plt.tight_layout() plt.show()

Basic Line Chart

2. 스타일링 옵션

선 스타일, 마커, 색상 등을 변경하여 가독성을 높일 수 있습니다.

plt.figure(figsize=(14, 6)) plt.plot(daily_sales.index, daily_sales.values, color='green', linestyle='--', marker='o', markersize=8, label='Daily Sales') plt.title('Daily Sales Trend (Styled)', fontsize=16, fontweight='bold') plt.xlabel('Date', fontsize=12) plt.ylabel('Sales ($)', fontsize=12) plt.grid(True, alpha=0.3, linestyle='-.') plt.legend() plt.show()

Styled Line Chart

스타일링 옵션

plt.figure(figsize=(14, 6)) plt.plot( daily_sales.index, daily_sales.values, linewidth=2, color='steelblue', marker='o', # 마커 추가 markersize=4, markerfacecolor='white', markeredgewidth=1.5, label='Daily Sales' ) plt.fill_between( daily_sales.index, daily_sales.values, alpha=0.2, # 영역 채우기 color='steelblue' ) plt.title('Daily Sales Trend', fontsize=16, fontweight='bold') plt.xlabel('Date', fontsize=12) plt.ylabel('Sales ($)', fontsize=12) plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show()
실행 결과
[Graph Saved: generated_plot_38d08c04e4_0.png]

Graph


2. 다중 시계열 비교

여러 라인 겹치기

# 카테고리별 월별 매출 category_monthly = df.groupby([ df['created_at'].dt.to_period('M'), 'category' ])['sale_price'].sum().unstack() # 상위 5개 카테고리 top_5 = df.groupby('category')['sale_price'].sum().nlargest(5).index category_monthly = category_monthly[top_5] # 다중 라인 차트 plt.figure(figsize=(14, 6)) for col in category_monthly.columns: plt.plot( category_monthly.index.astype(str), category_monthly[col], marker='o', linewidth=2, markersize=5, label=col ) plt.title('카테고리별 월별 매출 추이 (Top 5)', fontsize=16, fontweight='bold') plt.xlabel('월', fontsize=12) plt.ylabel('매출 ($)', fontsize=12) plt.legend(title='카테고리', bbox_to_anchor=(1.02, 1), loc='upper left') plt.xticks(rotation=45) plt.grid(True, alpha=0.3) plt.tight_layout() plt.show()
실행 결과
[Graph Saved: generated_plot_7d30c61072_0.png]

Graph

서브플롯으로 분리

fig, axes = plt.subplots(2, 3, figsize=(16, 10), sharex=True) axes = axes.flatten() for i, col in enumerate(top_5): ax = axes[i] ax.plot(category_monthly.index.astype(str), category_monthly[col], marker='o', linewidth=2, color=f'C{i}') ax.set_title(col, fontsize=12, fontweight='bold') ax.grid(True, alpha=0.3) ax.tick_params(axis='x', rotation=45) # 빈 서브플롯 숨기기 for j in range(len(top_5), len(axes)): axes[j].set_visible(False) fig.suptitle('카테고리별 월별 매출 추이', fontsize=16, fontweight='bold') plt.tight_layout() plt.show()
실행 결과
[Graph Saved: generated_plot_ac6a666484_0.png]

Graph


3. 이동 평균과 트렌드

이동 평균 추가

# 일별 매출과 이동 평균 daily_sales = df.groupby(df['created_at'].dt.date)['sale_price'].sum() ma_7 = daily_sales.rolling(window=7).mean() ma_30 = daily_sales.rolling(window=30).mean() plt.figure(figsize=(14, 6)) # 원본 데이터 (옅게) plt.plot(daily_sales.index, daily_sales.values, alpha=0.3, color='gray', label='일별 매출') # 7일 이동평균 plt.plot(daily_sales.index, ma_7.values, linewidth=2, color='steelblue', label='7일 이동평균') # 30일 이동평균 plt.plot(daily_sales.index, ma_30.values, linewidth=2, color='coral', label='30일 이동평균') plt.title('일별 매출과 이동평균', fontsize=16, fontweight='bold') plt.xlabel('날짜', fontsize=12) plt.ylabel('매출 ($)', fontsize=12) plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show()
실행 결과
[Graph Saved: generated_plot_e2af8308d9_0.png]

Graph

트렌드 라인 (선형 회귀)

from scipy import stats import numpy as np # 선형 회귀 x = np.arange(len(daily_sales)) slope, intercept, r_value, p_value, std_err = stats.linregress(x, daily_sales.values) trend_line = slope * x + intercept plt.figure(figsize=(14, 6)) plt.plot(daily_sales.index, daily_sales.values, alpha=0.5, color='steelblue', label='일별 매출') plt.plot(daily_sales.index, trend_line, linewidth=2, color='red', linestyle='--', label=f'트렌드 (기울기: {slope:.2f})') plt.title('매출 트렌드 분석', fontsize=16, fontweight='bold') plt.xlabel('날짜', fontsize=12) plt.ylabel('매출 ($)', fontsize=12) plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() print(f"📈 일평균 성장: ${slope:.2f}") print(f"📊 R² = {r_value**2:.3f}")
실행 결과
[Graph Saved: generated_plot_5302302ced_0.png]
📈 일평균 성장: $5.25
📊 R² = 0.447

Graph


4. YoY/MoM 비교 차트

전년 동월 비교

# 월별 매출 monthly = df.groupby([ df['created_at'].dt.year.rename('year'), df['created_at'].dt.month.rename('month') ])['sale_price'].sum().reset_index() # 피벗 monthly_pivot = monthly.pivot(index='month', columns='year', values='sale_price') # 비교 차트 plt.figure(figsize=(12, 6)) for year in monthly_pivot.columns: plt.plot( monthly_pivot.index, monthly_pivot[year], marker='o', linewidth=2, label=f'{year}년' ) plt.title('연도별 월간 매출 비교', fontsize=16, fontweight='bold') plt.xlabel('월', fontsize=12) plt.ylabel('매출 ($)', fontsize=12) plt.xticks(range(1, 13), ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월']) plt.legend(title='연도') plt.grid(True, alpha=0.3) plt.tight_layout() plt.show()
실행 결과
[Graph Saved: generated_plot_a0e75c3b92_0.png]

Graph


5. Plotly 인터랙티브 차트

기본 라인 차트

import plotly.express as px # 월별 매출 monthly_sales = df.groupby(df['created_at'].dt.to_period('M'))['sale_price'].sum() monthly_df = pd.DataFrame({ 'month': monthly_sales.index.astype(str), 'sales': monthly_sales.values }) fig = px.line( monthly_df, x='month', y='sales', title='월별 매출 추이', markers=True ) fig.update_layout( xaxis_title='월', yaxis_title='매출 ($)', hovermode='x unified' ) fig.show()

다중 시계열 + 범위 선택기

import plotly.graph_objects as go fig = go.Figure() # 여러 카테고리 추가 for cat in top_5: cat_data = category_monthly[cat] fig.add_trace(go.Scatter( x=cat_data.index.astype(str), y=cat_data.values, mode='lines+markers', name=cat, hovertemplate='%{y:$,.0f}<extra></extra>' )) fig.update_layout( title='카테고리별 월별 매출 (인터랙티브)', xaxis_title='월', yaxis_title='매출 ($)', hovermode='x unified', legend_title='카테고리', # 범위 선택기 xaxis=dict( rangeselector=dict( buttons=list([ dict(count=3, label='3개월', step='month', stepmode='backward'), dict(count=6, label='6개월', step='month', stepmode='backward'), dict(step='all', label='전체') ]) ), rangeslider=dict(visible=True) ) ) fig.show()

퀴즈 1: 이동평균 분석

문제

일별 주문 건수에 대해:

  1. 7일 이동평균과 14일 이동평균 계산
  2. 원본 데이터는 옅게, 이동평균은 진하게 표시
  3. 골든크로스 (7일 MA > 14일 MA 전환점) 표시

정답 보기

# 일별 주문 건수 daily_orders = df.groupby(df['created_at'].dt.date).size() ma_7 = daily_orders.rolling(7).mean() ma_14 = daily_orders.rolling(14).mean() # 골든크로스 찾기 golden_cross = (ma_7 > ma_14) & (ma_7.shift(1) <= ma_14.shift(1)) cross_dates = daily_orders[golden_cross].index plt.figure(figsize=(14, 6)) # 원본 (옅게) plt.plot(daily_orders.index, daily_orders.values, alpha=0.2, color='gray', label='일별 주문') # 이동평균 plt.plot(daily_orders.index, ma_7.values, linewidth=2, color='steelblue', label='7일 MA') plt.plot(daily_orders.index, ma_14.values, linewidth=2, color='coral', label='14일 MA') # 골든크로스 표시 for date in cross_dates: plt.axvline(date, color='gold', linestyle='--', alpha=0.7) plt.annotate('Golden Cross', xy=(date, daily_orders[date]), xytext=(10, 20), textcoords='offset points', fontsize=8, color='gold') plt.title('일별 주문과 이동평균 (골든크로스 표시)', fontsize=16, fontweight='bold') plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show()
실행 결과
[Graph Saved: generated_plot_772a0ee4c3_0.png]

Graph


정리

plt.plot() 주요 파라미터

파라미터설명예시
linewidth선 두께2
linestyle선 스타일'-', '--', ':'
marker마커 종류'o', 's', '^'
color색상'steelblue', '#1f77b4'
alpha투명도0.5
label범례 라벨'매출'

시계열 차트 선택 가이드

상황추천 차트
단일 시계열기본 라인 차트
다중 비교겹친 라인 or 서브플롯
노이즈 제거이동평균 추가
트렌드 확인회귀선 추가
인터랙티브Plotly

다음 단계

시계열 차트를 마스터했습니다! 다음으로 분포 시각화에서 히스토그램, 박스플롯 등 분포 분석 차트를 배워보세요.

Last updated on

🤖AI 모의면접실전처럼 연습하기