Нормализованная взаимная корреляция двух сигналов в питоне

Я хотел рассчитать нормализованную функцию взаимной корреляции двух сигналов, где оси x - это временная задержка, а оси y - значение корреляции между -1 и 1. поэтому я решил использовать scipy.

Я использую команду corr = signal.correlate(s1['Strain'], s2['Strain'], mode='full')

где s1['Strain'] и s2['Strain'] — значения кадра данных pandas, но они не возвращают нормализованную функцию с осями x в качестве временной задержки. Вот пример данных

s1:

            Strain
0        -1.587702e-22
1        -1.425868e-22
2        -1.174897e-22
3        -8.559119e-23
4        -4.949480e-23
.             .
.             .
.             .

для s2 похоже. Я знал дискретизацию обоих наборов данных, это 4096 кГц.

Спасибо за помощь.


person Malum Wolfram    schedule 20.07.2020    source источник
comment
Было бы полезно, если бы вы могли предоставить некоторые примеры данных для s1 и s2 и показать, что они возвращают, а также то, что вы ожидаете.   -  person Bill    schedule 20.07.2020


Ответы (1)


Прежде всего, чтобы получить нормализованный коэффициент (такой, что при отставании 0 мы получаем корреляцию Пирсона):

  • разделить оба сигнала на их стандартное отклонение
  • масштабировать по длине сигнала, по которому выполняется свертка (самый короткий сигнал)
out = correlate(x/std(x), y/std(y), 'full') / min(len(x), len(y))

Теперь о лагах из официальной документации correlate< /a> можно прочитать, что полный результат кросс-корреляции определяется следующим образом:

z[k] = (x * y)(k - N + 1)
     = \sum_{l=0}^{||x||-1}x_l y_{l-k+N-1}^{*}\]

Где * обозначает свертку, а k идет от 0 до ||x|| + ||y|| - 2 точно. N равно max(len(x), len(y)).

Лаги обозначены выше как аргумент свертки (x * y), поэтому они варьируются от 0 - N + 1 до ||x|| + ||y|| - 2 - N + 1, что равно n - 1 с n=min(len(x), len(y)).

Кроме того, бегло взглянув на исходный код, я думаю, что они иногда меняют местами x и y, если это удобно... (отсюда и min(len(x), len(y)) в приведенной выше нормализации. Однако это подразумевает изменение начала наших лагов, поэтому:

N = max(len(x), len(y))
n = min(len(x), len(y))

# if len(x) < (len(y):
lags = np.arange(-N + 1, n)

# else:
lags = np.arange(-n + 1, N)

Резюме

Проверьте этот код на двух временных рядах, для которых вы хотите построить взаимную корреляцию:

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import correlate

def plot_xcorr(x, y): 
    "Plot cross-correlation (full) between two signals."
    N = max(len(x), len(y)) 
    n = min(len(x), len(y)) 

    if N == len(y): 
        lags = np.arange(-N + 1, n) 
    else: 
        lags = np.arange(-n + 1, N) 
    c = correlate(x / std(x), y / std(y), 'full') 

    plt.plot(lags, c / n) 
    plt.show() 
person H. Rev.    schedule 29.09.2020