在0-lag和np.corrcoef之间的标准plt.xcorr之间的差异

时间:2016-09-22 00:35:59

标签: python numpy correlation cross-correlation

我正在研究两个相对较小的时间序列之间的交叉关联,但在努力实现我遇到的问题我无法自我调和。首先,我了解plt.xcorrnp.correlate之间的依赖关系。但是,我无法协调零滞后plt.xcorrnp.corrcoef之间的差异?

a = np.array([  7.35846410e+08,   8.96271634e+08,   6.16249222e+08,
     8.00739868e+08,   1.06116376e+09,   9.05690167e+08,
     6.31383600e+08])
b = np.array([  1.95621617e+09,   2.06263134e+09,   2.27717015e+09,
     2.27281916e+09,   2.71090116e+09,   2.84676385e+09,
     3.19578883e+09])

np.corrcoef(a,b)
# returns:
array([[ 1.        ,  0.02099573],
      [ 0.02099573,  1.        ]])

plt.xcorr(a,b,normed=True, maxlags=1)
# returns:
array([-1,  0,  1]),
 array([ 0.90510941,  0.97024415,  0.79874158])

我希望这些返回相同的结果。我显然不明白plt.xcorr是如何规范的,有人可以请我直截了当吗?

3 个答案:

答案 0 :(得分:1)

标准" Pearson积矩相关系数的计算"使用样本,移动平均值。 互相关系数不使用归一化样本。 除此之外,计算是类似的。但这些系数仍有不同的公式和不同的含义。只有当样本ab的平均值等于0时,它们才相等(如果按平均值移动则不会更改样本。

import numpy as np
import matplotlib.pyplot as plt

a = np.array([7.35846410e+08, 8.96271634e+08, 6.16249222e+08,
     8.00739868e+08, 1.06116376e+09, 9.05690167e+08, 6.31383600e+08])
b = np.array([1.95621617e+09, 2.06263134e+09, 2.27717015e+09,
     2.27281916e+09, 2.71090116e+09, 2.84676385e+09, 3.19578883e+09])

y = np.corrcoef(a, b)
z = plt.xcorr(a, b, normed=True, maxlags=1)
print("Pearson product-moment correlation coefficient between `a` and `b`:", y[0][1])
print("Cross-correlation coefficient between `a` and `b` with 0-lag:", z[1][1], "\n")


# Calculate manually:

def pearson(a, b):
    # Length.
    n = len(a)

    # Means.
    ma = sum(a) / n
    mb = sum(b) / n

    # Shifted samples.
    _ama = a - ma
    _bmb = b - mb

    # Standard deviations.
    sa = np.sqrt(np.dot(_ama, _ama) / n)
    sb = np.sqrt(np.dot(_bmb, _bmb) / n)

    # Covariation.
    cov = np.dot(_ama, _bmb) / n

    # Final formula.
    # Note: division by `n` in deviations and covariation cancel out each other in
    #       final formula and could be ignored.
    return cov / (sa * sb)

def cross0lag(a, b):
    return np.dot(a, b) / np.sqrt(np.dot(a, a) * np.dot(b, b))

pearson_coeff = pearson(a, b)
cross_coeff = cross0lag(a, b)

print("Manually calculated coefficients:")
print("  Pearson =", pearson_coeff)
print("  Cross   =", cross_coeff, "\n")


# Normalized samples:
am0 = a - sum(a) / len(a)
bm0 = b - sum(b) / len(b)
pearson_coeff = pearson(am0, bm0)
cross_coeff = cross0lag(am0, bm0)
print("Coefficients for samples with means = 0:")
print("  Pearson =", pearson_coeff)
print("  Cross   =", cross_coeff)

<强>输出:

Pearson product-moment correlation coefficient between `a` and `b`: 0.020995727082
Cross-correlation coefficient between `a` and `b` with 0-lag: 0.970244146831 

Manually calculated coefficients:
  Pearson = 0.020995727082
  Cross   = 0.970244146831 

Coefficients for samples with means = 0:
  Pearson = 0.020995727082
  Cross   = 0.020995727082

答案 1 :(得分:0)

我使用了http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.xcorr

  

normed:布尔值,可选,默认值:True

     

如果为True,则通过第0个滞后的自相关来规范化数据。

在以下代码中,plt_corr等于np_corr

plt_corr = plt.xcorr(a, b, normed=True, maxlags=6)

c = np.correlate(a, a)  # autocorrelation of a
d = np.correlate(b, b)  # autocorrelation of b
np_corr = np.correlate(a/np.sqrt(c), b/np.sqrt(d), 'full')

答案 2 :(得分:0)

正如 DJV 的回答所说,在 plt.xcorr 上,normed=True 仅对幅度进行标准化。如果您还想归一化为均值 = 0,就像对 Pearson r 所做的那样,您可以添加参数 detrend=mlab.detrend_mean

import matplotlib.pyplot as plt
import matplotlib.mlab as mlab

plt.xcorr(a, b, normed=True, maxlags=1, detrend=mlab.detrend_mean)