= 최근 데이터에 지수적으로 더 큰 가중치를 주는 이동 평균
👉 흔히 말하는 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
데이터 셋 선별:
솔직히 도대체 이것을 가지고 무엇을 하는 것인지 잘 모르겠어서 한참 헤매다가, 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()