HOWTO · Python
Correlación cruzada en Python
Este artículo discutirá múltiples formas de procesar la correlación cruzada en Python.
En esta página
La correlación cruzada compara dos secuencias numéricas reales mientras una se desplaza con respecto a la otra. El resultado asigna una puntuación a cada posición relativa, lo que permite identificar dónde coinciden los patrones. De forma predeterminada, las puntuaciones son sumas de productos; no son coeficientes de correlación normalizados automáticamente.
Qué mide la correlación cruzada
Para las secuencias reales x e y, la correlación cruzada multiplica los valores que se superponen y suma los productos en cada desplazamiento. Una puntuación positiva alta indica que, en ese desplazamiento, los valores suelen tener el mismo signo y seguir un patrón similar; una puntuación negativa señala signos opuestos. La puntuación también depende de la escala de las secuencias y de cuántos valores se superponen.
El modo full incluye todos los desplazamientos con al menos un par superpuesto. Si x tiene longitud N e y tiene longitud M, se obtienen N + M - 1 puntuaciones. El modo valid conserva solo los desplazamientos en los que la secuencia más corta queda completamente dentro de la más larga. El modo same devuelve un resultado centrado respecto a la primera entrada y con su misma longitud; para longitudes pares, la convención exacta de centrado depende de la biblioteca. Estos modos seleccionan desplazamientos, no normalizan el resultado.
Calcular la correlación cruzada con Python puro
Una implementación directa hace explícitas la superposición y la convención de retardos. Para las secuencias reales x e y, el código siguiente devuelve sumas sin normalizar de los productos de los valores superpuestos. El orden de los retardos y los resultados coinciden con la convención de NumPy correlate(x, y, mode="full") para entradas reales.
Ejecuta este ejemplo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
x = [1, 2, 3]
y = [4, 5]
scores = []
for lag in range(-len(y) + 1, len(x)):
score = sum(
x[index + lag] * y[index]
for index in range(len(y))
if 0 <= index + lag < len(x)
)
scores.append(score)
print(scores)
[5, 14, 23, 12]
La secuencia contiene una puntuación por cada retardo, ordenadas desde -(len(y) - 1) hasta len(x) - 1. Cada puntuación incluye únicamente los pares de índices que se superponen. Este método sencillo resulta útil para entradas pequeñas y para entender el cálculo; el trabajo de sus bucles anidados aumenta en proporción al producto de las longitudes de las secuencias.
Usar NumPy para la correlación cruzada
Instala NumPy con python -m pip install numpy. numpy.correlate procesa matrices numéricas unidimensionales de valores reales y ofrece los modos full, same y valid. El modo predeterminado es valid, así que especifica un modo si necesitas un conjunto concreto de desplazamientos.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
import numpy as np
x = np.array([1, 2, 3])
y = np.array([4, 5])
scores = np.correlate(x, y, mode="full")
print(scores.tolist())
[5, 14, 23, 12]
Para estas entradas reales, se obtienen el mismo orden de retardos del modo full y las mismas sumas de productos sin normalizar que en el ejemplo con Python puro. NumPy conjuga la segunda entrada cuando los datos son complejos; el código anterior con Python puro no lo hace. Por eso, limita la afirmación de equivalencia a entradas reales. Convierte las matrices en listas solo si te resulta útil una representación de Python puro; para seguir trabajando con datos numéricos, las matrices de NumPy suelen ser más prácticas. Para esta comparación, las entradas deben ser reales y unidimensionales.
Usar SciPy para la correlación cruzada
Instala SciPy con python -m pip install scipy; SciPy también requiere NumPy. scipy.signal.correlate ofrece los mismos tres modos de salida y resulta útil junto con las demás herramientas de procesamiento de señales de SciPy. correlation_lags devuelve el retardo asociado a cada posición del resultado, sin necesidad de calcular los índices manualmente.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
import numpy as np
from scipy.signal import correlate, correlation_lags
x = np.array([1, 2, 3])
y = np.array([4, 5])
scores = correlate(x, y, mode="full", method="auto")
lags = correlation_lags(len(x), len(y), mode="full")
print(scores.tolist())
print(lags.tolist())
[5, 14, 23, 12]
[-1, 0, 1, 2]
De forma predeterminada, la opción method permite que SciPy elija una estrategia de cálculo; no cambia la definición de correlación solicitada. Para comparar resultados de distintas bibliotecas, mantén las mismas entradas reales y el mismo modo. Al igual que NumPy, SciPy conjuga la segunda entrada si los datos son complejos, a diferencia del código anterior con Python puro. Este ejemplo usa matrices unidimensionales de valores reales.
Interpretar los retardos y elegir un método
Con x real como primer argumento e y real como segundo, NumPy y SciPy ordenan los retardos del modo full desde -(len(y) - 1) hasta len(x) - 1. Según esta convención, un retardo positivo compara y con una parte posterior de x. Antes de interpretar un pico como un desfase temporal, comprueba siempre el orden de los argumentos y la convención de retardos de la biblioteca: si intercambias las entradas, se invierte la dirección del retardo.
Elige Python puro si quieres un cálculo de referencia sin dependencias o trabajas con secuencias pequeñas. Elige NumPy para realizar una operación compacta con matrices en código numérico. Elige SciPy si también necesitas los valores explícitos de los retardos u otras funciones de procesamiento de señales. Si las muestras están espaciadas uniformemente, convierte el índice del retardo en tiempo multiplicándolo por el intervalo de muestreo. Si necesitas un coeficiente normalizado, define la normalización por separado y ten en cuenta cuántas muestras se superponen; las puntuaciones brutas de correlación cruzada no se pueden comparar directamente cuando cambian la longitud de la superposición o la escala.
Correlación cruzada y correlación de Pandas
pandas.Series.corr calcula un único coeficiente de correlación por pares para observaciones alineadas. No desplaza una serie sobre la otra ni devuelve una puntuación para cada retardo, por lo que no es una función de correlación cruzada. Para evaluar varios retardos, usa NumPy o SciPy. Si trabajas con datos de Pandas, primero alinea las observaciones y extrae los valores numéricos de forma deliberada; después, pasa esas matrices a la implementación elegida. Debes definir explícitamente cómo tratar los índices que no coinciden y los valores ausentes.