2013-04-06 14 views
30

Ich bin ziemlich neu für Pandas, so dass ich denke, ich mache etwas falsch -Korrelation zwischen den Spalten in Datenrahmen

Ich habe einen Datenrahmen:

 a  b 
0 0.5 0.75 
1 0.5 0.75 
2 0.5 0.75 
3 0.5 0.75 
4 0.5 0.75 

df.corr() gibt mir:

a b 
a NaN NaN 
b NaN NaN 

aber np.correlate(df["a"], df["b"]) gibt: 1.875

Warum ist t Hut? Ich möchte die Korrelationsmatrix für meinen DataFrame haben und dachte, dass corr() das tut (zumindest gemäß der Dokumentation). Warum gibt es NaN zurück?

Was ist die richtige Berechnung?

Vielen Dank!

Antwort

63

np.correlate berechnet die (nicht normalisierten) cross-correlation zwischen zwei 1-dimensionalen Sequenzen:

z[k] = sum_n a[n] * conj(v[n+k]) 

während df.corr (Standard) die Pearson correlation coefficient berechnet.

Der Korrelationskoeffizient (falls vorhanden) liegt immer zwischen -1 und 1. Die Kreuzkorrelation ist nicht begrenzt.

Die Formeln sind etwas verwandt, aber beachten Sie, dass in der Kreuzkorrelationsformel (oben) keine Subtraktion der Mittel und keine Division durch die Standardabweichungen, die Teil der Formel für Pearson Korrelationskoeffizienten ist.

Die Tatsache, dass die Standardabweichung von df['a'] und df['b'] gleich Null ist, verursacht, dass df.corr überall NaN ist.


Aus dem Kommentar unten, es klingt wie Sie für Beta suchen. Es wird auf Pearsons Korrelationskoeffizient bezogen, sondern statt durch das Produkt der Standardabweichungen Dividieren:

enter image description here

Sie teilen durch eine Varianz:

enter image description here


Sie können Beta berechnen mit np.cov

cov = np.cov(a, b) 
beta = cov[1, 0]/cov[0, 0] 

import numpy as np 
import matplotlib.pyplot as plt 
np.random.seed(100) 


def geometric_brownian_motion(T=1, N=100, mu=0.1, sigma=0.01, S0=20): 
    """ 
    http://stackoverflow.com/a/13203189/190597 (unutbu) 
    """ 
    dt = float(T)/N 
    t = np.linspace(0, T, N) 
    W = np.random.standard_normal(size=N) 
    W = np.cumsum(W) * np.sqrt(dt) # standard brownian motion ### 
    X = (mu - 0.5 * sigma ** 2) * t + sigma * W 
    S = S0 * np.exp(X) # geometric brownian motion ### 
    return S 

N = 10 ** 6 
a = geometric_brownian_motion(T=1, mu=0.1, sigma=0.01, N=N) 
b = geometric_brownian_motion(T=1, mu=0.2, sigma=0.01, N=N) 

cov = np.cov(a, b) 
print(cov) 
# [[ 0.38234755 0.80525967] 
# [ 0.80525967 1.73517501]] 
beta = cov[1, 0]/cov[0, 0] 
print(beta) 
# 2.10609347015 

plt.plot(a) 
plt.plot(b) 
plt.show() 

enter image description here

Das Verhältnis von mu s 2 und beta ist ~ 2.1.


Und man könnte es auch mit df.corr berechnen, obwohl dies, es zu tun viel mehr Umwege ist (aber es ist schön, da die Konsistenz zu sehen ist):

import pandas as pd 
df = pd.DataFrame({'a': a, 'b': b}) 
beta2 = (df.corr() * df['b'].std() * df['a'].std()/df['a'].var()).ix[0, 1] 
print(beta2) 
# 2.10609347015 
assert np.allclose(beta, beta2) 
+0

Dank! Also meine "a" und "b" sind tägliche Änderungen der Preise und ich möchte messen, wie "b" in Bezug auf "a" (Bedeutung - wenn jedes Mal "a" um 1% steigt b steigt um 2% Ich würde erwarten, 2,0 zu sehen, wenn "b" immer -0,5% ist, würde ich -0,5 erwarten. Ich denke, die 'Kreuzkorrelation' ist was ich will, oder? –

Verwandte Themen