BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Jay_95
Calcite | Level 5

The proc surveyreg works but I am trying to avoid typos and wanted a macro that would run multiple regression models using cycling through each outcome - exposure pair. Specifically, I need the ls mean estimations. The exposures are not mutually exclusive.  This is similar to some other questions but need some help with errors, the model is not specified correctly.

 

 

%macro sup4(outcome, exposure);

   %do i=1 %to 9;

     %do k=1 %to 7;

          proc surveyreg data=lib_sup.data_sup;

          weight var1;

          cluster var2;

          strata var3;

          class &exposure&k;

          model  &outcome&i = var4 var5 var6 &exposure&k;

          lsMEANS &exposure&k;

     %end;

   %end;

%mend;

%let index = oc_a oc_b oc_c oc_d oc_e oc_f oc_g oc_h oc_i ;

%let exposure = ex1 ex2 ex3 ex4 ex5 ex6 ex7;

%sup4 ;

 

It would also be great to get help with creating a table of the ls means output indicating the corresponding outcome and exposure pair.

Many thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

Something along these lines is what I think you are looking for. This explicitly defines the parameter for the macro and shows how to call with multiple space delimited variable names for each but not all. Obviously this is not tested as I do not have your data. This will call every outcome with every exposure in the two lists.

What goes on: %sysfunc allows calling of datastep functions (with care and some caveats as to which) so we can use Countw to get how many elements are in the list.

%Scan will extract the i-th or k-th member of the list into new outcome/exposure variables for use in the procedure call. Note that I added a Title statement so you can tell which output is which a bit more clearly.

 

If you are going to attempt macro coding here is a general rule to memorize: ALWAYS know and specify where a Procedure ends and end it properly in the code with RUN or QUIT statements as needed. One of the purposes of macro coding is to conditionally include generated code. If you do not know and properly end procedures I promise that at sometime in the future you will be trying to figure out why you are getting errors where some Proc XXXX code lines ended up in the middle of Proc YYYY. Or why the "last" iteration of a loop did not execute as expected.

 

%macro sup4(outcomelist=, exposurelist=);
   %do i=1 %to %sysfunc(countw(&outcomelist.));
     %let outcome= %scan(&outcomelist.,&i.);
     %do k=1 %to %sysfunc(countw(&exposurelist.));
          %let exposure= %scan(&exposurelist.,&k.);

          proc surveyreg data=lib_sup.data_sup;
             title "Outcome=&outcome. Exposure=&exposure";
             weight var1;
             cluster var2;
             strata var3;
             class &exposure.;
             model  &outcome. = var4 var5 var6 &exposure.;
             lsMEANS &exposure.;
          run; title;
     %end;
   %end;

%mend;


%sup4 (outcomelist= oc_a oc_b , exposurelist=ex1 ex2 );

View solution in original post

6 REPLIES 6
ballardw
Super User

You don't state what is going wrong very well.

 

You should include at least one example of the code that worked without any macro variables and indicate which variable names relate to exposure and outcome.

 

Have  you run your code with OPTIONS MPRINT; set? That will show errors in closer proximity to the code generated.

 

Generic note: This did not set any parameters for the macro and shows an incomplete call to the macro.

%let index = oc_a oc_b oc_c oc_d oc_e oc_f oc_g oc_h oc_i ;

%let exposure = ex1 ex2 ex3 ex4 ex5 ex6 ex7;

%sup4 ;

A call to your macro would look like:

%sup4(oc_a oc_b oc_c oc_d oc_e oc_f oc_g oc_h oc_i, ex1 ex2 ex3 ex4 ex5 ex6 ex7);

You did not provide anything for parameter.

 

Writing fixed number of loops %do i=1 to 9 is poor macro practice. You can get the number of elements in space delimited list with %sysfunc(countw(&outcome.)) and then use a loop such as

%do i=1 %to %sysfunc(countw(&outcomes.));
Jay_95
Calcite | Level 5

Thank you for the guidance.

 

For example, this code works with the data:

          proc surveyreg data=lib_sup.data_sup;

          weight var1;

          cluster var2;

          strata var3;

          class ex1;

          model  oc_a = var4 var5 var6 ex1;

          lsMEANS ex1k;

 

oc_a is the outcome 

ex1 is the exposure of interest needing ls mean estimates

 

Obviously “&exposure&k” and “&outcome&I” are not correctly stated. I would like to have the next variable in the list indicated in the model. I am in over my head and appreciate the help.

 

Here is the current error:

NOTE 137-205: Line generated by the invoked macro "SUP4".

1     proc surveyreg data=lib_sup.data_sup; weight var1; cluster var2; strata var3; class

1  ! &exposure&k; model &outcome&I.= var4 var5 var6 &exposure&k.; lsMEANS &exposure&k;

                                                                     22

ERROR 22-322: Syntax error, expecting one of the following: a name, ;, (, *, -, /, :, @, _CHARACTER_,

              _CHAR_, _NUMERIC_, |.

ballardw
Super User

Something along these lines is what I think you are looking for. This explicitly defines the parameter for the macro and shows how to call with multiple space delimited variable names for each but not all. Obviously this is not tested as I do not have your data. This will call every outcome with every exposure in the two lists.

What goes on: %sysfunc allows calling of datastep functions (with care and some caveats as to which) so we can use Countw to get how many elements are in the list.

%Scan will extract the i-th or k-th member of the list into new outcome/exposure variables for use in the procedure call. Note that I added a Title statement so you can tell which output is which a bit more clearly.

 

If you are going to attempt macro coding here is a general rule to memorize: ALWAYS know and specify where a Procedure ends and end it properly in the code with RUN or QUIT statements as needed. One of the purposes of macro coding is to conditionally include generated code. If you do not know and properly end procedures I promise that at sometime in the future you will be trying to figure out why you are getting errors where some Proc XXXX code lines ended up in the middle of Proc YYYY. Or why the "last" iteration of a loop did not execute as expected.

 

%macro sup4(outcomelist=, exposurelist=);
   %do i=1 %to %sysfunc(countw(&outcomelist.));
     %let outcome= %scan(&outcomelist.,&i.);
     %do k=1 %to %sysfunc(countw(&exposurelist.));
          %let exposure= %scan(&exposurelist.,&k.);

          proc surveyreg data=lib_sup.data_sup;
             title "Outcome=&outcome. Exposure=&exposure";
             weight var1;
             cluster var2;
             strata var3;
             class &exposure.;
             model  &outcome. = var4 var5 var6 &exposure.;
             lsMEANS &exposure.;
          run; title;
     %end;
   %end;

%mend;


%sup4 (outcomelist= oc_a oc_b , exposurelist=ex1 ex2 );
Jay_95
Calcite | Level 5

This runs perfectly and your explanations are really helpful. I greatly appreciate your assistance 

ballardw
Super User

I missed the request for the LSMEANS output to a data set.

You can get one for each pair by adding

 

ODS OUTPUT LSMEANS= LS_&exposure._&Outcome ;

in the body of the proc surveyreg code. This will create datasets with names like LS_ex1_oc1. Possible concern if using other variable names is if the total number of characters in the exposure and outcome exceed 28 characters then with the LS and the two underscore characters the result will exceed the 32 character limit of data set names.

 

If you add options to the LSMEANS statement of E (table Coef), DIFF or Adjust=, Stepdown  (table Diffs) or Lines (table LSMLINES) then additional tables will need to be captured to hold the additional output.

Jay_95
Calcite | Level 5

Again, codes works as expected. Again, thank you for your help. 

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
What is ANOVA?

ANOVA, or Analysis Of Variance, is used to compare the averages or means of two or more populations to better understand how they differ. Watch this tutorial for more.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 6 replies
  • 473 views
  • 0 likes
  • 2 in conversation