はじめに #
pandasで1次元配列を扱うSeriesクラスには、他のSeriesとの相関係数を求めるためのcorrメソッドが用意されている。 しかし、indexが時系列であるSeries同士で相関係数を求めようとすると、同じ時刻の値同士で相関を計算してしまう。 これを避けるためには、shiftメソッドで時刻をずらす必要がある。 本記事では、これについて実例を示す。
環境 #
ソフトウェア | バージョン |
---|---|
Python | 3.7.3 |
NumPy | 1.16.2 |
Pandas | 0.24.2 |
また、以下では、各ライブラリを以下のようにインポートしていることを前提とする。
import numpy as np
import pandas as pd
corrメソッドの基本 #
pandasで1次元配列を扱うSeriesクラスには、他のSeriesとの相関係数を求めるためのcorrメソッドが用意されている。 pandas.Series.corr — pandas 1.2.0 documentation
例
s1 = pd.Series([1, 2, 3, 4])
s2 = pd.Series([1, 3, 4, 4])
print(s1.corr(s2))
実行結果
0.9128709291752768
時系列データでcorrメソッドを使うときの問題 #
しかし、indexが時系列であるSeries同士で相関係数を求めようとすると、同じ時刻の値同士で相関を計算してしまう。
例を示す。乱数で生成した長さ10の配列s1
を生成する。また、s1
のindex
は、2019年12月1日を起点とした、1日周期の日付とする。
n_data = 10
start = pd.Timestamp("2019/12/01")
s1 = pd.Series(np.random.rand(n_data),
index=pd.date_range(start, freq="D", periods=n_data))
print(s1)
実行結果
2019-12-01 0.548814
2019-12-02 0.715189
2019-12-03 0.602763
2019-12-04 0.544883
2019-12-05 0.423655
2019-12-06 0.645894
2019-12-07 0.437587
2019-12-08 0.891773
2019-12-09 0.963663
2019-12-10 0.383442
Freq: D, dtype: float64
次に、s1
の1~9番目の要素を抽出したs2
と、2~10番目の要素を抽出したs3
を定義する。
s2 = s1.iloc[:-1]
s3 = s1.iloc[1:]
print(s2)
print(s3)
実行結果
2019-12-01 0.548814
2019-12-02 0.715189
2019-12-03 0.602763
2019-12-04 0.544883
2019-12-05 0.423655
2019-12-06 0.645894
2019-12-07 0.437587
2019-12-08 0.891773
2019-12-09 0.963663
Freq: D, dtype: float64
2019-12-02 0.715189
2019-12-03 0.602763
2019-12-04 0.544883
2019-12-05 0.423655
2019-12-06 0.645894
2019-12-07 0.437587
2019-12-08 0.891773
2019-12-09 0.963663
2019-12-10 0.383442
Freq: D, dtype: float64
直観的にはs2
とs3
の相関係数を計算すると、0に近い値が得られるように思う。しかしながら、実際に計算すると1となる。
print(s2.corr(s3))
実行結果
1.0
これは、corrメソッドの中で、配列の要素の位置ではなく、indexの日付を基準として相関係数の計算が行われているためである。 なお、この仕様については公式リファレンスに記載されていない。 この仕様が問題となるのは、自己相関の算出など、時間をずらして変数間の相関を求めたい場合である。
ちなみに、indexが時刻データであれば、以下のように長さの異なる配列の相関係数も計算できる(結果はもちろん1である)。
print(s2.corr(s1))
時系列データでcorrメソッドを使うときの対策 #
上記の仕様に関して、時間をずらして相関係数を算出するためには、shiftメソッドを使って配列の時刻をずらすことが必要である。
試しに、s1
の値を1つだけ後ろにずらした配列s4
を作成する。
s1
は乱数で生成した配列であるから、s4
との相関係数はほぼ0になる。
s4 = s1.shift(1)
print(s4)
print(s4.corr(s1))
実行結果
2019-12-01 NaN
2019-12-02 0.548814
2019-12-03 0.715189
2019-12-04 0.602763
2019-12-05 0.544883
2019-12-06 0.423655
2019-12-07 0.645894
2019-12-08 0.437587
2019-12-09 0.891773
2019-12-10 0.963663
Freq: D, dtype: float64
-0.13136358697190584
shiftメソッドについては以下のページを参照。 pandas.Series.shift — pandas 1.2.0 documentation
また、他にindexを時刻以外にするという対策もある。
参考リンク #
相関係数を算出するcorrメソッドについては以下を参照。 pandas.Series.corr — pandas 1.2.0 documentation Pythonで相関係数を計算する[4パターン] - Qiita
pandasのSeries, DataFrameをずらすshiftメソッドについては以下を参照。 pandas.Series.shift — pandas 1.2.0 documentation pandasでデータを行・列(縦・横)方向にずらすshift | note.nkmk.me