如何使用Pandas计算两个时间序列的相关性

16 投票
2 回答
27898 浏览
提问于 2025-04-16 20:13

我有两组温度数据,它们的记录时间间隔不一样,但都是定期的。我想找出这两组数据之间的相关性。

我一直在尝试使用Pandas来实现这个目标。我创建了两个时间序列,并使用了TimeSeriesA.corr(TimeSeriesB)来计算相关性。不过,如果这两个时间序列的时间不完全匹配(通常相差几秒),我得到的结果就是Null。如果我能做到以下几点,就能得到一个不错的结果:

a) 在每个时间序列中插入或填补缺失的时间(我知道在Pandas中可以做到这一点,只是不知道怎么做)

b) 从Python的datetime对象中去掉秒数(把秒数设为00,但不改变分钟)。这样我会失去一些精确度,但影响不大

c) 在Pandas中使用其他方法来计算两个时间序列之间的相关性

d) 使用Python中的其他方法来计算两组浮点数的相关性,每个浮点数都有一个对应的datetime对象,并考虑到时间的因素。

有没有人有好的建议?

2 个回答

2

通过调整你的时间戳,你可能会失去一些准确性。你可以对你的时间序列进行外连接,这样可以把NaN值填充为0,这样你就能得到所有的时间戳(无论是共享的还是只属于某一个数据集的)。接下来,你可能想对新数据集的列进行相关性计算,这样就能得到你想要的结果,而且不会失去准确性。这是我在处理时间序列时写的代码:

t12 = t1.join(t2, lsuffix='_t1', rsuffix='_t2', how ='outer').fillna(0)

t12.corr()

这样你就能得到所有的时间戳了。

18

你可以用pandas做很多事情,但你需要决定如何对齐数据,因为它们并不是在同一时刻发生的。

使用某个时间序列中的时间点的“当时”值,这里有个例子:

    In [15]: ts
    Out[15]: 
    2000-01-03 00:00:00    -0.722808451504
    2000-01-04 00:00:00    0.0125041039477
    2000-01-05 00:00:00    0.777515530539
    2000-01-06 00:00:00    -0.35714026263
    2000-01-07 00:00:00    -1.55213541118
    2000-01-10 00:00:00    -0.508166334892
    2000-01-11 00:00:00    0.58016097981
    2000-01-12 00:00:00    1.50766289013
    2000-01-13 00:00:00    -1.11114968643
    2000-01-14 00:00:00    0.259320239297



    In [16]: ts2
    Out[16]: 
    2000-01-03 00:00:30    1.05595278907
    2000-01-04 00:00:30    -0.568961755792
    2000-01-05 00:00:30    0.660511172645
    2000-01-06 00:00:30    -0.0327384421979
    2000-01-07 00:00:30    0.158094407533
    2000-01-10 00:00:30    -0.321679671377
    2000-01-11 00:00:30    0.977286027619
    2000-01-12 00:00:30    -0.603541295894
    2000-01-13 00:00:30    1.15993249209
    2000-01-14 00:00:30    -0.229379534767

你可以看到这些数据相差了30秒。reindex这个函数可以帮助你对齐数据,同时向前填充值(获取“当时”的值):

    In [17]: ts.reindex(ts2.index, method='pad')
    Out[17]: 
    2000-01-03 00:00:30    -0.722808451504
    2000-01-04 00:00:30    0.0125041039477
    2000-01-05 00:00:30    0.777515530539
    2000-01-06 00:00:30    -0.35714026263
    2000-01-07 00:00:30    -1.55213541118
    2000-01-10 00:00:30    -0.508166334892
    2000-01-11 00:00:30    0.58016097981
    2000-01-12 00:00:30    1.50766289013
    2000-01-13 00:00:30    -1.11114968643
    2000-01-14 00:00:30    0.259320239297

    In [18]: ts2.corr(ts.reindex(ts2.index, method='pad'))
    Out[18]: -0.31004148593302283

注意,'pad'这个选项在最新版本的pandas中也可以用'ffill'来表示!

去掉所有日期时间中的秒数。最好的方法是使用rename

    In [25]: ts2.rename(lambda date: date.replace(second=0))
    Out[25]: 
    2000-01-03 00:00:00    1.05595278907
    2000-01-04 00:00:00    -0.568961755792
    2000-01-05 00:00:00    0.660511172645
    2000-01-06 00:00:00    -0.0327384421979
    2000-01-07 00:00:00    0.158094407533
    2000-01-10 00:00:00    -0.321679671377
    2000-01-11 00:00:00    0.977286027619
    2000-01-12 00:00:00    -0.603541295894
    2000-01-13 00:00:00    1.15993249209
    2000-01-14 00:00:00    -0.229379534767

注意,如果使用rename后出现重复的日期,会抛出一个Exception错误。

如果你想做一些稍微复杂的事情,假设你想计算每分钟的平均值(当你每秒有多个观察值时):

    In [31]: ts_mean = ts.groupby(lambda date: date.replace(second=0)).mean()

    In [32]: ts2_mean = ts2.groupby(lambda date: date.replace(second=0)).mean()

    In [33]: ts_mean.corr(ts2_mean)
    Out[33]: -0.31004148593302283

如果你没有从https://github.com/wesm/pandas获取最新的代码,这些最后的代码片段可能无法正常工作。如果在GroupBy对象上.mean()不工作,可以试试.agg(np.mean)

希望这些对你有帮助!

撰写回答