[Pandas] rolling / expanding
Pandas rolling, Pandas expanding, 이동 평균, windowed pandas
정의
rolling(window): 고정 크기 슬라이딩 윈도우 (이동 평균 등)expanding(): 시작부터 누적 윈도우 (cumulative)ewm(alpha=): 지수 가중 이동 평균
시각화
rolling 기본
s.rolling(window=3).mean() # 3-point 이동 평균
s.rolling(window=7).sum() # 7일 합계 (시계열)
s.rolling(window=5).std()
s.rolling(window=10).max()
python
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8])
print(s.rolling(window=3).mean().tolist()) 결과
[nan, nan, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]| index | value | rolling(3).mean |
|---|---|---|
| 0 | 1 | NaN |
| 1 | 2 | NaN |
| 2 | 3 | 2.0 (1+2+3)/3 |
| 3 | 4 | 3.0 (2+3+4)/3 |
| 4 | 5 | 4.0 (3+4+5)/3 |
| 5 | 6 | 5.0 |
| 6 | 7 | 6.0 |
| 7 | 8 | 7.0 |
처음 N-1 개는 NaN (window 가 안 채워짐).
min_periods (최소 데이터 수)
s.rolling(window=3, min_periods=1).mean()
# [1.0, 1.5, 2.0, 3.0, 4.0, ...] ← 처음 2 개도 계산
time-based rolling (시계열)
# index 가 DatetimeIndex 일 때
df.rolling('7D').sum() # 지난 7일
df.rolling('30min').mean() # 지난 30분
데이터 빈도가 불규칙해도 시간 기반으로 정확히 윈도우 형성.
center=True
s.rolling(window=3, center=True).mean()
# 중심 정렬, [NaN, 2.0, 3.0, 4.0, ..., NaN]
기본은 right-aligned (윈도우의 마지막 위치에 결과). center=True 는 중앙.
expanding (누적)
s.expanding().mean() # 시작부터 현재까지 평균
s.expanding().sum() # 누적합 (== cumsum)
s.expanding(min_periods=5).mean()
ewm (지수 가중)
s.ewm(alpha=0.3).mean() # alpha 클수록 최근 가중
s.ewm(span=10).mean() # span = (2/alpha - 1)
s.ewm(halflife=5).mean()
최근 데이터에 더 큰 가중치, 이전 데이터는 점진적 감소. 금융 / 신호 처리.
groupby + rolling
df.groupby('user_id')['amount'].rolling(window=7).sum()
# 각 user 별 7-day 합계 (MultiIndex 결과)
자주 쓰는 패턴
7일 이동 평균 (smoothing)
df['ma7'] = df['sales'].rolling(7).mean()
누적 합 / 평균
df['cumulative_revenue'] = df['revenue'].expanding().sum()
df['running_avg'] = df['revenue'].expanding().mean()
Bollinger Bands
ma = s.rolling(20).mean()
std = s.rolling(20).std()
upper = ma + 2 * std
lower = ma - 2 * std
윈도우 안에서 사용자 함수
s.rolling(window=5).apply(lambda x: x.max() - x.min(), raw=True)
# raw=True 면 numpy array 가 전달되어 빠름
함정
1. window 가 너무 커서 NaN 만
short_series.rolling(window=100).mean()
# 데이터가 99 개라면 모두 NaN
min_periods=1 로 부분 결과.
2. shift 와 혼동
s.rolling(3).mean() # 현재 포함 3 개
s.shift(1).rolling(3).mean() # 이전 3 개 (오늘 제외)
미래 정보 누설 방지 (lookahead bias) 가 필요할 때 shift.
3. 성능
- 큰 데이터 + 작은 윈도우: 빠름
- 큰 데이터 + 큰 윈도우: 느림
numbaengine 사용:s.rolling(window=10).mean(engine='numba')(pandas 1.x+)
참고
이 글의 용어 (3개)
- [Pandas] DataFramepandas
- 정의 은 2차원 레이블 테이블. 각 열이 , 모든 열이 같은 (행 라벨) 를 공유. SQL 테이블 / Excel 시트 / R data.frame 의 Python 대응체. 생성 <…
- [Pandas] groupbypandas
- 정의 는 데이터를 그룹으로 나누고 (split), 각 그룹에 함수를 적용 (apply), 결과를 합쳐 (combine) 새 DataFrame 으로 만드는 split-apply-c…
- [Pandas] resamplepandas
- 정의 는 시계열 데이터를 다른 빈도 (월별, 일별, 시간별 등) 로 재샘플링하면서 집계한다. 의 시계열 버전. DatetimeIndex (또는 으로 datetime 컬럼) 이 필…
💬 댓글