Pandas & NumPy Academy · レッスン

ローリングウィンドウ

rolling(n).mean()などのメソッドを使い、固定された行数を対象に移動平均、移動合計、移動標準偏差を計算します。

レッスン 1/413 ステップ

「ローリングウィンドウ」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

ローリングウィンドウとは

ローリングウィンドウ(スライディングウィンドウまたは移動ウィンドウとも呼ばれます)は、連続する行からなる固定サイズのウィンドウを1行ずつ前に移動させながら、各ウィンドウの統計量を計算します。たとえば、7日間のローリング平均では、各日の値がその日と直前6日間の平均値に置き換えられます。ローリングウィンドウは、金融における移動平均、ノイズの多いセンサーデータの平滑化、ビジネスダッシュボードにおける直近期間の指標の計算の基礎となります。

import pandas as pd
import numpy as np

# Simple example: 3-day rolling mean
data = pd.Series([10, 12, 15, 11, 9, 13, 16, 14, 12, 18],
                 index=pd.date_range('2024-01-01', periods=10))

rolling_mean = data.rolling(window=3).mean()
print('Original:')
print(data.values)
print('\n3-day rolling mean:')
print(rolling_mean.values.round(2))

rolling() メソッドと window パラメーター

Series.rolling(window=n) は Rolling オブジェクトを返します。window パラメーターには、スライディングウィンドウのサイズを行数(整数ウィンドウの場合)または '7D' のような時間オフセット(時刻をインデックスとする Series の場合)で指定します。ローリングオブジェクトを作成した後は、.mean()、.sum()、.std()、.min()、.max()、さらには .apply(func) などの集計メソッドをチェーンできます。ウィンドウを埋めるのに十分な先行行がないため、最初の window-1 行は常に NaN になります。

import pandas as pd
import numpy as np

prices = pd.Series(
    [100, 102, 98, 105, 110, 108, 115, 112, 120, 118],
    index=pd.date_range('2024-01-01', periods=10),
    name='price'
)

df = pd.DataFrame({'price': prices})
df['MA3'] = df['price'].rolling(3).mean()
df['MA7'] = df['price'].rolling(7).mean()
df['std3'] = df['price'].rolling(3).std()
print(df.round(2))

min_periods パラメーター

デフォルトでは、rolling(n) は結果を計算する前に、ウィンドウ内に正確に n 個の非 NaN 値があることを要求します。min_periods パラメーターを使うと、この要件を緩和できます。たとえば、rolling(7, min_periods=3) は少なくとも3つの値が利用可能になった時点で平均を計算するため、Series の早い段階から非 NaN 値が生成されます。これは、時系列の先頭で最初の n-1 行を NaN にするのではなく、移動平均を得たい場合に便利です。

import pandas as pd
import numpy as np

prices = pd.Series([100, 102, 98, 105, 110, 108, 115],
                   index=pd.date_range('2024-01-01', periods=7))

# Default: first 6 rows are NaN
ma7_default = prices.rolling(7).mean()

# min_periods=3: compute mean once 3 values available
ma7_minperiods = prices.rolling(7, min_periods=3).mean()

df = pd.DataFrame({
    'price': prices,
    'MA7_default': ma7_default,
    'MA7_min3': ma7_minperiods
})
print(df.round(2))

累積合計のためのローリング合計

rolling(n).sum() は、各位置で直前 n 行の合計を計算します。日次売上の30日間ローリング合計を使うと、各日の直近1か月の売上を得られます。毎日更新されるため、固定された月間合計よりも有用です。ローリング合計は、小売分析(直近30日間の売上)、Web 分析(直近7日間のアクティブユーザー)、金融(直近 n 期間の出来高)などで一般的に使用されます。

import pandas as pd
import numpy as np

np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=60)
daily_sales = pd.Series(np.random.randint(100, 500, 60), index=dates, name='daily_sales')

df = pd.DataFrame({'daily_sales': daily_sales})
df['trailing_7d'] = df['daily_sales'].rolling(7).sum()
df['trailing_30d'] = df['daily_sales'].rolling(30).sum()

print(df.tail(10).round(0))

ボラティリティのためのローリング標準偏差

金融では、ボラティリティを日次リターンのローリング標準偏差として測定します。ローリング標準偏差が大きい場合は価格変動が激しく、小さい場合は価格が安定していることを示します。この指標は、オプション価格評価やポートフォリオ管理におけるリスク計算に利用されます。計算式は次のとおりです。np.log(price/price.shift(1)) で日次の対数リターンを計算し、その後 rolling(window).std() を適用します。

import pandas as pd
import numpy as np

np.random.seed(0)
prices = pd.Series(
    100 * np.exp(np.cumsum(np.random.normal(0.001, 0.02, 120))),
    index=pd.date_range('2024-01-01', periods=120)
)

# Daily log returns
log_returns = np.log(prices / prices.shift(1))

# 20-day rolling volatility (annualised)
volatility = log_returns.rolling(20).std() * np.sqrt(252)

print('Last 5 rows of daily volatility:')
print(volatility.tail(5).round(4))

時間ベースのローリングウィンドウ

固定された行数の代わりに、ウィンドウとして時間オフセットを指定できます。rolling('7D') は「直近7日間の暦日分のデータ」を意味します。これにより、不均一な時系列(週末や祝日の欠損)も正しく処理できます。行数で指定するウィンドウでは、欠損の状況によって含まれる暦日の期間が変わりますが、時間オフセットで指定するウィンドウは常に7日間のデータを対象にします。時間ベースのウィンドウを使用するには、Series が DatetimeIndex を持っている必要があります。

import pandas as pd
import numpy as np

# Business-day index (no weekends)
biz_dates = pd.bdate_range('2024-01-01', periods=15)
sales = pd.Series(np.random.randint(100, 300, 15), index=biz_dates)

# 7-calendar-day window (variable row count near weekends)
df = pd.DataFrame({'sales': sales})
df['rolling_7d'] = sales.rolling('7D').mean()

print(df.round(1))

カスタム関数のためのローリング適用

rolling(n).apply(func) は、各ウィンドウを NumPy 配列としてカスタム関数に渡します。これにより、組み込みの集計では対応できないローリング計算(ローリング中央絶対偏差、ローリング歪度、ローリング第1四分位数など)も実行できます。関数は1次元配列を受け取り、スカラー値を返す必要があります。なお、apply はベクトル化できないため、組み込みメソッドより低速です。

import pandas as pd
import numpy as np

prices = pd.Series(
    [100, 102, 98, 105, 110, 95, 115, 112, 120, 108],
    index=pd.date_range('2024-01-01', periods=10)
)

# Rolling range (max - min) over a 5-day window
def rolling_range(arr):
    return arr.max() - arr.min()

df = pd.DataFrame({'price': prices})
df['5d_range'] = prices.rolling(5).apply(rolling_range, raw=True)
print(df.round(2))

DataFrame の列に対するローリング処理

rolling().mean() を DataFrame に直接適用すると、すべての数値列のローリング統計量を同時に計算できます。各列では、それぞれ独立したローリングウィンドウが計算されます。これは、複数の株価や複数の商品売上の移動平均を、列ごとにループせず1回の操作で計算したい場合に便利です。

import pandas as pd
import numpy as np

np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=10)
df = pd.DataFrame({
    'AAPL': 100 + np.cumsum(np.random.randn(10)),
    'MSFT': 200 + np.cumsum(np.random.randn(10)),
    'GOOG': 150 + np.cumsum(np.random.randn(10))
}, index=dates)

# 3-day moving average of all three stocks
ma3 = df.rolling(3).mean()
print('3-day MA for all stocks:')
print(ma3.round(2))

ローリング平均と元のデータの組み合わせ

よく使われる可視化パターンとして、生の時系列とそのローリング平均を同じ座標軸にプロットする方法があります。ローリング平均は日々のノイズを平滑化してトレンドを明らかにし、生の系列はボラティリティを示します。両者の差から、どの程度のノイズが含まれているかが分かります。DataFrame にローリング平均を追加するには、結果を新しい列に代入するだけです。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=60)
sales = pd.Series(
    200 + np.cumsum(np.random.randn(60) * 10),
    index=dates, name='Daily Sales'
)

df = pd.DataFrame({'sales': sales})
df['MA7'] = df['sales'].rolling(7).mean()
df['MA30'] = df['sales'].rolling(30).mean()

df.plot(figsize=(12, 5), title='Sales with 7-day and 30-day Moving Average')
plt.ylabel('Sales')
plt.show()

中央寄せのローリングウィンドウ

デフォルトでは、rolling は後方ウィンドウ(現在の行と、その直前 n-1 行)を使用します。center=True を設定すると、現在の行を中央に置き、過去と未来の行を同数使用する中央寄せのウィンドウになります。中央寄せのウィンドウはより滑らかな結果を生成し、未来の値が分かっている過去データのオフライン平滑化に適しています。ただし、未来のデータが必要になるため、リアルタイムの予測には適していません。

import pandas as pd
import numpy as np

np.random.seed(0)
data = pd.Series(
    np.sin(np.linspace(0, 4*3.14159, 30)) + np.random.normal(0, 0.3, 30)
)

df = pd.DataFrame({'signal': data})
df['trailing_MA5'] = data.rolling(5).mean()
df['centered_MA5'] = data.rolling(5, center=True).mean()

print('Comparison (first 8 rows):')
print(df.head(8).round(3))

GroupByデータのローリングウィンドウ

groupby().rolling()を使用すると、グループごとのローリング統計量を計算できます。たとえば、商品カテゴリごとの7日間ローリング売上を計算する場合、ウィンドウは各グループの開始時にリセットされるため、ある商品のデータが別の商品に混ざることはありません。ローリング処理の後に.reset_index(level=0, drop=True)を使用すると、インデックスから余分なグループレベルを削除し、結果を元のDataFrameに揃えられます。

import pandas as pd
import numpy as np

np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=10)
df = pd.DataFrame({
    'date': list(dates) * 2,
    'product': ['A'] * 10 + ['B'] * 10,
    'sales': np.random.randint(50, 200, 20)
}).sort_values(['product', 'date'])

# 3-day rolling mean per product
df['rolling_mean'] = (df
    .groupby('product')['sales']
    .transform(lambda x: x.rolling(3).mean())
)
print(df.to_string(index=False))

クイックチェック

このレッスンで学んだローリングウィンドウの理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、rolling(n)によってn行のスライディングウィンドウを作成し、平均、合計、標準偏差、最小値、最大値、またはカスタム関数を計算できること、min_periodsによって結果の計算に必要な値の最小数を減らせること、center=Trueによってオフライン平滑化用の中央揃えウィンドウを作成できることを学びました。次は、Seriesの先頭から成長する累積統計量である拡張ウィンドウについて学びます。

無料で開始

AI チューターと学ぶ Python — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
30
レッスン
120

よくある質問

「ローリングウィンドウ」レッスンは無料ですか?

はい。「ローリングウィンドウ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

「ローリングウィンドウ」で何を学びますか?

rolling(n).mean()などのメソッドを使い、固定された行数を対象に移動平均、移動合計、移動標準偏差を計算します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Pandas & NumPy Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「ローリングウィンドウ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPandas & NumPy Academyレッスンでコードを書いて実行できますか?

はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ローリングウィンドウ
  2. 拡張ウィンドウ
  3. 指数加重移動平均
  4. グループ内の順位とパーセンタイル
← Pandas & NumPy Academyに戻る