3

I am writing a macro that will run PROC MIXED with the level-1 residual variance fixed to a near-zero value using the PARMS statement. I am trying to generate the bulk of the starting values for the PARMS statement using SAS/IML, something like:

%macro test (dataset= , classroom= , preds= , outcome=);
proc iml;

/*count number of variables*/
    %let nvars = 0; 
    %do %while(%qscan(&preds,&nvars+1,%str( )) ne %str());
        %let nvars = %eval(&nvars+1);
    %end; 

/*determine location of level-1 residual in the start value vector*/
    %let error_location = %eval(((&nvars*(&nvars-1))/2)+&nvars+1);

/*create vector of start values from lower triangle of identity matrix*/
    start_vector = symsqr(I(&nvars));
    %let starts = %str(start_vector[label=""]); 

/*analyze data*/
    proc mixed data=&dataset noprofile method=ml;
        class &classroom;
        model &outcome = &preds /noint;
        random &preds /type=un sub=&classroom g; 
        parms 
            &starts
            .00000001 /hold= &error_location;
    run;
quit;
%mend;

The code works fine without the PARMS statement in the PROC MIXED code. When I run the code as is, however, SAS apparently puts the literal string 'start_vector[label=""]' after PARMS rather than listing the values generated by IML.

How can I avoid this error and have SAS specify the values contained in START_VECTOR as starting values for the PARMS statement?

Joe
  • 62,789
  • 6
  • 49
  • 67
John
  • 33
  • 3

2 Answers2

1

You should use the SYMPUT or SYMPUTX routines in SAS/IML to convert a vector to a macro variable.

This is one way to get a vector into a single string in a macro variable.

proc iml;
  start = {"Hi","Bye"};
  call symput("start",rowcat(start`));
  %put &start;
quit;

With a numeric vector, you need to use char to convert it:

proc iml; start_vector = j(5); call symputx("start_vector",rowcat(char(j))); %put &start_vector; quit;

With a numeric matrix, you need to use SHAPE to flatten it:

proc iml; 
    start_vector = j(5,5); 
    call symputx("start_vector",rowcat(shape(char(start_vector),1))); 
    %put &start_vector;
quit;
Joe
  • 62,789
  • 6
  • 49
  • 67
  • Thanks, Joe. I tried SYMPUT previously, but SYMPUT requires that the original data be formatted as text. Since START_VECTOR is generated as numeric, I get the following error when using SYMPUT: ERROR: (execution) Numeric argument should be character. – John Jul 30 '14 at 18:47
  • `SYMPUTX` will convert it for you (or you can convert it yourself). You might want to use `CHAR` to add a space after the numbers (or a delimter of some sort) if it squishes them up. – Joe Jul 30 '14 at 18:49
  • I used the following code but got the same error: proc iml; start_vector = symsqr(I(&nvars)); call symputx("start_vector",rowcat(start_vector`)); %put &start_vector; quit; – John Jul 30 '14 at 19:04
  • You need to get it into a single row character vector. See above for how I suggest to do so (there are lots of other ways). – Joe Jul 30 '14 at 19:21
1

Your problem and two solutions are discussed in the article "Passing values from PROC IML into SAS Procedures."

Do you have to wrap this in a macro? If so, the SUBMIT and ENDSUBMIT statements won't work, since they can't be called form a macro. However, since SAS/IML enables you to define and call modules with arguments, I usually avoid the macro language and define a module that takes arguments, then call the module directly.

Rick
  • 1,210
  • 6
  • 11