Passing element of the array (which refers to variable in dataset) to macro

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 7
Accepted Solution

Passing element of the array (which refers to variable in dataset) to macro

[ Edited ]

I have a macro that produces some special graphs by taking as input names of two variables from the dataset.

  

Let's say I have two variables in the dataset: Age, Date, LoanBig, LoanSmall. In reality there are many more of these.

 

I can run the macro as follows:

 

%dograph(Age,LoanBig), etc

 

But I want to loop through these variables instead. So I created the array:

 

data summary;

set summary;

array myarray1(2) Age Date;

array myarray2(2) LoanSmall LoanBig;

 

*The following does not work. the error says that the variable myarray1 can not be found

%dograph(myarray1(1),LoanSmall);

 

*The following test works. It creates the variable in the dataset called "temp" that is a copy of the variable Age

 

temp = myarray1(1)

 

*Eventually I want to loop through  these. But for now it does not even work with actual index.

run;

 

 


Accepted Solutions
Solution
‎04-25-2018 02:09 PM
SAS Employee
Posts: 24

Re: Passing element of the array (which refers to variable in dataset) to macro

Just created some sample data to work with here:

data temp;
   input var1 var2 var3 ;
datalines;
1  1  1
2  4  8
3  9 27
4 16 64
;
run;

and a simple macro that creates a scatterplot:

%macro graphthis(xaxis,yaxis);
   proc sgplot data=temp;
      scatter x=&xaxis y=&yaxis;
   run;
%mend;

 

Now, if you can write out your variables in a list, then store them in macro variables

%let xs = var1;
%let ys = var2 var3;

and loop through the macro variables like so:

%macro loopthrough();
   %do i=1 %to %sysfunc(countw(&xs));
      %do j=1 %to %sysfunc(countw(&ys));    
         %let x&i = %scan(&xs, &i, %str( ));
         %let y&i = %scan(&ys, &j, %str( ));
         %graphthis(&&x&i, &&y&i);
      %end;
   %end;
%mend;

options mprint mlogic symbolgen;

%loopthrough();

View solution in original post


All Replies
Valued Guide
Posts: 534

Re: Passing element of the array (which refers to variable in dataset) to macro

We'll need to know a lot more about what your macro dograph is all about. Also, when you mention it doesn't work, what are the messages you get? Some log and code would help.

 

But assuming it does something like proc sgplot or proc plot than it's not a surprise you get problems. Inside a datastep you cannot run another proc.

 

But ultimately we'll need code and log to be certain. Please show us what you've done sofar and give us a good idea of what you were expecting / hoping to achieve.

 

Regards,

- Jan,.

Occasional Contributor
Posts: 7

Re: Passing element of the array (which refers to variable in dataset) to macro

Posted in reply to jklaverstijn

Thank you. Please see my reply below. I am actually able to use this macro from within the data step when passing the variable names directly. I just can not do this when referencing an item in the array. I want to run this macro through a loop, but I do not want to change the macro. It is currently being used by hard calling it with different variable combinations over 40 rimes.

Super User
Posts: 13,583

Re: Passing element of the array (which refers to variable in dataset) to macro

We would need the actual code of the macro to address why it works/does not work.

As well as a description of what the macro is supposed to actually accomplish.

 

First likely issue: ARRAYS are not permanent objects in a data set. Once the data step completes the array object no longer exists. So you cannot reference an array element in the manner you are attempting.

 

A typical approach is to pass the list of variables as a single parameter and then parse the list and build code using the name(s) selected from the parameter.

 

A somewhat less macro driven approach is to use a data step to create call execute statements that generate the code needed.

 

 

Occasional Contributor
Posts: 7

Re: Passing element of the array (which refers to variable in dataset) to macro

[ Edited ]

Regarding the likely issue being that arrays are not permanent object and can not be referred to after the data step completes: I am not using the array outside the datastep. I am only using it within the datastep. Also, within the datastep I can do

temp = myarray1(1);

and I can do

%dograph(Age,LoanSmall);

But I can not do:

%dograph(myarray1(1),LoanSmall);

 

The macro produces some formatted png image files with standardized naming to be read into the Latex document. Before doing that it also collapses the data by some appropriate averages according to the first argument passed (either Age or Date). There will be many douzens of these image files, and the macro will be called from many different parts of the code. Right now somebody is using this code by copying and pasting hardcoded macro calls with actual variable names about 40 times. "%dograph(Age,LoanSmall), %dograph(Age,LoanLarge), etc. In reality there are many more loan types.

 

For now, I just want a way of looping through the variables for the first and second argument. below I will put a stripped down version of the macro. As I mentioned, the macro itself works when called like this:

%dograph(Age,LoanSmall);

The short version of the macro. It is possible that this macro can be streamlined and improved. But it is being used successfully in production for a while and does work when calling directly with variable names. I do not want to change the macro - it is not mine. I just want to be able to call it as a loop, the way I can do it in STATA, R, Matlab and many other languages.

 

%macro dograph(AgeorDate,loantype);

 

data subset;

set summary;

run;

 

PROC FORMAT;

VALUE genderval  0="All"

                 1="Couple"

                 2="Male"

                3="Female";

RUN;

 

data subset0;

set subset;

if female=1 then gender = 3;

if male = 1 then gender = 2;

if couple = 1 then gender = 1;

FORMAT gender genderval.;

LABEL smm = "SMM";

LABEL loanage = "Loan Age in Months";

run;

 

data subsets;

set subset0;

gender = 0;

run;

 

proc datasets;

append base= subsets

data= subset0;

 

Proc sort data= subsets;

by gender &AgeorDate ;

run;

 

proc means data= subsets noprint;

var smm fit;

by gender &AgeorDate;

weight _weight_;

output out=lalas;

run;

 

data lalas;

set lalas;

if _STAT_='MEAN';

run;

 

goptions reset=index device=png gsfname=graphout;

 

ods graphics on /

     width = 5.25in

     outputfmt= png

     imagemap = on

     reset =  index

     imagename="IJMy_&AgeorDate"

     border=off;

 

ods listing gpath="/sasmart/zkydmjo/IJGraph";

  

 ods graphics on / width=6.75in height=5.25in;

 

 PROC SGPANEL DATA=lalas;

 PANELBY gender /SPACING=3 novarname;

 series y=smm x=&AgeorDate /

              MARKERS MARKERATTRS = (SYMBOL = CircleFilled COLOR = black SIZE = 5)

               LINEATTRS = (COLOR = black PATTERN = SOLID);

 series y=fit x=&AgeorDate /

              MARKERS MARKERATTRS = (SYMBOL = circle COLOR = green SIZE = 5)

               LINEATTRS = (COLOR = green PATTERN = SOLID);

 COLAXIS grid;

 ROWAXIS grid;

 RUN;

 

 ods listing close;

 

%mend dograph;

Super User
Super User
Posts: 8,120

Re: Passing element of the array (which refers to variable in dataset) to macro

When you run a macro the TEXT that it generates is then interpreted by SAS as if the original program contained that text.

So if you have a macro that generates a data or proc step.

%macro dograph;
  proc plot .....
%mend ;

And you call that macro in the middle of defining a data step.

data test;
   ...
  %dograph;
   ...
run;

Once the macro processors finishes its pre-processing what SAS sees is a program that looks like.

data test ;
   ...
   proc plot;
       ...
  ...
run;

So the definition of your data step is truncated as soon as you start to try to run another step.

Solution
‎04-25-2018 02:09 PM
SAS Employee
Posts: 24

Re: Passing element of the array (which refers to variable in dataset) to macro

Just created some sample data to work with here:

data temp;
   input var1 var2 var3 ;
datalines;
1  1  1
2  4  8
3  9 27
4 16 64
;
run;

and a simple macro that creates a scatterplot:

%macro graphthis(xaxis,yaxis);
   proc sgplot data=temp;
      scatter x=&xaxis y=&yaxis;
   run;
%mend;

 

Now, if you can write out your variables in a list, then store them in macro variables

%let xs = var1;
%let ys = var2 var3;

and loop through the macro variables like so:

%macro loopthrough();
   %do i=1 %to %sysfunc(countw(&xs));
      %do j=1 %to %sysfunc(countw(&ys));    
         %let x&i = %scan(&xs, &i, %str( ));
         %let y&i = %scan(&ys, &j, %str( ));
         %graphthis(&&x&i, &&y&i);
      %end;
   %end;
%mend;

options mprint mlogic symbolgen;

%loopthrough();
Occasional Contributor
Posts: 7

Re: Passing element of the array (which refers to variable in dataset) to macro

Posted in reply to antonbcristina

Thank you! This indeed accomplished what I was trying to do!

☑ This topic is solved.

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

Discussion stats
  • 7 replies
  • 183 views
  • 2 likes
  • 5 in conversation