two columns python numpy pandas correlation cross-correlation

python - columns - ¿Correlación cruzada(lapso de tiempo de correlación) con pandas?



pandas dataframe correlation between two columns (2)

Tengo varias series de tiempo, que quiero correlacionar, o mejor dicho, correlacionar entre ellas, para saber en qué momento el factor de correlación es mayor.

Encontré various questions y respuestas / enlaces sobre cómo hacerlo con numpy, pero eso significaría que tengo que convertir mis marcos de datos en matrices numpy. Y dado que mi serie de tiempo a menudo cubre diferentes períodos, me temo que me encontraré con el caos.

Editar

El problema que estoy teniendo con todos los métodos numpy / scipy, es que parece que no tienen conocimiento de la naturaleza temporal de mis datos. Cuando relaciono una serie de tiempo que comienza en, por ejemplo, 1940, con una que comienza en 1970, pandas corr sabe, mientras que np.correlate solo produce una np.correlate 1020 entradas (longitud de la serie más larga) llena de nan.

Las diversas Q sobre este tema indican que debería haber una manera de resolver el problema de la diferente longitud, pero hasta ahora, no he visto ninguna indicación sobre cómo usarlo para períodos de tiempo específicos. Solo necesito cambiar por 12 meses en incrementos de 1, para ver el tiempo de máxima correlación dentro de un año.

Edit2

Algunos datos de muestra mínimos:

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)

Debido a varios pasos de procesamiento, esos dfs terminaron cambiándose a df que se indexaron de 1940 a 2015. Esto debería reproducir esto

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)

Esto es lo que obtengo cuando me relaciono con pandas y cambio un conjunto de datos:

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

Y tratando de scipy:

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

que según whos es

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

Pero me gustaría tener 12 entradas. / Edit2

La idea que se me ha ocurrido es implementar una correlación de retardo de tiempo, así:

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

Pero esto probablemente sea lento, y probablemente estoy tratando de reinventar la rueda aquí. Editar El enfoque anterior parece funcionar, y lo he puesto en un bucle para pasar los 12 meses de un año, pero todavía preferiría un método incorporado.


Hay un mejor enfoque : puede crear una función que cambie su marco de datos antes de llamar al corr ().

Obtenga este marco de datos como un ejemplo:

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

Su función para cambiar otras columnas (excepto el objetivo):

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)

Suponiendo que su objetivo está comparando el prcp (variable de precipitación) con stp (presión atmosférica)

Si lo haces en el presente será:

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

Pero si cambió 1 (una) período todas las demás columnas y mantiene el objetivo (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

Tenga en cuenta que ahora la columna stp se desplaza una posición hacia arriba en el período, por lo que si llama a corr (), será:

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

Así que, puedes hacerlo con lag -1, -2, -n !!


Por lo que puedo decir, no hay un método incorporado que haga exactamente lo que está preguntando. Pero si miras el código fuente del método autocorr serie pandas, puedes ver que tienes la idea correcta:

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))

Así que una simple función de covarianza cruzada de tiempo sería

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))

Entonces, si quisiera ver las correlaciones cruzadas en cada mes, podría hacer

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