BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
panda
Quartz | Level 8

Hi - 

 

I want to write a macro for a if then command to create a series of dummy varibales, my code looks like this:

%macro change(var);
data want;
   set data;
   if Q07&var. = 4 or Q07&var. = 5 then dissatisfy&var. = 1;
   else dissatisfy&var. = 0;
run;
%mend;
%change(f);
%change(h);
%change(b);
%change(a);
%change(e);
%change(i);
%change(d);
%change(g);
%change(c);
%change(j);
%change(k);

The ideal new dummy variables woule be: dissatisfyf dissatisfyh dissatisfyb....dissatisfyk. However, when I runned this, I could just get dissatisfyk. 

Do you know what's wrong?

 

Thanks!!!

1 ACCEPTED SOLUTION

Accepted Solutions
Ron_MacroMaven
Lapis Lazuli | Level 10

1. your code creates the same data set for each macro call

that's why you get the results of only the last call.

Check your log to see:

DATA want;

q07a = ...;

DATA want;

q07b = ...;

 

2. macro  is not necessary here

learn how to use arrays

 

DATA want;

array _q (*) q07a -- q07h;*may have to list q07a q07b q07c ....;

array _d(*) disa -- dish;*names must align with above;

set data;

do _i = 1 to dim(_q);

   _d(_i) = (_d(_i)  eq 4

          or _d(_i)  eq 5);

   end;

 

Ron Fehd not always macro-needed maven

 

View solution in original post

4 REPLIES 4
Reeza
Super User

You always start from the same data set. In this case, your previous runs are not saved, only the last run.

 

data want; *-> Created new each time from data - previous data not kept;
   set data;
   if Q07&var. = 4 or Q07&var. = 5 then dissatisfy&var. = 1;
   else dissatisfy&var. = 0;
run;

 

Keep the dataset name the same or instead, use an array may simplify this a lot.  Other option is to use a format.  I would strongly recommend looking at the automated ways of creating dummy variables such as using GLMMOD. And depending on the PROC, it may handle it already, these procs would include Logistic, GLM, PHREG. 

 

data want; *-> Created new each time from data - previous data not kept;
   set want;
   if Q07&var. = 4 or Q07&var. = 5 then dissatisfy&var. = 1;
   else dissatisfy&var. = 0;
run;
PaigeMiller
Diamond | Level 26

yes, I know what is happening ... each time you run the program, you create a new data set named WANT, which erases previous data sets named WANT, and so the last time you run the program, the variable in WANT is dissatisfyk.

 

This can all be avoided by not using macros here, but instead using an ARRAY statement or two, something like (UNTESTED CODE)

 

array q07 q07a q07b q07c /* I'm not going to type them all */ ;
array dis dissatisfya dissatisfyb dissatisfyc;
do I=1 to dim(q07);
     if q07(I)=4 or q07(I)=5 then dis(I)=1; else dis(I)=0;
end;
--
Paige Miller
Ron_MacroMaven
Lapis Lazuli | Level 10

1. your code creates the same data set for each macro call

that's why you get the results of only the last call.

Check your log to see:

DATA want;

q07a = ...;

DATA want;

q07b = ...;

 

2. macro  is not necessary here

learn how to use arrays

 

DATA want;

array _q (*) q07a -- q07h;*may have to list q07a q07b q07c ....;

array _d(*) disa -- dish;*names must align with above;

set data;

do _i = 1 to dim(_q);

   _d(_i) = (_d(_i)  eq 4

          or _d(_i)  eq 5);

   end;

 

Ron Fehd not always macro-needed maven

 

Tom
Super User Tom
Super User

Just turn on the MPRINT option and look at the generated code. You will see that you keep overwriting the target dataset so only the last call has any effect. You have basically put your macro loop in the wrong place. You want to loop INSIDE of a single data step to create multiple variables in that data step.

 

But you really don't need macro code for this problem.  Just use arrays.

Let's call your input dataset HAVE instead of DATA to avoid confusion the the DATA statement.  Also let's make your new variable names using numeric suffix instead of letter suffixes to save a lot of typing.

Also we can take advantage of how SAS evaluates boolean expressions to 1 or 0 to simplify the code by replacing the IF/THEN/ELSE construct with a simple assignment statement.

 

data want;
   set have;
   array old Q07a Q07b Q07c Q07d Q07e Q07f Q07g Q07h Q07i Q07j Q07k;
   array new dissatisfy1 - dissatisfy11 ;
   do i=1 to dim(old);
     new(i) = old(i) in (4,5);
   end;
run;

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 1969 views
  • 6 likes
  • 5 in conversation