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 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"])
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 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))
# 低頻度データを作成
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 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 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 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)
# 時系列を作成
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))
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 はこの種のデータを処理するための完全なツールチェーンを提供しています。