ITや趣味など気軽に投稿しています。

【Pandas】データの差分(階差)を計算して時系列データを分析する

時系列データを分析する際、データの「定常性」が分析の精度を大きく左右します。

この記事では、「定常性」の概要を解説し、非定常データを定常データに近づけるための前処理手法と、Pandasを用いた実装方法を紹介します。

定常とは

時系列データにおける定常とは、以下の条件を満たすデータの性質を指します。

  • どの期間のデータを取り出しても、平均が一定範囲に収まる
  • どの期間のデータを取り出しても、分散が一定範囲に収まる
  • 規則的な周期性がない

次のグラフは、Microsoftの株価データです。

Microsoftの株価グラフ

このグラフからは、以下の特徴が読み取れます。

  • 上昇トレンドが見られ、平均が一定ではない
  • 株価が上昇するにつれ、そのばらつき(分散)が大きくなっている

このことから、この時系列データは定常ではないといえます。定常でないデータは非定常データと呼ばれます。

多くの時系列分析手法(ARIMAモデルなど)は、データが定常であることを前提としています。そのため、分析に先立ち、非定常データを定常に近いデータに変換する前処理が必要になります。

非定常データを定常データに近づける方法

階差をとる

非定常データを定常に近づける代表的な手法が「階差」をとる方法です。階差とは、ある時点のデータとその1つ前の時点のデータとの差分のことです。

階差をとることで、トレンド成分を除去し、平均をある程度一定にすることができます。

上記株価データの階差をとったグラフは以下のようになります。

Microsoftの株価の階差グラフ

上昇トレンドはなくなり、平均は一定になりました。階差をとる処理は必要に応じて複数回実施することもあります。1回だけ差分をとった場合を「一回差分」、2回階差計算を繰り返した場合を「二回差分」と呼びます。

ただし、この結果を見ると期間によってばらつき(分散)に差が残っていることがわかります。

対数変換・平方根変換

分散を安定化させるためには、元データに対数変換または平方根変換を適用する方法が有効です。

元データを対数変換したグラフが以下です。

元データを対数変換したグラフ

株価が上昇しても、ばらつきがある程度一定に保たれています。このデータに対してさらに階差をとった結果が以下です。

対数変換したデータの階差をとったグラフ

平均・分散ともにどの期間をとってもほぼ一定の値になっており、トレンドも除去されています。対数変換 → 階差の組み合わせにより、定常に近いデータへの変換が実現できたといえます。

Pythonで実装する

ここまで紹介した手順を、PandasおよびNumPyを使って実装します。

Pandasバージョン

本記事は、Pandas 2.2.3の情報を基に執筆しています。

import pandas as pd
print(pd.__version__)

>>
2.2.3

使用するデータ

上記と同様に、Microsoftの株価データを使用します。このデータは、以下のKaggleリンクから取得できます。

Microsoft Stock Time Series Analysis – Kaggle

import pandas as pd

df = pd.read_csv("input/Microsoft_Stock.csv").set_index("Date")

x = pd.to_datetime(df.index).strftime('%Y-%m-%d')
y = df["Open"]
dfの中身

データには各日の始値、終値、最高値などが含まれていますが、今回は始値(Open)をY軸にとってグラフを描画していきます。

対数変換・平方根変換

対数変換・平方根変換にはNumPyを使用します。

# 対数変換
y = np.log(df["Open"])

# 平方根変換
y = np.sqrt(df["Open"])

対数変換は値の大きさに応じた変動幅を均一化する効果があり、平方根変換も同様に分散を安定化させる効果があります。データの特性に応じて使い分けてください。

階差をとる

階差の計算にはdiff()メソッドを使用します。diff()はPandasのSeriesおよびDataFrameに用意されているため、データフレームに直接適用することも、Series単体に適用することもできます。

# 対数変換してから階差をとる
y = np.log(df["Open"])
y = y.diff()

データフレーム全体に適用する場合は以下のように記述します。

df_diff = df.diff()
df_diffの中身

注意: 先頭行は前のデータが存在しないため、階差を計算できず欠損値(NaN)になります。

コード全体

Microsoftの株価データを定常に近いデータに変換してグラフ出力するコード全体は以下の通りです。

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

df = pd.read_csv("input/Microsoft_Stock.csv").set_index("Date")

x = pd.to_datetime(df.index).strftime('%Y-%m-%d')
y = df["Open"]

# 対数変換
y = np.log(df["Open"])
# 階差
y = y.diff()

# x軸ラベルの表示間隔
ticks = 200
plt.xticks(np.arange(0, len(x), ticks), x[::ticks], rotation=60)

plt.plot(x, y)

まとめ

今回は、時系列データにおける定常性の概念と、非定常データを定常データに変換する手法を紹介しました。

  • 定常データとは、平均・分散が時間によらず一定で、周期性のないデータのこと
  • 階差(diff)をとることで、トレンド成分を除去できる
  • 対数変換・平方根変換を組み合わせることで、分散の安定化も実現できる
  • Pandasのdiff()メソッドを使えば、数行のコードで階差を計算できる

効果的な時系列分析を行うためには、このような前処理が不可欠です。Pandasではdiff()メソッドにより非常に簡単に実装できるため、ぜひ実際にコードを動かして試してみてください。