SAS: create covariance matrix with variables

217 views Asked by At

I am working on a project in which we have to do some simulations. I am now at the point I want to use the RandNormal function, to generate multivariate normal data given a vector of means and a covariance matrix. For the covariance matrix, we have to use different parameters, so instead of putting the values in directly, I want to just put the variable name in the matrix (so we do not have to do the calculations by hand).

We get this error:

ERROR: (execution) Character argument should be numeric.

And this is our code. The dataset Simulatie also contains the variables defined in this proc iml.

proc iml;
    use Simulatie;
    read all;
    close Simulatie;

    sigma0sq = 2;
    sigma1sq = 3;
    sigma2sq = 1;
    sigma0 = sqrt(sigma0sq);
    sigma1 = sqrt(sigma1sq);
    sigma2 = sqrt(sigma2sq);
    rhoM = 0.7;
    rhoV = 0.5;
    rhoMsigma0sigma1 = rhoM*sigma0*sigma1;
    rhoVsigma0sigma2 = rhoV*sigma0*sigma2;
    rhoVsigma1sigma2 = rhoV*sigma1*sigma2;

    Mean = {0, 0, 0}; /* population means */

    Cov = {sigma0sq rhoMsigma0sigma1 rhoVsigma0sigma2, /* population covariances */
           rhoMsigma0sigma1 sigma1sq rhoVsigma1sigma2,
           rhoVsigma0sigma2 rhoVsigma1sigma2 sigma2sq};

    N = 185; /* sample size */
    call randseed(123);
    X = RandNormal(N, Mean, Cov); /*x is a nx3 matrix */
    SampleMean = mean(X);
    SampleCov = cov(X);
quit;

We tried putting in for instance

Cov = {3 2 1, 2 4 0,1 0 5};

Which works perfectly nice, but when we change it to variable names, it gets an error. We did some googling but couldn't find the solution, could anyone help us out :) It seems like such a silly, easy-to-fix error, but we just don't succeed!

Thanks in advance.

1

There are 1 answers

0
Rick On

The reason for your error is explained in the article "How to build a vector from expressions."

The simplest solution is to use the horizontal and vertical concatenation operators to build the matrix:

Cov = (sigma0sq || rhoMsigma0sigma1 || rhoVsigma0sigma2) //
      (rhoMsigma0sigma1 || sigma1sq || rhoVsigma1sigma2) //
      (rhoVsigma0sigma2 || rhoVsigma1sigma2 || sigma2sq);

An alternative is to allocate the 3x3 matrix and then use subscripts to assign each element:

Cov = j(3, 3, .);
Cov[1,1] = sigma0sq;
Cov[1,2] = rhoMsigma0sigma1;
Cov[1,3] = rhoVsigma0sigma2;
Cov[2,2] = sigma1sq;
Cov[2,3] = rhoVsigma1sigma2;
Cov[3,3] = sigma2sq;
/* make symmetric */
Cov[2,1] = Cov[1,2];
Cov[3,1] = Cov[1,3];
Cov[3,2] = Cov[2,3];