2019/07/01
2020/04/14
非定常な時系列データを変換して定常性を持たせる解析
この記事では、pythonで時系列解析・分析を行っていくうえでの基礎知識として、非定常な時系列データを変換して定常性を持たせる解析について説明します。平均・分散、正規分布などの統計学の初歩の知識を前提とした初心者向け入門記事です。
以降、時点\(t\) での時系列の値・確率変数を共に \(yt\) と表しています。
時系列データの解析に変換が必要な理由
時系列が定常性を満たしさえすれば非常に分析しやすそうです。 例えば、平均が時間とともに変化しないため、総和をサンプル数で割ることによる平均の推定が有効ですし、自己相関についても同様のことがいえます。
しかし、私たちが興味のある時系列のほとんどはAirPassengersのように非定常です。 株価や売上、サイトのアクセス数などは明らかなトレンドを持つでしょうし、機械の振動や音声などは動作によりバラツキ(分散)が一定ではありません。
そこで、非定常な時系列は定常性を持つように変換する必要があります。 本記事では、時系列データに対する主要な変換・前処理として差分変換と対数変換・季節差分を紹介します。 また、変換を行う前の系列のことを 原系列といいます。
主要な変換・前処理
差分変換
一時点離れた値との差を取る差分変換により、平均に関して非定常な系列を定常にできる場合があります。 差分系列 \(Δyy \)は以下の式で定義されます。
$$\Delta y_t = y_t – y_{t-1}$$
差分変換は、系列が定常であるとみなせるようになるまで複数回行うことがあります。 一度差分をとることは一階差分と呼ばれ、さらにもう一度差分をとることは二階差分と呼ばれます。 周期性のあるデータに対しては、周期分だけ離れた値との差をとる季節差分を行うことがあります。
非負な原系列に対して対数を取る対数変換は、トレンドに比例してバラツキが変化するような系列に対して有効です。これは、対数をとることにより積の構造が和の構造に変わるためです。
$${\rm log}(X\times Y)={\rm log}X + {\rm log}Y$$
対数差分変換
金融の分野では、元の価格推移のデータを対数変換したのち差分変換する対数差分変換がしばしば行われ、変化後のデータは「対数収益率」とよばれます。 対数収益率を用いることには、「100円の銘柄が1円値上がりする」ことと「1000円の銘柄が1円値上がりする」ことの不平等さを解消できることなど、様々なメリットがあります。
対数変換の練習
ではここで、実際に対数変換と対数変換の練習をすることにします。 まずは差分変換についてですが、pandasのdiff()メソッドを使うことができます。 引数periodsは差分を取るラグを表しています。 実行結果を見ると、AirPassengersのトレンドは除去され、平均に関する非定常性を解消できたことが伺えます。
Passengers_diff = df["Passengers"].diff(periods = 1) Passengers_diff.plot()
次に対数変換を行ってみましょう。 対数をとるには数値計算モジュールnumpyのlog()を使います。 なお、対数の底はネイピア数\( e\) です。 対数変換後の図ともとの図を見比べると、トレンドに比例したバラツキの増加が解消されたことがわかります。
import numpy as np
Passengers_log = np.log(df["Passengers"]) Passengers_log.head()
Month
1949-01-01 4.718499
1949-02-01 4.770685
1949-03-01 4.882802
1949-04-01 4.859812
1949-05-01 4.795791
Name: Passengers, dtype: float64
Passengers_log.plot()
対数変換と差分変換を組み合わせた対数差分の例を示します。 先ほど作成したPassengers_logを再利用し、差分をとってみましょう。 周期性が残っているものの、定常性の条件のうち、平均と分散に関するものが解消できたことが伺えます。
Passengers_log_diff = Passengers_log.diff(periods = 1) Passengers_log_diff.plot()
周期を取り除くために、Passengers_logに対しperiods = 12として季節差分を行ってみましょう。 季節周期がなくなり、前年差が残ったことになります。
Passengers_sdiff = Passengers_log.diff(periods = 12) Passengers_sdiff.plot()
さらにもう一度ラグ1の差分をとると、見た目が大分定常らしくなりました。
Passengers_sdiff2 = Passengers_sdiff.diff() Passengers_sdiff2.plot()
まとめ
いかがでしたか?
差分変換や対数変換を行うことによって、非定常な時系列データを定常化することができましたね。
ただすべての時系列データを差分変換によって定常にできるわけではありません。
次の記事では、どのような性質をもつ系列が差分変換に向いているのか、解説します。
Recommended