Pandas - EWM 지수 가중 함수

Soogyung Gwon·2026년 2월 2일

구름을잡아라

목록 보기
10/60

EWM (Exponentially Weighted Mean)

= 최근 데이터에 지수적으로 더 큰 가중치를 주는 이동 평균

👉 흔히 말하는 EMA (Exponential Moving Average)

기본 재귀식

𝛼
α : 평활 계수 (0 < α ≤ 1)

📌 α가 클수록

최신 값에 더 민감
반응 빠름

📌 α가 작을수록

과거를 더 오래 기억
부드러움

α 값을 pandas에서는 보통 span으로 조절

예:

span = 10 → α ≈ 0.18
span = 20 → α ≈ 0.095

👉 span이 클수록 더 느리고 부드러움

https://www.kaggle.com/datasets/kannanaikkal/food-demand-forecasting

Kaggle 데이터 실습

데이터 셋 선별:
솔직히 도대체 이것을 가지고 무엇을 하는 것인지 잘 모르겠어서 한참 헤매다가, GPT에게 지수가중함수를 이용하면 어떤 것을 할 수 있냐고 물어본 결과, 겨우 추정치를 내는 데 사용할 수 있다는 것을 이해하고 시계열데이터 중 하나를 골랐다.

그런데 아직 데이터를 정렬하고 정제하는 방법을 잘 몰라서 한참을 또 헤매다가, 결국은 GPT/Gemini 선생님에게 다시 물어봐서 해 보았다. 솔직히 제대로 되었는지도 잘 모르겠고, 다시 한번 실습을 해보고 싶다는 생각이 들었다.

import pandas as pd
import matplotlib.pyplot as plt

# 1. 데이터 로드 (경로는 본인의 환경에 맞게 수정하세요)
try:
    df = pd.read_csv('./data/train.csv')
except FileNotFoundError:
    print("파일을 찾을 수 없습니다. 경로를 확인해주세요.")
    # 예시용 더미 데이터 생성을 원하시면 말씀해주세요.

# 2. 데이터 정렬 및 EMA 계산
# center, meal, week 순으로 정렬해야 시간 순서대로 EMA가 계산됩니다.
df = df.sort_values(["center_id", "meal_id", "week"])

# EMA(지수 이동 평균) 계산: 4주 기준
df["ema_orders_4w"] = (
    df.groupby(["center_id", "meal_id"])["num_orders"]
      .transform(lambda x: x.ewm(span=4, adjust=False).mean())
)

# 3. 실제 데이터가 존재하는 샘플 자동 추출
valid_center = df['center_id'].iloc[0]
valid_meal = df['meal_id'].iloc[0]
sample = df[(df["center_id"] == valid_center) & (df["meal_id"] == valid_meal)].copy()

# 4. 다음 주 예측치 계산
last_row = sample.iloc[-1]
next_week = last_row["week"] + 1
next_pred = last_row["ema_orders_4w"]

print(f"--- 분석 결과 (Center: {valid_center}, Meal: {valid_meal}) ---")
print(f"마지막 주차: {last_row['week']}주")
print(f"다음 주({next_week}주) 예측 주문량: {next_pred:.2f}건")

# 5. 시각화 (기존 데이터 + 다음 주 예측 지점)
plt.figure(figsize=(12, 6))

# 실제 주문량 (연한 파란색 선과 점)
plt.plot(sample["week"], sample["num_orders"], label="Actual Orders", 
         color='steelblue', marker='o', alpha=0.4)

# 계산된 EMA (빨간색 실선)
plt.plot(sample["week"], sample["ema_orders_4w"], label="EMA 4-week (Trend)", 
         color='red', linewidth=2)

# 다음 주 예측 지점 (빨간색 점선 및 별표 점)
plt.plot([last_row["week"], next_week], [last_row["ema_orders_4w"], next_pred], 
         color='red', linestyle='--', linewidth=2)
plt.scatter(next_week, next_pred, color='darkred', marker='*', s=150, 
            label="Next Week Forecast", zorder=5)

# 그래프 꾸미기
plt.title(f"Food Demand Forecasting (Center {valid_center}, Meal {valid_meal})", fontsize=14)
plt.xlabel("Week", fontsize=12)
plt.ylabel("Number of Orders", fontsize=12)
plt.legend()
plt.grid(True, linestyle=':', alpha=0.6)

plt.show()
profile
오랜시간 망설였던 코딩을 다시 해보려고 노력하고 있는 사람

0개의 댓글