You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中时间序列互相关系数超[-1,1]范围的原因及解决办法

问题根源:计算方法错误,与数据集无关

你得到的结果超出-1到1范围,是因为scipy.signal.correlate返回的是未归一化的互相关原始值,不是你需要的互相关系数。同时你的代码里存在重复去均值、错误归一化的问题,导致结果异常。

代码中的错误点

  1. 重复去均值:已经对序列做了wl=w_sub['a'] - np.mean(w_sub['a']),后续又计算wl-np.mean(wl),此时序列均值已经为0,重复操作无意义。
  2. 错误的归一化方式:用np.max(wl)做归一化不是标准化操作,无法让序列方差为1,后续互相关值的尺度会失控。
  3. 未对互相关结果归一化:原始互相关值的大小取决于序列能量,必须经过归一化处理才能得到范围在-1到1的系数。

修正后的实现

方法一:手动归一化(兼容所有scipy版本)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from dateutil.relativedelta import relativedelta
from scipy import signal

np.random.seed(1)
tidx = pd.date_range('1975-01-01', periods=36,  freq='MS') 
tim=pd.to_datetime(tidx)
df_t=pd.DataFrame(tim, columns=['time']) 
p1=pd.DataFrame([13, 17, 13, 15, 9, 9, 16, 11, 11, 16, 11, 10, 23, 19, 23, 9, 3, 6, 4, 27, 8, 16, 
                 26, 17, 16, 15, 16,  8, 36,  9,  9, 11, 11, 16,  7,  5], columns=['a'])
p2=pd.DataFrame([1182.7,1191.5,1206.1,1259.6,1351.2,1473.2,1531.6,1531.2,1531.4,1530.7,1527.8,1526.9,
                 1526.9, 1520.3, 1511.9, 1501.7, 1491.7, 1516.8, 1526.1, 1541.7, 1541.7, 1530.7,
                 1518.4, 1490.6, 1479.1, 1465.4, 1409.1, 1329.5, 1302.4, 1379.2, 1520.9, 1545.6, 
                 1550.0,  1539.1, 1498.7, 1468.4],columns=['b'])

df_final=pd.concat([df_t, p1, p2], axis=1)

fig, ax1  = plt.subplots(figsize=(10,4), sharey=False, dpi=300)
t1=df_final['time'].iloc[0]
cr=[]

for i in range(0, 36, 12):
    t2=t1+relativedelta(months=i)
    t3=t1+ relativedelta(months=i+12)
    sub=df_final[(df_final.time>=t2) & (df_final.time<t3)]
    w_sub=sub['a']
    e_sub=sub['b']
    
    # 正确标准化:去均值后除以标准差,使序列方差为1
    wl = (w_sub - w_sub.mean()) / w_sub.std()
    eq = (e_sub - e_sub.mean()) / e_sub.std()
    
    # 计算未归一化互相关
    corr_raw = signal.correlate(wl, eq, mode='same', method='direct')
    # 归一化得到互相关系数:除以序列长度(适配mode='same'的有效样本量)
    corr_coeff = corr_raw / len(wl)
    
    cr.append(corr_coeff)

cc=pd.DataFrame(cr)
ccc=np.mean(cc)
lags = signal.correlation_lags(len(w_sub), len(e_sub), mode="same")
ax1.plot(lags, ccc, 'red')
ax1.set_ylim(-1, 1)  # 强制显示-1到1范围,验证结果
plt.show()

方法二:使用scipy内置归一化(scipy 1.7.0+支持)

直接利用signal.correlate的normalize参数,自动完成归一化:

# 替换互相关计算部分
corr_coeff = signal.correlate(wl, eq, mode='same', method='direct', normalize='full')

normalize='full'会用两个序列的L2范数乘积做归一化,确保结果在-1到1之间。

关键说明

  • 互相关系数的核心是归一化的互相关值,必须保证输入序列是标准化(去均值+除以标准差)的,或者对原始互相关结果做归一化处理。
  • signal.correlation_lags返回的滞后值范围是-5到6(12个点),不是你之前用的0到11,修正后才能正确对应滞后关系。

内容的提问来源于stack exchange,提问作者danial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:07:06