メインコンテンツへスキップ

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

·1294 文字·3 分
目次

はじめに
#

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を生成する。また、s1indexは、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

直観的にはs2s3の相関係数を計算すると、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

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

関連記事

PandasのSeriesとDataFrameの作成
·1427 文字·3 分
Pandasの基本データ構造であるSeriesとDataFrameの作成方法について述べる。
PyTorchの自動微分で勾配を求める
·2720 文字·6 分
PyTorchのtensorクラスを使った1階微分、2階微分の求め方について解説する。
Chainerの自動微分で勾配を求める
·2221 文字·5 分
ChainerのVariableクラスを使った1階微分、2階微分の求め方について解説する。
ChainerのIteratorクラスによる学習用ミニバッチ作成
·2129 文字·5 分
データセットから学習用ミニバッチを作成してくれるIteratorクラスの動作を確認する。
Chainer入門 最小限のニューラルネットワーク実装
·1600 文字·4 分
ディープラーニング用のライブラリChainerの使い方を理解するため、ChainerのChainクラスとOptimizerを使って最小限のニューラルネットワーク (NN) を実装する。
SciPyを使ったFIRフィルタによる波形整形
·1247 文字·3 分
SciPyを使って、FIR (Finite Impulse Response, 有限インパルス応答) フィルタによる離散信号の波形を整形する。ローパス、ハイパス、バンドパス、バンドエリミネイトの各フィルタの設計から、信号への適用まで行う。