Python | データ処理:rolling

Python
スポンサーリンク

概要(rollingは「直近の一定区間で連続計算する」ための移動窓)

pandasのrollingは、直近N件や一定時間幅(例:過去7日など)のデータを“窓”として切り出し、その窓ごとに平均・合計・標準偏差などを計算します。移動平均・移動合計・移動標準偏差など、時系列の平滑化やトレンド把握に必須です。最重要ポイントは、window(窓の大きさ)、min_periods(最小必要データ数)、center(ラベル位置)、時間ベースの窓指定(”7D”など)です。


基本の使い方(固定幅N点の移動計算)

最小例(3点移動平均)

import pandas as pd

s = pd.Series([10, 12, 11, 13, 9])
ma3 = s.rolling(window=3).mean()
print(ma3)
# 0    NaN
# 1    NaN
# 2   11.0   # (10+12+11)/3
# 3   12.0   # (12+11+13)/3
# 4   11.0   # (11+13+9)/3
Python

直近3点の平均を、ひとつずつずらしながら計算します。最初の2点は窓が満たないためNaNになります。

min_periodsで“早めに値を出す”

ma3_min2 = s.rolling(window=3, min_periods=2).mean()
print(ma3_min2)
# 0    NaN
# 1   11.0   # (10+12)/2
# 2   11.0   # (10+12+11)/3
# 3   12.0
# 4   11.0
Python

min_periodsを2にすると、窓内の有効データが2以上あれば計算します。初期のNaNを減らしたいときに有効です。

centerで“出力位置”を中央へ

ma_center = s.rolling(window=3, center=True).mean()
print(ma_center)
# 窓の中心にラベルがつく(プロットの見え方が滑らかになる)
Python

デフォルトでは窓の末尾(右端)に値が付きます。center=Trueは見せ方重視のときに便利です。


時間ベースの窓(“過去7日”などの自然な指定)

日付インデックスで7日移動平均

import pandas as pd

idx = pd.date_range("2025-01-01", periods=7, freq="D")
s = pd.Series([100, 120, 80, 200, 150, 90, 110], index=idx)

ma7d = s.rolling("7D").mean()  # 過去7日間の平均(時間幅ベース)
print(ma7d)
Python

“7D”のような頻度文字列を使うと、“直近の期間”で窓が決まります。不等間隔の時系列でも自然な窓になります。

欠損と境界の扱い(min_periodsで制御)

ma7d_safe = s.rolling("7D", min_periods=3).mean()  # 3点以上あれば計算
Python

期間窓でも、最初の方はデータが少なくなりがち。min_periodsで安定させます。


よく使う集計と応用(mean・sum・std・max/min・apply・agg)

定番の移動統計

roll = s.rolling(window=3)
ma = roll.mean()   # 移動平均
su = roll.sum()    # 移動合計
sd = roll.std()    # 移動標準偏差(揺らぎ)
mx = roll.max()    # 移動最大
mn = roll.min()    # 移動最小
Python

トレンド把握(mean/sum)と変動評価(std)が基本セットです。

任意ロジックを適用(apply)

import numpy as np

# 窓内の中央値と上側外れ値を除く自作ロジック(例)
def robust_mean(x):
    med = np.median(x)
    keep = x[x <= med*1.5]
    return keep.mean()

rmean = s.rolling(5).apply(robust_mean, raw=True)
Python

applyで自作関数を窓ごとに適用できます。raw=Trueならndarrayが渡されて高速になりやすいです。

複数指標を一度に(agg)

out = s.rolling(5).agg(["mean", "std", "min", "max"])
print(out)
Python

同じ窓で複数の統計量をまとめて計算できます。


実践例(平滑化・異常検知・ボリンジャーバンド・時系列レポート)

売上の短期ノイズを平滑化

daily = pd.Series(
    [100, 120, 80, 200, 150, 90, 110, 130, 140],
    index=pd.date_range("2025-01-01", periods=9, freq="D")
)
smooth = daily.rolling("7D").mean()
Python

移動平均で“尖り”を抑え、傾向を見やすくします。期間窓は不等間隔でも扱いやすいです。

異常検知の下ごしらえ(移動平均からの乖離)

ma = daily.rolling(3).mean()
sd = daily.rolling(3).std()
zscore = (daily - ma) / sd
flag = (zscore.abs() >= 2)  # 2σ以上を異常候補に
Python

短期平均からの標準化乖離で“急激な変化”を素早く浮かせられます。

ボリンジャーバンド(トレンドと変動幅の同時表示)

ma20 = daily.rolling(20, min_periods=5).mean()
sd20 = daily.rolling(20, min_periods=5).std()
upper = ma20 + 2*sd20
lower = ma20 - 2*sd20
Python

移動平均+標準偏差で、トレンド線と“通常変動の範囲”を作れます。

日次レポートの安定化(中心ラベルで見やすく)

weekly_ma = daily.rolling("7D", center=True).mean()
Python

center=Trueでグラフの視覚的ズレを減らし、レポートの説得力を上げます。


重要ポイントの深掘り(窓の意味・NaNの扱い・前処理順・性能)

窓の意味を“現場言葉”で決める

  • 「直近N点の平均」か「過去N日間の平均」かで、window指定が変わります。固定幅(整数)と期間幅(”7D”など)を混同しないこと。

NaNは“窓が満たない/欠損が混じる”合図

  • 最初の方のNaNは窓不足、途中のNaNは欠損混入が原因です。min_periodsで“早めに出す”、fillnaで事前補完、どちらの戦略を取るか決めておきましょう。

時系列の前処理順

  • to_datetimeで日時型へ → sort_valuesで時系列順へ固定 → 必要なら重複・欠損処理 → rollingで移動計算。この順を守ると境界や窓の挙動が安定します。

性能と可読性

  • 可能なら標準関数(mean/sum/std)を使うのが速くて安定。applyは柔軟ですが遅くなりやすいので、最小限に。raw=Trueでndarray受け取りにすると多少速くなります。

まとめ(window・min_periods・center・期間窓を“意図通り”に設計する)

rollingは、データの直近区間を切り出して連続的に統計を計算するための中核です。固定幅ならwindow=N、期間幅なら”7D”のように自然な窓を指定し、min_periodsで初期NaNを制御、centerで表示の見え方を整える。mean/sum/stdなどの定番指標で平滑化や変動把握を行い、必要ならapply/aggで拡張。前処理順とNaNの意味を理解しておけば、初心者でも“滑らかで解像度の高い”時系列分析を自信を持って書けます。

タイトルとURLをコピーしました