Pandas 時系列分析

時系列分析はデータ分析の重要な構成要素であり、Pandas はリサンプリング、ローリング計算、移動平均など、時系列データを処理・分析するための豊富な機能を提供しています。


時系列の基本操作

時系列の作成

例

import pandas as pd
import numpy as np

# 時系列データを作成
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=100, freq="D")

ts = pd.Series(
    np.random.randn(100).cumsum() + 100,
    index=dates
)

print("時系列データ(最初の10件):")
print(ts.head(10))
print()

# 情報を確認
print(f"インデックス型: {type(ts.index)}")
print(f"開始時間: {ts.index.min()}")
print(f"終了時間: {ts.index.max()}")
print(f"時間範囲: {ts.index.max() - ts.index.min()}")

日付をインデックスに設定

例

import pandas as pd
import numpy as np

# DataFrame を作成し、日付インデックスを設定する
df = pd.DataFrame({
    "日付": pd.date_range("2024-01-01", periods=30, freq="D"),
    "売上高": np.random.randint(100, 500, 30),
    "訪問者数": np.random.randint(50, 200, 30)
})

print("設定前:")
print(df.head())
print()

# 日付をインデックスに設定
df = df.set_index("日付")
print("設定後:")
print(df.head())
print()

# loc を使用して日付でクエリ
print("2024-01-05から2024-01-10までのクエリ:")
print(df.loc["2024-01-05":"2024-01-10"])

リサンプリング

リサンプリング(Resampling)は、時系列データをある頻度から別の頻度に変換するプロセスであり、アップサンプリング(データポイントの増加)とダウンサンプリング(データポイントの削減)が含まれます。

ダウンサンプリング

例

import pandas as pd
import numpy as np

# 日次データを作成
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=90, freq="D")
ts = pd.Series(np.random.randint(100, 500, 90), index=dates)

print("日次データ(最初の10件):")
print(ts.head(10))
print()

# 月単位でリサンプリング(合計)
monthly = ts.resample("M").sum()
print("月ごとの合計:")
print(monthly)
print()

# 月単位でリサンプリング(平均)
monthly_mean = ts.resample("M").mean()
print("月ごとの平均:")
print(monthly_mean)

アップサンプリング

例

import pandas as pd

# 低頻度データを作成
dates = pd.date_range("2024-01-01", periods=3, freq="M")
ts = pd.Series([100, 200, 150], index=dates)

print("月次データ:")
print(ts)
print()

# 日次レベルにアップサンプリング(補完方法が必要)
ts_daily = ts.resample("D").ffill()
print("日次レベルへのアップサンプリング(最初の10件):")
print(ts_daily.head(10))

一般的なリサンプリング方法

方法 説明
sum() 合計
mean() 平均
max() / min() 最大値/最小値
first() / last() 最初の値/最後の値
count() 非欠損値の数
ohlc() 始値、高値、安値、終値

ローリング計算

ローリング計算(Rolling)は、時系列データに対してスライディングウィンドウ計算を行うものであり、移動平均や移動標準偏差などの計算によく使用されます。

移動平均

例

import pandas as pd
import numpy as np

# データを作成
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=30, freq="D")
ts = pd.Series(np.random.randint(100, 200, 30), index=dates)

# 7日移動平均を計算
rolling_mean = ts.rolling(window=7).mean()
print("7日移動平均(最初の10件):")
print(rolling_mean.head(10))
print()

# 7日移動標準偏差を計算
rolling_std = ts.rolling(window=7).std()
print("7日移動標準偏差:")
print(rolling_std.head(10))

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

例

import pandas as pd
import numpy as np

ts = pd.Series(range(1, 11))

print("元データ:")
print(ts)
print()

# ローリング合計
print("ローリング3合計:")
print(ts.rolling(3).sum())
print()

# ローリング最大値
print("ローリング3最大値:")
print(ts.rolling(3).max())
print()

# apply を使用
print("ローリング3カスタム関数(レンジ):")
print(ts.rolling(3).apply(lambda x: x.max() - x.min()))

時系列データの可視化

例

import pandas as pd
import numpy as np

# サンプルデータを作成
np.random.seed(42)
dates = pd.date_range("2024-01-01", periods=100, freq="D")
ts = pd.Series(
    np.random.randn(100).cumsum() + 100,
    index=dates
)

# 移動平均を計算
ma_7 = ts.rolling(7).mean()
ma_30 = ts.rolling(30).mean()

# データを表示
print("時系列 + 移動平均:")
print(f"元データ(最初の5件): {ts.head().tolist()}")
print(f"7日移動平均線(最初の10件): {ma_7.dropna().head().tolist()}")
print(f"30日移動平均線(最後の5件): {ma_30.dropna().tail().tolist()}")

時系列特徴量の抽出

例

import pandas as pd

# 時系列を作成
ts = pd.Series(
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    index=pd.date_range("2024-01-01", periods=10, freq="D")
)

# 差分
diff = ts.diff()
print("1階差分:")
print(diff)
print()

# 変化率(パーセント変化)
pct = ts.pct_change()
print("変化率(パーセント変化):")
print(pct)
print()

# シフト
shifted = ts.shift(1)
print("後方へ1シフト:")
print(shifted)

実践:株価データ分析

例

import pandas as pd
import numpy as np

# 株価データをシミュレート
np.random.seed(42)
n_days = 60

df = pd.DataFrame({
    "日付": pd.date_range("2024-01-01", periods=n_days, freq="D"),
    "始値": 100 + np.random.randn(n_days).cumsum(),
    "終値": 100 + np.random.randn(n_days).cumsum(),
    "出来高": np.random.randint(1000000, 10000000, n_days)
})
df = df.set_index("日付")

# 日次収益率を計算
df["収益率"] = df["終値"].pct_change()

# ボラティリティを計算(7日ローリング標準偏差)
df["ボラティリティ"] = df["収益率"].rolling(7).std() * np.sqrt(252)  # 年率換算

# 移動平均線を計算
df["MA5"] = df["終値"].rolling(5).mean()
df["MA20"] = df["終値"].rolling(20).mean()

# 取引シグナルを生成(ゴールデンクロス/デッドクロス)
df["シグナル"] = 0
df.loc[df["MA5"] > df["MA20"], "シグナル"] = 1
df.loc[df["MA5"] < df["MA20"], "シグナル"] = -1

print("株価データ分析結果:")
print(df.tail(10))

よくある質問

1、日付が連続していない

一部の時系列は毎日データがあるとは限りません(祝日など)。以下のものを使用してasfreq 或 reindex処理する必要があります。

2、タイムゾーンの問題

タイムゾーンをまたぐデータを処理する場合は、次を使用してtz_localizeとtz_convertタイムゾーンの設定と変換を行います。

3、欠損値の影響

ローリング計算はデフォルトで欠損値をスキップしますが、結果の連続性に影響を与える可能性があります。

時系列分析は金融、気象、IoTなどの分野における基礎スキルであり、Pandas はこの種のデータを処理するための完全なツールチェーンを提供しています。

その他の拡張