Autocorrelación y correlación cruzada en series de tiempo con C++ en Linux

Hace algún tiempo, programé en C++ un modelo autoregresivo linear de primer orden para generar elementos climáticos de temperatura máxima, temperatura mínima y radiación solar. Los valores producidos estaban “acoplados” a datos de precipitación comprendidos entre 1970 y 1994 (en total 9131 valores). Las matrices de covarianza empleadas fueron:


Para lag 0:

    1.000  0.697  0.249
    0.697  1.000 -0.192
    0.249 -0.192  1.000

Para lag 1:

    0.670  0.632  0.058
    0.532  0.700 -0.075
    0.102 -0.091  0.240 

En consecuencia, el modelo produjo 9.131 valores para cada elemento climático cuyas medias y desviaciones estándares mensuales se correspondían ajustadamente con los valores reales. Para analizar las series de tiempo en cuanto a si en realidad presentaban la autocorrelación y la correlación cruzada que sugerían las matrices de covarianza, había que quitarle las tendencias a cada una de las series de tiempo y producir residuales con media cero y varianza uno (eso para no “hacer trampa” porque los residuales podían ser grabados en un archivo aparte antes de calcular los valores diarios de las variables generadas). Me señalaron que Matlab me podría ayudar a procesar las series de residuales para encontrar los coeficientes de autocorrelación y correlación cruzada pero cuando le introduje esos “pequeños vectores” de 9.131 valores (equivalente a 25 años de registro) Matlab se “desmayó”. Ni siquiera con 10 años de registro y, finalmente, terminé probando con éxito sólo 5 años. No obstante, por más que indagué, no pude encontrar que Matlab me determinara los coeficientes de correlación cruzada para lag 1; sólo autocorrelación para lag 1 y correlación cruzada para lag 0 (me faltaban, por tanto, 6 valores). Cansado de buscar que Matlab hiciera lo que yo quería (tardé como dos días en ello) tomé la decisión de elaborar yo mismo el código en C++ (fue lo primero que debí haber hecho) y en un momento tenía todos los coeficientes de correlación cruzada calculados; incluidos los de autocorrelación como caso particular.

Aquí tenemos el código para ser ejecutado en Linux:

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

#include <math.h>

int main() {

 double x[20000], y[20000];

 int i, j, n;

 char archivo1[20], archivo2[20];

 system("ls");

 cout << "\nIntroduzca archivo primera variable = ? ";

 cin >> archivo1;

 cout << "\nIntroduzca archivo segunda variable = ? ";

 cin >> archivo2;

 cout << "\nIntroduzca numero de datos = ? ";

 cin >> n;

 ifstream label1 (archivo2);
 ifstream label2 (archivo1);

 for (i = 0; i < n; i++){

  label1 >> x[i];
  label1 >> y[i];

 }

 double mx, my, sx, sy, sxy, denom, r;

 /* Calcula la media de las dos series x[], y[] */

 mx = 0;
 my = 0;

 for (i = 0; i < n; i++){

  mx += x[i];
  my += y[i];

 }

 mx /=n;
 my /=n;

 /*Calcula el denominador */

 sx = 0;
 sy = 0;

 for (i = 0; i < n; i++){

  sx += (x[i] - mx) * (x[i] - mx);
  sy += (y[i] - my) * (y[i] - my);

 }

 denom = sqrt (sx * sy);

 /* Calcula la correlación de las series */

 int lag;

 cout << "\nlag = ?";

 cin >> lag;

 sxy = 0;

 for (i = 0; i < n -lag; i++){

  sxy += (x[i] - mx) * (y[i + lag] - my);

 }

 r = sxy /denom;

 /* r es el coeficiente de correlación (o autocorrelación)
 de la serie */

 cout.setf(ios::fixed);
 cout.precision(3);

 cout << "\nr(" << lag << ") = " << r << "\n\n";

 return 0;

}

el cual, con muy pequeñas modificaciones, corre en Windows XP usando el Dev-C++ con licencia GNU.

Aquí tenemos los resultados parciales de una ejecución en Linux Debian donde los valores de r1(3,1) = 0,100 y r1(1,3) = 0,063 concuerdan aceptablemente con los valores respectivos de 0,102 y 0,058 que se encuentran en la matriz de covarianza para lag 1.

Esta entrada fue publicada en Código C++. Guarda el enlace permanente.

6 respuestas a Autocorrelación y correlación cruzada en series de tiempo con C++ en Linux

  1. Pingback: Lenguaje R en Linux |

  2. Jose Hernandez dijo:

    en la formula de la correlacion no deberia ser
    sxy += (x[i] – mx) * (y[i + lag] – my); (cambiar el mx de la y)

    en lugar de

    sxy += (x[i] – mx) * (y[i + lag] – mx);

    • Me parece que si. Gracias por el dato. Estos son los peores errores lógicos porque dan resultados aparentemente razonables. Lo positivo es que esto sólo se usó con propósitos ilustrativos porque lo que se derivó después fue procesado con R. Ya lo corrijo.

  3. Gracias, me sirvió el ejemplo para hallar la autocorrelación de dos vectores en Qt.

  4. si lo quisiera cambiar a matlab este codigo con mexfuntion como haria para que pudiera utilizar esta funcion en matlab__

Responder

Por favor, inicia sesión con uno de estos métodos para publicar tu comentario:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s