JavaScriptを有効にしてください

pandas.Seriesのcorrメソッドで時系列データの相関係数を求める際の注意点

 ·   3 min read

はじめに

pandasで1次元配列を扱うSeriesクラスには、他のSeriesとの相関係数を求めるためのcorrメソッドが用意されている。
しかし、indexが時系列であるSeries同士で相関係数を求めようとすると、同じ時刻の値同士で相関を計算してしまう。
これを避けるためには、shiftメソッドで時刻をずらす必要がある。
本記事では、これについて実例を示す。

環境

ソフトウェア バージョン
Python 3.7.3
NumPy 1.16.2
Pandas 0.24.2

また、以下では、各ライブラリを以下のようにインポートしていることを前提とする。

1
2
import numpy as np
import pandas as pd

corrメソッドの基本

pandasで1次元配列を扱うSeriesクラスには、他のSeriesとの相関係数を求めるためのcorrメソッドが用意されている。
pandas.Series.corr — pandas 1.2.0 documentation

1
2
3
4
s1 = pd.Series([1, 2, 3, 4])
s2 = pd.Series([1, 3, 4, 4])

print(s1.corr(s2))

実行結果

1
0.9128709291752768

時系列データでcorrメソッドを使うときの問題

しかし、indexが時系列であるSeries同士で相関係数を求めようとすると、同じ時刻の値同士で相関を計算してしまう。

例を示す。乱数で生成した長さ10の配列s1を生成する。また、s1indexは、2019年12月1日を起点とした、1日周期の日付とする。

1
2
3
4
5
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)

実行結果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
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を定義する。

1
2
3
4
s2 = s1.iloc[:-1]
s3 = s1.iloc[1:]
print(s2)
print(s3)

実行結果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
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

直観的にはs2s3の相関係数を計算すると、0に近い値が得られるように思う。しかしながら、実際に計算すると1となる。

1
print(s2.corr(s3))

実行結果

1
1.0

これは、corrメソッドの中で、配列の要素の位置ではなく、indexの日付を基準として相関係数の計算が行われているためである。
なお、この仕様については公式リファレンスに記載されていない。
この仕様が問題となるのは、自己相関の算出など、時間をずらして変数間の相関を求めたい場合である。

ちなみに、indexが時刻データであれば、以下のように長さの異なる配列の相関係数も計算できる(結果はもちろん1である)。

1
print(s2.corr(s1))

時系列データでcorrメソッドを使うときの対策

上記の仕様に関して、時間をずらして相関係数を算出するためには、shiftメソッドを使って配列の時刻をずらすことが必要である。

試しに、s1の値を1つだけ後ろにずらした配列s4を作成する。
s1は乱数で生成した配列であるから、s4との相関係数はほぼ0になる。

1
2
3
s4 = s1.shift(1)
print(s4)
print(s4.corr(s1))

実行結果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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

シェアする

Helve
WRITTEN BY
Helve
関西在住、電機メーカ勤務のエンジニア。X(旧Twitter)で新着記事を配信中です

サイト内検索