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

時系列データを分析する際、そのままのデータで分析できる場合もあれば、うまく分析できない場合もあります。

分析できるかできないかは、データの「定常性」に関わる場合が多いです。今回は、「定常性」とは?をざっくり説明した後、うまく分析できないデータを分析できるようにするための処理を紹介していきます。

定常とは

時系列における定常とは、ざっくり言うと

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

ようなものを指します。

詳細は以下サイトが参考になります。

https://www.ai.u-hyogo.ac.jp/~arima/arima.pdf

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

Microsoftの株価グラフ

この時系列データは定常といえるでしょうか?

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

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

データ分析を行う際には、このような非定常データを定常に近いデータに変換していく必要があります。

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

階差をとる

非定常データを定常に近いデータに近づける方法として「階差」をとるという方法があります。階差とは、あるデータとその1つ前のデータの差分のことです。階差をとることで、トレンドを除去し、平均をある程度一定にすることができます。

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

Microsoftの株価の階差グラフ

上昇トレンドはなくなり、平均は一定になりました。階差をとる処理は、場合によって複数回実施することもあります。今回は一度だけ差分をとったので「一回差分」、2回階差計算を繰り返しタ場合を「二回差分」といったように表現します。

ただ、今回のデータの場合、まだ期間によってばらつきに差がありそうです。

対数変換、平方根変換

ばらつきをほぼ一定にするためには、元データを対数変換あるいは平方根変換する方法があります。今回は元データを対数変換してみます。

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

株価が上昇しても、そのばらつきはある程度一定になりました。このデータで階差をとってグラフを描いてみます。

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

平均、分散ともにどの期間をとっても同じような値になりそうです。また、トレンドも除去できているので、定常に近いデータに変換できたといえそうです。

Pythonで実装する

ここまで紹介してきた手順を、Pythonで実装していきます。

使用するデータ

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

https://www.kaggle.com/vijayvvenkitesh/microsoft-stock-time-series-analysis

import pandas as pd

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

x = df.index
y = df["Open"]

情報としてはその日の始値、終値、最高値とうありますが、今回は始値”Open”をY軸にとってグラフ描画していきます。

対数変換、平方根変換

対数変換、平方根変換にはnumpyを用います。

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

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

階差をとる

階差をとる場合はdiff()メソッドを用います。このメソッドはPandasにもnumpyにも用意されているため、データフレームにそのまま適用することもできればnumpy配列に適用することもできます。

今回はnumpy配列に適用します。

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

ちなみにデータフレームに適用する場合は以下の通り

df_diff = df.diff()
df_diffの中身

先頭のデータは階差を計算できないため欠損値になります。

コード全体

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 = df.index
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)

Pythonでデータサイエンスするなら

Pythonでデータサイエンスをするなら、以下の書籍がおすすめです。Pandas、matplotlib、Numpy、scikit-learnといったデータサイエンスに必要なライブラリを、体系立てて一通り学ぶことができます。

ややお値段高めですが、これ1冊で十分という内容・ボリュームなので、損はしないと思います^^

まとめ

時系列データにおける定常性について触れ、非定常データを定常に近いデータに変換して分析できるようにする手順を紹介しました。

効果的な分析をするためにはその前処理が重要です。今回の例はPythonでも簡単に実装できるので、是非手を動かしながら試してみてください!

ではでは👋