본문으로 건너뛰기
김신건의 로그

[Pandas] expanding / ewm

· 수정 · 📖 약 2분 · 626자/단어 #python #pandas #expanding #ewm #window #time-series
Pandas expanding, Pandas ewm, 지수가중이동평균

정의

Pandas rolling 외의 윈도우 연산.

  • expanding() : 시작부터 현재까지 누적 윈도우
  • ewm() : exponentially weighted (지수 가중)

윈도우 개념 비교

flowchart TD
    D["시계열 데이터"]
    D -->|"고정 n 개만"| R["rolling(n)<br/>균등 가중, 슬라이딩"]
    D -->|"시작 → 현재 전체"| E["expanding()<br/>누적 성장, 균등 가중"]
    D -->|"전체, 지수 감쇠"| W["ewm(span=n)<br/>최근 값 강조"]
항목rolling(n)expanding()ewm(span=n)
윈도우 크기고정 n1 → 무한사실상 무한
가중치균등균등지수 감쇠
초기 NaNn-1 개0 개 (min_periods=1)0 개
노이즈 민감도중간낮음낮음 (최근 강조)

expanding

s.expanding().mean()           # 시작부터 현재까지 평균
s.expanding().sum()            # = cumsum
s.expanding(min_periods=5).std()
python
import pandas as pd
s = pd.Series([10, 20, 30, 40, 50])
print('mean:', s.expanding().mean().tolist())
print('std :', s.expanding().std().round(2).tolist())
결과
mean: [10.0, 15.0, 20.0, 25.0, 30.0]
std : [nan, 7.07, 10.0, 12.91, 15.81]
indexsexpanding mean
01010
12015
23020
34025
45030

rolling 과 달리 윈도우 크기가 무한히 커진다.

ewm, 지수 가중

s.ewm(alpha=0.3).mean()
s.ewm(span=10).mean()
s.ewm(halflife=5).mean()
s.ewm(com=4).mean()
파라미터의미
alpha직접 가중치 (0 < α ≤ 1)
span평균적 윈도우 크기 (α = 2/(span+1))
halflife가중치가 절반이 되는 거리
comcenter of mass (α = 1/(1+com))

alpha 가 클수록 최근 값에 가중.

python
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8])
print('span=3 ewm:', s.ewm(span=3).mean().round(2).tolist())
print('span=7 ewm:', s.ewm(span=7).mean().round(2).tolist())
결과
span=3 ewm: [1.0, 1.67, 2.43, 3.27, 4.17, 5.12, 6.09, 7.06]
span=7 ewm: [1.0, 1.57, 2.18, 2.81, 3.45, 4.11, 4.78, 5.46]

span=3 이 작아서 최근 값에 더 빨리 반응, span=7 은 smoother.

ewm 의 수식

지수 감쇠 가중. 모든 과거 값을 고려하지만 가중치가 지수적으로 감소.

ewm 추가 파라미터

# min_periods: 최소 관측 수 (미만이면 NaN)
s.ewm(span=5, min_periods=3).mean()

# ignore_na: NaN 을 건너뛰고 가중치 계산
s.ewm(span=5, ignore_na=True).mean()

# times: 불균등 시간 간격 지원 (pandas 1.1+)
import numpy as np
times = pd.to_datetime(['2026-01-01', '2026-01-02', '2026-01-05', '2026-01-06'])
s2 = pd.Series([1.0, 2.0, 3.0, 4.0], index=times)
s2.ewm(halflife='1D', times=s2.index).mean()
파라미터기본값의미
min_periods0최소 관측 수 (미만 NaN)
ignore_naFalseNaN 위치 가중치 처리
adjustTrue초기 가중치 보정 여부
timesNone불균등 시간 간격 지원

TIP

시계열 데이터가 불규칙 간격 (주말 없음, 결측 등) 이면 times= + halflife='1D' 조합으로 실제 시간 기반 감쇠 적용.

ewm var / std / cov

# 분산, 표준편차
s.ewm(span=10).var()
s.ewm(span=10).std()

# 공분산, 상관계수
s1.ewm(span=10).cov(s2)
s1.ewm(span=10).corr(s2)

금융 리스크 모델 (GARCH 근사), 포트폴리오 변동성 추적에 활용.

rolling vs expanding vs ewm

항목윈도우가중치
rolling(n)고정 n같음
expanding()1 → ∞같음
ewm(span=n)사실상 무한지수 감쇠

자주 쓰는 패턴

누적 평균 / 표준편차

df['avg_so_far'] = df['x'].expanding().mean()
df['std_so_far'] = df['x'].expanding().std()

ML 의 online 통계, 게임 점수 누적 평균 등.

지수 이동 평균 (EMA)

df['ema_short'] = df['close'].ewm(span=12, adjust=False).mean()
df['ema_long'] = df['close'].ewm(span=26, adjust=False).mean()
df['macd'] = df['ema_short'] - df['ema_long']

금융 지표 MACD.

Bollinger Bands

ma = df['close'].rolling(20).mean()
std = df['close'].rolling(20).std()
df['upper'] = ma + 2 * std
df['lower'] = ma - 2 * std

(rolling 기반)

시계열 smoothing

df['smoothed'] = df['signal'].ewm(span=10).mean()
# noise 줄이기

이상 탐지 (Z-score 기반)

# expanding 으로 누적 평균/표준편차 계산 후 Z-score
df['mean_so_far'] = df['value'].expanding().mean()
df['std_so_far']  = df['value'].expanding().std()
df['z_score']     = (df['value'] - df['mean_so_far']) / df['std_so_far']

# |z| > 3 이면 이상치
df['is_anomaly'] = df['z_score'].abs() > 3

온라인 이상 탐지: 과거 전체 분포를 기준으로 현재 값이 얼마나 벗어났는지 실시간 계산.

adjust 옵션

s.ewm(span=3, adjust=True).mean()    # 기본, 더 정확한 평균
s.ewm(span=3, adjust=False).mean()   # 재귀식 사용 (online 계산용)
  • adjust=True : 시작 부분의 가중치도 보정
  • adjust=False : 단순 재귀 (실시간 처리에 적합)

Rolling vs EWM 시각 비교

Rolling Mean vs EWM Mean (span=3)
EWM 이 최근 값 변화에 더 빠르게 반응한다.

함정

1. expanding 의 첫 N 개

s.expanding(min_periods=5).std()
# 처음 4 개는 NaN

표본 크기가 작으면 표준편차가 불안정.

2. ewm 의 가중치 합

adjust=False 면 초기 가중치 합이 1 미만, bias 발생 가능.

3. groupby 결합

df['ema'] = df.groupby('user')['x'].transform(
    lambda s: s.ewm(span=10).mean()
)

apply 보다 transform 권장 (원본 shape 유지).

4. ewm + NaN 혼재

# NaN 이 있으면 ignore_na=True 로 건너뜀
s_with_nan = pd.Series([1, None, 3, 4, 5])
s_with_nan.ewm(span=3, ignore_na=True).mean()

기본 ignore_na=False 는 NaN 위치에서 가중치를 0 으로 처리해 결과가 달라짐.

참고

이 글의 용어 (3개)
[Pandas] cumsum / cummax / cummin / cumprodpandas
정의 누적 (cumulative) 연산. 각 위치까지의 누적 결과를 반환, 결과 길이는 원본과 동일. | 함수 | 의미 | |:---|:---| | | 누적 합 | | | 누적 …
[Pandas] resamplepandas
정의 는 시계열 데이터를 다른 빈도 (월별, 일별, 시간별 등) 로 재샘플링하면서 집계한다. 의 시계열 버전. DatetimeIndex (또는 으로 datetime 컬럼) 이 필…
[Pandas] rolling / expandingpandas
정의 - : 고정 크기 슬라이딩 윈도우 (이동 평균 등) - : 시작부터 누적 윈도우 (cumulative) - : 지수 가중 이동 평균 사용 상황 | 상황 | 적합한 방법 | …

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기