2015-10-16 81 views
15

我有各種不同的時間序列,我想要關聯 - 或者說,互相關 - 彼此,以找出在哪個時間滯後相關因子是最大的。與大熊貓的互相關(時滯 - 相關)?

我發現variousquestions和答案/鏈接討論如何用numpy做到這一點,但這些都意味着我必須把我的數據框變成numpy數組。而且由於我的時間系列經常涉及不同時期,所以恐怕我會陷入混亂。

編輯

我與所有的numpy的/ SciPy的方法遇到的問題是,他們似乎缺少我的數據的時間序列性質的認識。當我將1940年開始的一個時間序列與1970年開始的時間序列相關聯時,熊貓corr知道這一點,而np.correlate只產生1020個條目(長度較長的序列),數組滿足nan。

在這個問題上的各種問題表明,應該有辦法解決不同的長度問題,但到目前爲止,我沒有看到如何在特定時間段內使用它的跡象。我只需要按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) 

由於各種處理步驟,這些DFS最終變成DF個從1940年索引到2015年這應該重現此:

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) 

這就是當我與大熊貓關聯並移動一個數據集時得到的結果:

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個條目。 /EDIT 2

的想法,我想出了,是實現時間滯後相關自己,就像這樣:

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 

但是,這可能是緩慢的,而我可能是想在這裏重新發明輪子。 編輯上述方法似乎工作,我已經把它放到一個循環中,要經歷一年的所有12個月,但我仍然更喜歡內置方法。

+0

如果你還沒有看到這些,請考慮使用['scipy.signal.correlate'](http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.correlate .html)和['scipy.signal.correlate2d'](http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.correlate2d.html)。我會說轉換成numpy陣列可能是你最好的選擇。 – wgwz

+0

我已經看到了這些,但我想避免去numpy,因爲在這一步之後,我將不得不轉換回數據框,以進一步計算。我想我會嘗試重新發明輪子,然後... –

+0

據我所知,這是一個非常普遍的工作流程,轉換爲numpy和後面。我沒有看到這樣做需要猶豫。我會建議將你的陣列寫入磁盤,所以你不要在你的代碼中重複轉換。簽出'pd.HDFStore'和'h5py'。如果你覺得要重新發明輪子,就去做吧。 – wgwz

回答

21

據我所知,沒有一個內置的方法,正好你在問什麼。但是,如果你看一下熊貓系列方法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)) 

因此,一個簡單timelagged互協方差函數是

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)] 
+0

謝謝,這有助於很多!完全忘記了內置的自相關本質上是一個時滯關聯。我會看看是否可以用它來產生比列表更有用的輸出。 –

0

有一個更好的方法:您可以創建一個函數,在調用corr()之前,您的數據框首先移動

得到這個數據幀像一個例子:

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 

但是,如果你轉移1(1)週期中的所有其他列並保持目標(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 

所以,你可以用lag -1,-2,-n來做!