web-dev-qa-db-ja.com

パンダとの相互相関(タイムラグ相関)?

さまざまな時系列があり、相互に相関させるか、相互相関させて、相関係数が最大の時間差を見つけます。

variousquestions とnumpyでそれを行う方法を議論する回答/リンクを見つけましたが、それらは私のデータフレームをnumpy配列に変えなければならないことを意味します。そして、私の時系列はしばしば異なる期間をカバーしているので、私は混乱に陥ることを恐れています。

編集

私がすべてのnumpy/scipyメソッドで抱えている問題は、それらが私のデータの時系列の性質を認識していないように見えることです。たとえば、1940年に始まる時系列を1970年に始まる時系列と相関させると、pandas corrはこれを知っていますが、np.correlateは、nanでいっぱいの1020エントリ(より長いシリーズの長さ)配列を生成します。

このテーマのさまざまなQは、異なる長さの問題を解決する方法があるはずであることを示していますが、これまでのところ、特定の期間にそれを使用する方法に関する指示は見ていません。 1年以内に最大の相関の時間を見るために、1ずつ12か月シフトする必要があります。

Edit2

最小限のサンプルデータ:

import pandas as pd
import numpy as np
dfdates1 = pd.date_range('01/01/1980', '01/01/2000', freq = 'MS')
dfdata1 = (np.random.random_integers(-30,30,(len(dfdates1)))/10.0) #My real data is from measurements, but random between -3 and 3 is fitting
df1 = pd.DataFrame(dfdata1, index = dfdates1)
dfdates2 = pd.date_range('03/01/1990', '02/01/2013', freq = 'MS')
dfdata2 = (np.random.random_integers(-30,30,(len(dfdates2)))/10.0)
df2 = pd.DataFrame(dfdata2, index = dfdates2)

さまざまな処理手順により、これらのdfは1940年から2015年にインデックス付けされたdfに変更されます。これにより、これが再現されるはずです。

bigdates = pd.date_range('01/01/1940', '01/01/2015', freq = 'MS')
big1 = pd.DataFrame(index = bigdates)
big2 = pd.DataFrame(index = bigdates)
big1 = pd.concat([big1, df1],axis = 1)
big2 = pd.concat([big2, df2],axis = 1)

これは、pandasと相関させ、1つのデータセットをシフトしたときに得られるものです。

In [451]: corr_coeff_0 = big1[0].corr(big2[0])
In [452]: corr_coeff_0
Out[452]: 0.030543266378853299
In [453]: big2_shift = big2.shift(1)
In [454]: corr_coeff_1 = big1[0].corr(big2_shift[0])
In [455]: corr_coeff_1
Out[455]: 0.020788314779320523

そして、scipyを試す:

In [456]: scicorr = scipy.signal.correlate(big1,big2,mode="full")
In [457]: scicorr
Out[457]: 
array([[ nan],
       [ nan],
       [ nan],
       ..., 
       [ nan],
       [ nan],
       [ nan]])

whosによれば

scicorr               ndarray                       1801x1: 1801 elems, type `float64`, 14408 bytes

しかし、私は12のエントリが欲しいだけです。 / Edit2

私が思いついたアイデアは、タイムラグ相関を自分で実装することです。

corr_coeff_0 = df1['Data'].corr(df2['Data'])
df1_1month = df1.shift(1)
corr_coeff_1 = df1_1month['Data'].corr(df2['Data'])
df1_6month = df1.shift(6)
corr_coeff_6 = df1_6month['Data'].corr(df2['Data'])
...and so on

しかし、これはおそらく遅いです、そして、私はおそらくここで車輪を再発明しようとしています。 Edit上記のアプローチはうまくいくようで、私はそれをループに入れて、1年の12ヶ月すべてを通過しましたが、私はまだ好むでしょう組み込みメソッド。

28
JC_CL

私が知る限り、exactlyあなたが求めていることを行う組み込みメソッドはありません。ただし、pandas Seriesメソッドautocorrのソースコードを見ると、正しいアイデアがあることがわかります。

def autocorr(self, lag=1):
    """
    Lag-N autocorrelation

    Parameters
    ----------
    lag : int, default 1
        Number of lags to apply before performing autocorrelation.

    Returns
    -------
    autocorr : float
    """
    return self.corr(self.shift(lag))

したがって、単純な時間遅れの相互共分散関数は次のようになります。

def crosscorr(datax, datay, lag=0):
    """ Lag-N cross correlation. 
    Parameters
    ----------
    lag : int, default 0
    datax, datay : pandas.Series objects of equal length

    Returns
    ----------
    crosscorr : float
    """
    return datax.corr(datay.shift(lag))

次に、各月の相互相関を調べたい場合は、次のようにします。

 xcov_monthly = [crosscorr(datax, datay, lag=i) for i in range(12)]
33
Daniel Watkins

より良いアプローチがあります:shiftedcorr()を呼び出す前に、データフレームを最初にします。

例のようにこのデータフレームを取得します。

d = {'prcp': [0.1,0.2,0.3,0.0], 'stp': [0.0,0.1,0.2,0.3]}
df = pd.DataFrame(data=d)

>>> df
   prcp  stp
0   0.1  0.0
1   0.2  0.1
2   0.3  0.2
3   0.0  0.3

他の列をシフトする関数(ターゲットを除く):

def df_shifted(df, target=None, lag=0):
    if not lag and not target:
        return df       
    new = {}
    for c in df.columns:
        if c == target:
            new[c] = df[target]
        else:
            new[c] = df[c].shift(periods=lag)
    return  pd.DataFrame(data=new)

ターゲットがprcp(降水量変数)とstp(大気圧)を比較していると仮定します

あなたが現時点で行う場合は:

>>> df.corr()
      prcp  stp
prcp   1.0 -0.2
stp   -0.2  1.0

ただし、shifted 1(one)他のすべての列をピリオドにして、target(prcp)を保持する場合:

df_new = df_shifted(df, 'prcp', lag=-1)

>>> print df_new
   prcp  stp
0   0.1  0.1
1   0.2  0.2
2   0.3  0.3
3   0.0  NaN

ここで、列stpはピリオドで1つ上にシフトしているため、corr()を呼び出すと、次のようになることに注意してください。

>>> df_new.corr()
      prcp  stp
prcp   1.0  1.0
stp    1.0  1.0

したがって、遅延-1、-2、-nで処理できます。

2
Andre Araujo

Andreの答えに基づいて-ターゲットとの(時間差のある)相関関係だけを気にしながら、さまざまなラグをテストしたい場合(たとえば、どのラグが最も高い相関を与えるかを確認する場合)、次のようなことができます:

lagged_correlation = pd.DataFrame.from_dict(
    {x: [df[target].corr(df[x].shift(-t)) for t in range(max_lag)] for x in df.columns})

このように、各行は異なるラグ値に対応し、各列は異なる変数に対応します(そのうちの1つはターゲット自体であり、自己相関を提供します)。

0
Itamar Mushkin