Как получить корреляцию между двумя временными рядами с помощью Pandas

У меня есть два набора температурных данных, которые имеют показания через регулярные (но разные) промежутки времени. Я пытаюсь получить корреляцию между этими двумя наборами данных.

Я играл с Pandas, чтобы попытаться сделать это. Я создал два временных ряда и использую TimeSeriesA.corr(TimeSeriesB). Однако, если время в двух временных сериях точно не совпадает (обычно они отличаются на секунды), я получаю в ответ Null. Я мог бы получить достойный ответ, если бы мог:

а) Интерполировать/заполнить пропущенное время в каждом TimeSeries (я знаю, что это возможно в Pandas, я просто не знаю, как это сделать)

б) удалить секунды из объектов даты и времени python (установите секунды равными 00, не меняя минуты). Я бы потерял степень точности, но не огромную сумму

c) Используйте что-то еще в Pandas, чтобы получить корреляцию между двумя временными рядами.

d) Используйте что-то в python, чтобы получить корреляцию между двумя списками поплавков, каждый из которых имеет соответствующий объект даты и времени с учетом времени.

У кого-нибудь есть предложения?


person user814005    schedule 24.06.2011    source источник


Ответы (2)


У вас есть несколько вариантов использования панд, но вы должны принять решение о том, как имеет смысл выравнивать данные, учитывая, что они не происходят в одно и то же время.

Используйте значения "на момент" времени в одном из временных рядов, вот пример:

    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» также имеет псевдоним «ffill» (но только в самой последней версии pandas на GitHub на данный момент!).

Удалите секунды из всех ваших свиданий. Лучший способ сделать это — использовать 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

Обратите внимание, что если переименование приводит к дублированию дат, будет выбрано 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. . Если .mean() не работает с объектом GroupBy, как указано выше, попробуйте .agg(np.mean)

Надеюсь это поможет!

person Wes McKinney    schedule 24.06.2011
comment
Если я правильно читаю последнюю часть, последняя часть вычисляет среднее значение для значений между 00 и 60 секундами (среднее значение для XX:XX:30, а не XX:XX:00) и присваивает результат XX:XX: 00. Простой способ обойти это будет date.replace(second=30), слишком сложный способ получить средние значения в минуту: ts_mean = seriesT.groupby(lambda date: date.replace(second=0) if date.second<30 else date.replace(second=0)+timedelta(minutes=1)).mean() - person user814005; 30.06.2011

Сдвигая временные метки, вы можете потерять некоторую точность. Вы можете просто выполнить внешнее соединение для своего временного ряда, заполнив значения NaN 0, и тогда у вас будут целые временные метки (либо общие, либо принадлежащие только одному из наборов данных). Затем вы можете выполнить функцию корреляции для столбцов вашего нового набора данных, которая даст вам результат, который вы ищете, без потери точности. Это мой код, когда я работал с временными рядами:

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

t12.corr()

Таким образом, у вас будут все временные метки.

person Elnaz Mahdi Khoshouei    schedule 07.09.2020