Подтвердить что ты не робот

Корреляция столбцов в DataFrame

Я новичок в pandas, поэтому я думаю, что я делаю что-то неправильно -

У меня есть DataFrame:

     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() дает мне:

    a   b
a NaN NaN
b NaN NaN

но np.correlate(df["a"], df["b"]) дает: 1.875

Почему? Я хочу иметь корреляционную матрицу для моего DataFrame и думаю, что corr() делает это (по крайней мере, согласно документации). Почему он возвращает NaN?

Каков правильный способ вычисления?

Большое спасибо!

4b9b3361

Ответ 1

np.correlate вычисляет (ненормализованный) cross-correlation между двумя одномерными последовательностями:

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

а df.corr (по умолчанию) вычисляет коэффициент корреляции Пирсона.

Коэффициент корреляции (если он существует) всегда находится между -1 и 1 включительно. Кросс-корреляция не ограничена.

Формулы несколько взаимосвязаны, но обратите внимание, что в формуле кросс-корреляции (см. выше) нет вычитания средств и нет деления на стандартные отклонения, которые являются частью формулы для коэффициента корреляции Пирсона.

Тот факт, что стандартное отклонение df['a'] и df['b'] равно нулю, является причиной того, что df.corr является NaN всюду.


Из комментария ниже, похоже, что вы ищете Beta. Это связано с коэффициентом корреляции Пирсона, но вместо деления на произведение стандартных отклонений:

enter image description here

вы делите на дисперсию:

enter image description here


Вы можете вычислить Beta с помощью 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

Отношение mu равно 2, а Beta равно ~ 2.1.


И вы также можете вычислить его с помощью df.corr, хотя это гораздо более крутой способ сделать это (но приятно видеть, что есть последовательность):

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)