DATA Step, Macro, Functions and more

Macro within a Macro?

Accepted Solution Solved
Reply
Contributor bts
Contributor
Posts: 23
Accepted Solution

Macro within a Macro?

I'm having trouble with the following symputx statement. I'm looking to end up with macros for each of the 4 chi square values.

 

%macro proc_code (i);

 

ods output chisq=chia&i;

proc freq data=collapsed_values;

tables discuss_pay*gender/chisq;

where discuss_pay ne . and gender=1 or gender=2;

run;

quit;

 

  data _null_;set chia&i;

       format tmp $40.;

       if Statistic="Chi-Square" then do;

         tmp=put(prob,6.4);

         if prob <.001 then do;

           tmp= "<.001";

         end;

         if prob <.0001 then do;

           tmp= "<.001";

         end;

         if prob gt .001 then do;

           tmp=trim(catt(round(prob,.001)));

         end;

       tmp=catt("Chi-Square Results CHISQ","(",DF,")=",round(value,.01)," p",tmp);

call symputx('chi&i',tmp);

end;

   RUN;   

%mend;

 

%proc_code (1);

%proc_code (2);

%proc_code (3);

%proc_code (4);

 


Accepted Solutions
Solution
‎04-25-2016 11:56 AM
Super User
Posts: 5,099

Re: Macro within a Macro?

Taking into account everything posted so far, two small changes are needed.  You have:

 

call symputx('chi&i',tmp);

 

You would need to replace this with:

 

call symputx("chi&i",tmp, 'G');

 

This takes care of two issues.  First, macro processing skips over any text in single quotes.  So to get &i to resolve, change the single quotes to double quotes.  And second, "G" will keep the macro variables around once the macro finishes executing.

View solution in original post


All Replies
Super User
Posts: 17,960

Re: Macro within a Macro?

I don't see how this will work. 

I think your WHERE condition is incorrect, and if you're always running the same proc with the same table statement the values won't differ regardless of your i value. 

 

 

ods output chisq=chia&i;

proc freq data=collapsed_values;

tables discuss_pay*gender/chisq;

where discuss_pay ne . and gender=1 or gender=2;

run;

quit;

 

I think this is what you want

 

where discuss_pay ne . and gender in (1,2);

 

You need to change your proc freq somehow I imagine?

Contributor bts
Contributor
Posts: 23

Re: Macro within a Macro?

The proc freq works (i removed the where statement to test it) - it's the macro that doesn't. I tried a %let statement in lieu of the symputx statement, but still no go. 

Super User
Posts: 17,960

Re: Macro within a Macro?

It may work, but I don't think it's correct. 

 

 

Contributor bts
Contributor
Posts: 23

Re: Macro within a Macro?

oh i misunderstood - thank you very much for pointing that out. 

Super User
Posts: 5,260

Re: Macro within a Macro?

I Assume that mean that you need to access those macro variables outside the macro?

It's about scope. Macro variable created within a macro exist only in local scope of the macro.

You need to define them as global.

Data never sleeps
Contributor bts
Contributor
Posts: 23

Re: Macro within a Macro?

No, I don't need to access it outside the macro. After running that code, I typed %put chi1, and i got the error: 

WARNING: Apparent symbolic reference CHI1 not resolved.

Super User
Posts: 5,099

Re: Macro within a Macro?

Linus is right about that part.  Once the macro finishes, your macro variables disappear with it.  You could put this statement inside the macro instead:

 

%put &&chi&i;

 

But you will still find that &chi1 is equal to &chi2 is equal to &chi3 is equal to &chi4.  The output of PROC FREQ never changes.

Super User
Posts: 5,099

Re: Macro within a Macro?

It looks like you plan on calling the macro 4 times.  So you don't need your macro to loop through 4 executions automatically.  Rather, focus on the PROC FREQ.  Each time PROC FREQ runs, it generates exactly the same output.  You might use ODS to place that output into a different data set each time, but the output of PROC FREQ doesn't change.

 

How do you want the results of PROC FREQ to change each time you call the macro?

Contributor bts
Contributor
Posts: 23

Re: Macro within a Macro?

I have another macro variable (&var) that cycles through a list of variables to be used in the proc freq. Although I used 4 in the example I posted, there are actually 60 variables, hence 60 chi square statistics that I want outputed chi1-chi60. So I thought I could output a macro variable that represents the 60 chi-squares. 

 

 

 

%macro proc_code(var,i);

 

ods output chisq=chi&i;

proc freq data=pd.griffin_collapsed_values;

tables &var*gender/chisq;

run;

quit;

 

data _null_;set chia&i;

       format tmp $40.;

       if Statistic="Chi-Square" then do;

         tmp=put(prob,6.4);

         if prob <.001 then do;

           tmp= "<.001";

         end;

         if prob <.0001 then do;

           tmp= "<.001";

         end;

         if prob gt .001 then do;

           tmp=trim(catt(round(prob,.001)));

         end;

       tmp=catt("Chi-Square Results CHISQ","(",DF,")=",round(value,.01)," p",tmp);

call symputx('chi&i',tmp);

end;

   RUN;    

 

%mend;

%proc_code( discuss_pay,1 );

%proc_code( doc_language,2);

%proc_code( undstd_docs,3 );

%proc_code( undstd_role,4);

Contributor bts
Contributor
Posts: 23

Re: Macro within a Macro?

When I add %put &&chi&i; within the macro, it returns a value of "tmp".

Super User
Posts: 17,960

Re: Macro within a Macro?

Why a macro? Why not just run them all at once?

Whatever you're using the macro variables for later, it's probably easier if you have them all in a table.

 

ods output chisq=chi;
proc freq data=sashelp.cars;
tables (cylinders type origin)*make/chisq;
run;
quit;

data chi;
set chi;

variable = scan(table, 2, " *");
where Statistic="Chi-Square";
run;

proc print data=chi;
run;

 

Contributor bts
Contributor
Posts: 23

Re: Macro within a Macro?

Because after the chi-squares and before the macro ends, I'm creating graphs and will be putting their chi-square statistic in footnotes to each graph. 

Super User
Super User
Posts: 7,430

Re: Macro within a Macro?

Sorry, I think there is a lot of unecessary code in there.  Why are you calling the macro 4 times to start with, you get the same output for each loop as the freq is exactly the same for each call?

 

ods output chisq=chia;
proc freq data=collapsed_values;
tables discuss_pay*gender/chisq;
where discuss_pay ne . and gender=1 or gender=2;
run;
data _null_;
length tmp $40;
set chiA;
if Statistic="Chi-Square" then do;
tmp=cat("Chi-Square Results CHISQ","(",DF,")=",round(value,.01)," p",ifc(prob <.001,"<.001",strip(round(prob,.001))));
call symputx('chi',tmp);
end;
run;

This is what your code resolves to to my mind, the only thing I can't work out is why the four calls - and why these can't be put into the proc freq?  Posting test data, in the form of a datastep, and what the output should look like would help. 

Solution
‎04-25-2016 11:56 AM
Super User
Posts: 5,099

Re: Macro within a Macro?

Taking into account everything posted so far, two small changes are needed.  You have:

 

call symputx('chi&i',tmp);

 

You would need to replace this with:

 

call symputx("chi&i",tmp, 'G');

 

This takes care of two issues.  First, macro processing skips over any text in single quotes.  So to get &i to resolve, change the single quotes to double quotes.  And second, "G" will keep the macro variables around once the macro finishes executing.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 14 replies
  • 630 views
  • 2 likes
  • 5 in conversation