Skip to content

Pandas Rolling Window: Rolling, Expanding, and EWM

Updated on

移動平均やスムージングされたシグナルは時系列分析の中核ですが、多くのチームはウィンドウの位置合わせ、欠損値、そして遅い Python ループに悩まされています。

  • 問題: Rolling 統計量を手計算するとエラーが出やすく、timestamp とずれがちです。
  • 不満の種: ループや場当たり的な shift の組み合わせは off‑by‑one エラーや初期期間の穴、そして重いノートブックの原因になります。
  • 解決策: rollingexpandingewm を適切なウィンドウ定義(min_periods、時間ベースのウィンドウ、centeradjust など)と組み合わせて使い、正しく速いベクトル化された結果を得ましょう。

Want an AI agent that understands your pandas notebooks and rolling-window features?

RunCell is a JupyterLab AI agent that can read your code, analyze DataFrames, understand notebook context, debug errors, and even generate & execute code for you. It works directly inside JupyterLab—no switching windows or copy-pasting.

👉 Try RunCell: runcell.dev (opens in a new tab)


クイックリファレンス

Window typeBest forKey parameters
rolling移動平均、ボラティリティ、カスタムウィンドウ関数window=3(または "7D")、min_periodscenterwin_typeon
expanding開始時点からの累積統計量min_periods
ewm指数減衰スムージングや重み付きメトリクスspanalphahalflifeadjusttimes

サンプルデータ

import pandas as pd
 
dates = pd.date_range("2024-01-01", periods=8, freq="D")
sales = pd.DataFrame({"date": dates, "revenue": [10, 12, 9, 14, 15, 13, 11, 16]})
sales = sales.set_index("date")

Rolling Windows(固定幅・時間ベース)

固定サイズのウィンドウ

sales["rev_ma3"] = (
    sales["revenue"]
    .rolling(window=3, min_periods=2)
    .mean()
)
  • min_periods は結果を出し始めるタイミングを制御します。最初の行は最小カウントに達するまで NaN のままです。
  • center=True を指定すると統計量をウィンドウの中央に配置できます(プロット時に便利)。

Datetime index または on= 列に対する時間ベースのウィンドウ

sales_reset = sales.reset_index()
sales_reset["rev_7d_mean"] = (
    sales_reset.rolling("7D", on="date")["revenue"].mean()
)
  • 不規則サンプリングには期間文字列("7D""48H" など)を使います。pandas は固定件数ではなく、指定した lookback 期間内に入る行を自動で選びます。
  • ウィンドウの左右どちら側を含めるかを変えたい場合は、closed="left" または "right" を調整します。

カスタムウィンドウ関数

sales["rev_range"] = (
    sales["revenue"].rolling(4).apply(lambda x: x.max() - x.min(), raw=True)
)

raw=True を指定すると、apply 内で NumPy array を直接扱えるため高速になります。


Expanding Windows(累積)

sales["rev_cum_mean"] = sales["revenue"].expanding(min_periods=2).mean()
  • 各観測値が「それ以前のすべて」を見るべきとき(ランニング平均、累積比率など)には expanding を使います。
  • shift() と組み合わせて、最新値を過去平均と比較することもできます。

Exponential Weighted Windows

sales["rev_ewm_span4"] = sales["revenue"].ewm(span=4, adjust=False).mean()
  • adjust=False は、多くの分析ダッシュボードで使われる典型的なスムージングに近い再帰式を用います。
  • halflife は直感的な減衰表現を提供します: ewm(halflife=3) は 3 期間ごとに重みを半減させます。
  • 不規則な timestamp では、times="date"(または index に設定)を渡すことで、行数ではなく実際の時間差に基づいて重み付けできます。

ウィンドウの選び方(チートシート)

GoalRecommended methodNotes
短期ノイズの平滑化小さな windowcenter=True を指定した rolling数値列に対して動作。初期から値を見たいなら min_periods を 1 以上に
開始時からのランニング合計・平均expanding固定ウィンドウなし。累積する KPI に最適
古い観測値を減衰させるewm(span=...)大きい rolling window よりモメンタム系シグナルに向く
不規則な timestamprolling("7D", on="date") のような時間ベース rolling または ewm(..., times="date")サンプリングが密な日のバイアスを避けられる
特徴量生成rolling().agg(["mean","std","min","max"])複数集約で特徴量セットを手早く構築

パフォーマンスと正確性のポイント

  • 時間ベースのウィンドウを多用する場合は、datetime 列を datetime64[ns] にし、index に設定しておきます。
  • 速度のために、Python の apply よりも組み込み集約関数(meanstdsumcount)を優先しましょう。
  • 先見バイアスを避けるには、教師あり学習向け特徴量を作る際、rolling の前に shift() でターゲットを過去側にずらします。
  • 元データが不規則な場合は、resample と組み合わせて頻度を正規化してから rolling を行います。

rollingexpandingewm を使えば、ループなしでほとんどのスムージングや特徴量エンジニアリングをカバーできます。pandas-to-datetimepandas-resample と組み合わせて時間軸を整えれば、チャートやモデルにそのまま投入できる高速で信頼性の高いメトリクスを得られます。