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

I am stumped with a very simple do loop problem.  For reasons unknown, the loop logic is ignoring the equals sign I'm using so that the output is not what I need.

 

This works:

data work.retail;
input year:32. quarter:32. sales:32.;
datalines;
2007 1 921266
2007 2 1013371
2007 3 1000151
2007 4 1060394
2008 1 950268
2008 2 1028016
2008 3 999824
2008 4 957207
;;;;
run;


data work.retail2;
set work.retail;
if quarter = 1
then do;
d1 = 1;
end;
else do;
d1 = 0;
end;
if quarter = 2
then do;
d2 = 1;
end;
else do;
d2 = 0;
end;
if quarter = 3
then do;
d3 = 1;
end;
else do;
d3 = 0;
end;
run;

/* But this does not work */

%macro MakeRetail2;
data work.retail2;
set work.retail;
%do i =1 %to 3;
%if quarter = &i
%then %do;
d&i = 1;
%end;
%else %do;
d&i = 0;
%end; * end else-do;
%end; * end do-loop *;
output;
run;
%mend MakeRetail2;

%MakeRetail2

 

 

/* Any guidance would be appreciated */

1 ACCEPTED SOLUTION

Accepted Solutions
PaigeMiller
Diamond | Level 26
%if quarter = &i %then %do;

 

Here is the problem — %if cannot access the values of data set variables like QUARTER. This actually compares a text string (not the data set variable) quarter to the value of &i, and since &i is always an integer, the text string quarter is never equal to &i.

 

So, you can use arrays to eliminate the need for macros. Arrays specifically access the value of data set variables, which macro %IF cannot do. Also the resulting code is much simpler.

 

data retail2;
    set retail;
    array d d1-d3;
    do i =1 to 3;
        if quarter = i then d(i) = 1; 
        else d(i)=0;
    end;
    drop i;
run;

 

Please also note the indenting of the code makes following the code and following the looping easier, visually.

 

Lastly, there is rarely a need to create dummy variables like this. What do you plan to do with these dummy variables? Most SAS PROCs don't need dummy variables to do analyses.

 

 

--
Paige Miller

View solution in original post

10 REPLIES 10
PaigeMiller
Diamond | Level 26
%if quarter = &i %then %do;

 

Here is the problem — %if cannot access the values of data set variables like QUARTER. This actually compares a text string (not the data set variable) quarter to the value of &i, and since &i is always an integer, the text string quarter is never equal to &i.

 

So, you can use arrays to eliminate the need for macros. Arrays specifically access the value of data set variables, which macro %IF cannot do. Also the resulting code is much simpler.

 

data retail2;
    set retail;
    array d d1-d3;
    do i =1 to 3;
        if quarter = i then d(i) = 1; 
        else d(i)=0;
    end;
    drop i;
run;

 

Please also note the indenting of the code makes following the code and following the looping easier, visually.

 

Lastly, there is rarely a need to create dummy variables like this. What do you plan to do with these dummy variables? Most SAS PROCs don't need dummy variables to do analyses.

 

 

--
Paige Miller
fcolina
Fluorite | Level 6
The array approach is far simpler. Thank you for the explanation and thank you to the others that came up with answers for this problem. I really appreciate it.
PaigeMiller
Diamond | Level 26

@fcolina wrote:
The array approach is far simpler. Thank you for the explanation and thank you to the others that came up with answers for this problem. I really appreciate it.

@fcolina Next, lets address why you feel you need dummy variables ... this is rarely necessary in most SAS PROCs. Please explain why you need these dummy variables for quarter?

--
Paige Miller
Reeza
Super User
data work.retail;
	input year:32. quarter:32. sales:32.;
	datalines;
2007 1 921266
2007 2 1013371
2007 3 1000151
2007 4 1060394
2008 1 950268
2008 2 1028016
2008 3 999824
2008 4 957207
;
	;
	;
	;
run;

data work.retail2_correct;
	set work.retail;

	if quarter=1 then
		do;
			d1=1;
		end;
	else
		do;
			d1=0;
		end;

	if quarter=2 then
		do;
			d2=1;
		end;
	else
		do;
			d2=0;
		end;

	if quarter=3 then
		do;
			d3=1;
		end;
	else
		do;
			d3=0;
		end;
run;

data retail2_array;
	set retail;
	d1=0;
	d2=0;
	d3=0;
	d4=0;
	array d(*) d1-d4;
	d(quarter)=1;
run;

%macro MakeRetail2;
	data work.retail2_macro;
		set work.retail;

		%do i=1 %to 3;

			if quarter=&i
then
				d&i=1;
			else
				d&i=0;
		%end;
		* end else-do;
	run;

%mend MakeRetail2;

%MakeRetail2;

Format your code including indents as a start. 

See the two different options above. 

 

FYI - see this post plus the links below to see the different options to create dummy variables more easily. And note that if the proc supports a CLASS statement (LOGISTIC/PHREG) this isn't necessarily required at all. https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-dummy-variables-Categorical-Var...

fcolina
Fluorite | Level 6
Thank you for your reply. The array approach makes more sense than a macro.
Tom
Super User Tom
Super User

First of all don't bother to use looping when it adds no value.

data retail;
  input year quarter sales;
datalines;
2007 1 921266
2007 2 1013371
2007 3 1000151
2007 4 1060394
2008 1 950268
2008 2 1028016
2008 3 999824
2008 4 957207
;;;;

data retail2;
  set retail;
  d1=quarter=1;
  d2=quarter=2;
  d3=quarter=3;
  d4=quarter=4;
run;

If you do need to repeat a series of actions for a set of common variables the default tool to use is an ARRAY.  There is no need to use CODE GENERATION. 

data retail2;
  set retail;
  array d[4];
  do index=1 to 4;
    d[index]=quarter=index;
  end;
  drop index;
run;

If you do have a need for code generation then make sure it is generating the code you want. This macro %DO loop will generate the code in my first data step.

data retail2;
  set retail;
%do quarter=1 %to 4;
  d&quarter=quarter=&quarter;
%end;
run;
fcolina
Fluorite | Level 6
Yes thank you, I agree that the array works best.
Tom
Super User Tom
Super User

@fcolina wrote:
Yes thank you, I agree that the array works best.

With an N of 4 the wallpaper code it easier to create and understand then the DO loop.

fcolina
Fluorite | Level 6
I don't know what happened to the indents I had, they vanished when I pasted to the website.
Tom
Super User Tom
Super User

@fcolina wrote:
I don't know what happened to the indents I had, they vanished when I pasted to the website.

Use the Insert Code or Insert SAS Code button on the editor menu to get a pop-up window where you can paste text that preserve the spacing.  If you put the code into the body of your message it assumes it is paragraphs to be reflowed to fit the current browsers width.

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 10 replies
  • 1200 views
  • 0 likes
  • 4 in conversation