DATA Step, Macro, Functions and more

A simple question?

Reply
N/A
Posts: 0

A simple question?

My code simplified:

%macro test;
%do i=1 %to 3;
data OUT1 OUT2 OUT3;
set IN;
select(&i);
when(1) do; if x='A' then count1+1; output out1; end;
when(2) do; if x='B' then count2+1; output out2; end;
when(3) do; if x='C' then count3+1; output out3; end;
otherwise;
run;
%end;
%mend;

x has all three values A, B and C, in data set IN.

The only counting is done when i=3, and I get the number of records with x='C' in data set IN, and I get that correctly in OUT3.

OUT1 and OUT2 have 0 observations.

This is probably a very simple mistake I've made, but I can't find it.

Susan
Contributor
Posts: 31

Re: A simple question?

Hey Susan,
the do loop is making the datasets out1 out2 out3 created for i=1 for i=2 /3 the datasets are replaced, thats why the data1 /2 is coming out as 0
for i=1
data OUT1 OUT2 OUT3;
set IN;
select(1);
when(1) do; if x='A' then count1+1; output out1; end;
when(2) do; if x='B' then count2+1; output out2; end;
when(3) do; if x='C' then count3+1; output out3; end;
otherwise;
end;
for i=2
data OUT1 OUT2 OUT3;
set IN;
select(2);
when(1) do; if x='A' then count1+1; output out1; end;
when(2) do; if x='B' then count2+1; output out2; end;
when(3) do; if x='C' then count3+1; output out3; end;
otherwise;
end;

for i=3
data OUT1 OUT2 OUT3;
set IN;
select(3);
when(1) do; if x='A' then count1+1; output out1; end;
when(2) do; if x='B' then count2+1; output out2; end;
when(3) do; if x='C' then count3+1; output out3; end;
otherwise;
end;

As you said the that the only counting is done when i=3, and you get the number of records with x='C' in data set IN, and I get that correctly in OUT3.
OUT1 and OUT2 have 0 observations. This is because the dataset OUT1/2 is getting reused by the last do loop (i=3). thats why the count1/2 =0
Trusted Advisor
Posts: 2,113

Re: A simple question?

Susan,

Sushil nailed the 'why' part of your question. You should be able to see the behavior in the SAS log. The DATA step was run three times. The first time it would have shown the proper number of observations for OUT1, the second for OUT2, and the third, as you saw, for OUT3. When trying to debug problems like this, using OPTIONS MPRINT; and looking carefully at the log can really help.

Doc
SAS Super FREQ
Posts: 8,743

Re: A simple question?

Hi:
Another good rule is that working with SAS macro programs, you should have a working SAS program to start from -- so you know where your macro variables go and so you know what output you will get given your input.

What confuses me about your program is what the desired results will be. You want 3 tables, OUT1, OUT2 and OUT3. you are creating a cumulative "count" variable -- for every value of X: COUNT1, COUNT2 and COUNT3 -- but you're not keeping X and COUNT1 in OUT1, X and COUNT2 in OUT2, etc. So I'm not sure what you want in your final output.

cynthia

Here's a question. Given this data, what would you expect to see in OUT1 for example???
[pre]
X NUM
A 111
B 222
C 333
A 444
B 555
C 666

***********
Possible desired results OUT1:
X NUM COUNT1
A 111 1
A 444 2
[/pre]
N/A
Posts: 0

Re: A simple question?

Possible desired results OUT1:
X NUM COUNT1
A 111 1
A 444 2

Yes, that's what I wanted.

**************************************

DATA OUT&i.;

Susan
SAS Super FREQ
Posts: 8,743

Re: A simple question?

I guess, then, that I don't understand where the need for the macro do loop comes in. A select/when test on X get you those results without using a macro program. I can understand how you might want to run this program more times or make it more generic, but I think that something like this will give you the desired results.

cynthia
[pre]
data IN;
infile datalines;
input x $ num;
return;
datalines;
A 111
A 444
B 222
B 555
C 333
C 666
;
run;

data OUT1(keep=x num count1)
OUT2(keep=x num count2)
OUT3(keep=x num count3);
set IN end=eof;
select(x);
when('A') do; count1+1; output out1; end;
when('B') do; count2+1; output out2; end;
when('C') do; count3+1; output out3; end;
otherwise;
end;
run;

proc print data=out1;
title 'out1';
run;

proc print data=out2;
title 'out2';
run;

proc print data=out3;
title 'out3';
run;
[/pre]
N/A
Posts: 0

Re: A simple question?

As I said: My code is simplified.

And it's very much simplified.

When I have a question I try to narrow the description of the real case, and concentrate on the main issue.
SAS Super FREQ
Posts: 8,743

Re: A simple question?

Hi:
I know what you mean. Sometimes macro programs can get very complicated, very fast.

My overall approach would be somewhat different, rather than hard-code OUT1, OUT2 and OUT3 or A, B and C in the DATA step, I'd let macro logic take care of the values of X based on the values of &I. I'd probably use an approach like shown below, which would allow me to increase the size of the %DO loop without changing the data set names or the SELECT.

Of course, you may have considered this design already and rejected it because of the other programming you need to do, but I thought this possibility worth posting in case other folks have a simlar question and only need the simpler approach.

cynthia
[pre]
data IN;
infile datalines;
input x $ num;
return;
datalines;
A 111
A 444
B 222
B 555
C 333
C 666
;
run;

%macro test;
%do i=1 %to 3;

%if &i = 1 %then %do; %let want=A; %end;
%else %if &i = 2 %then %do; %let want=B; %end;
%else %if &i = 3 %then %do; %let want=C; %end;

data OUT&i;
set IN;
if x = "&want" then do;
count&i + 1;
output out&i;
end;
run;

proc print data=out&i;
title "Out&i Data and Count Test for X: &want";
run;

%end;
%mend;

options mprint symbolgen;
%test;
[/pre]
Ask a Question
Discussion stats
  • 7 replies
  • 176 views
  • 0 likes
  • 4 in conversation