BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
blueskyxyz
Lapis Lazuli | Level 10
2.JPG***total number for each siteid
A  100
B  200
C  300
;

data have;
input trtn siteid $ f1 ;
cards;
1 A 10
2 A 15
3 A 25
1 B 10
2 B 15
3 B 25
1 C 10
2 C 15
3 C 25
;
run;

%let n1=100;
%let n2=200;
%let n3=300;

data pct;
	length npct $200;
	set have;
	if trtn=1 then npct=strip(put(f1,best.))||" ("||strip(put(f1/&n1*100,5.1))||")";
	if trtn=2 then npct=strip(put(f1,best.))||" ("||strip(put(f1/&n2*100,5.1))||")";
	if trtn=3 then npct=strip(put(f1,best.))||" ("||strip(put(f1/&n3*100,5.1))||")";
run;

option symbolgen mprint mlogic;
%MACRO PCT;
DATA pct;
	LENGTH NPCT $200;
	SET have;
	%*why &i=trtn is false, how to modify the code??;
	%DO i=1 %TO 3;
		%if &i=trtn %then %do;
			n=&&n&i;
			if f1>. and n>. then NPCT=strip(put(F1,best.))||" ("||strip(put(F1/n*100,5.1))||")";
		%end;
	%END;
RUN;
%MEND;
%PCT;

the result in the data step is what I want, but the macro %pct cannot work, why? how?

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

It doesn't work because the value of &I can only be the digit strings 1 ,  2 or 3 and none of those will ever equal the string trtn.

 

If you want to use a %DO loop to recreate the repetitive code in your first step then there is no need for and %IF statements.

Just replace the digit 1 with &i in the first example. Make sure to add an extra & so that you can get the value of macro variable N1 instead of the value of macro variable N.

data pct;
  length npct $200;
  set have;
%do i=1 %to 3 ;
  if trtn=&i then npct=strip(put(f1,best.))||" ("||strip(put(f1/&&n&i*100,5.1))||")";
%end;
run;

Or just eliminate the need for any looping by using the SYMGETN() function instead.

data pct;
  length npct $200;
  set have;
  npct=strip(put(f1,best.))||" ("||strip(put(f1/symgetn(cats('N',trtn))*100,5.1))||")";
run;

View solution in original post

12 REPLIES 12
blueskyxyz
Lapis Lazuli | Level 10

Sorry for my mistake,

updated as below:

 

***total number for each trtn

trtn total
1   100
2   200
3   300
;

andreas_lds
Jade | Level 19

Because you are comparing the value of macro variable i with the string trtn - which is always false, because of your definition of i. Why do you use macro-statements at all?

blueskyxyz
Lapis Lazuli | Level 10
@andreas_lds , thank you for correcting my mistake, actually I want compare the value of &i with the value of variable trtn; is there any function to get the value of variable?
Quentin
Super User

Sounds like you want to compare the value of the data step variable TRTN to a literal value that happens to come from resolving &i.

 

When you want to evaluate the value of a data step variable, you use a data step IF statement, not a macro %IF statement.

 

Thus if you change your code to:

%MACRO PCT;

%local i;
DATA pct; LENGTH NPCT $200; SET have; %DO i=1 %TO 3; if &i=trtn then do; n=&&n&i; if f1>. and n>. then NPCT=strip(put(F1,best.))||" ("||strip(put(F1/n*100,5.1))||")"; end; %END; RUN; %MEND; %PCT;

 

The code works.  Note that the macro is simply generating SAS code.  The above macro will generate:

 

DATA pct;
	LENGTH NPCT $200;
	SET have;

		if 1=trtn then do;
			n=100;
			if f1>. and n>. then NPCT=strip(put(F1,best.))||" ("||strip(put(F1/n*100,5.1))||")";
		end;

		if 2=trtn then do;
			n=200;
			if f1>. and n>. then NPCT=strip(put(F1,best.))||" ("||strip(put(F1/n*100,5.1))||")";
		end;

		if 3=trtn then do;
			n=300;
			if f1>. and n>. then NPCT=strip(put(F1,best.))||" ("||strip(put(F1/n*100,5.1))||")";
		end;

RUN;

Looking at that step showing the generated code, there are likely better ways in SAS to write this sort of lookup.  But the code is valid syntax.

 

blueskyxyz
Lapis Lazuli | Level 10
@ Quentin , thanks your post, Tom's answer has resolved my question.
Kurt_Bremser
Super User

You do not need a macro at all, as proper lookup technique is done with data step means only:

data have;
input trtn siteid $ f1;
cards;
1 A 10
2 A 15
3 A 25
1 B 10
2 B 15
3 B 25
1 C 10
2 C 15
3 C 25
;

data lookup;
input trtn n;
datalines;
1 100
2 200
3 300
;

data pct;
length npct $200;
set have;
if _n_ = 1
then do;
  declare hash lookup (dataset:"lookup");
  lookup.definekey('trtn');
  lookup.definedata('n');
  lookup.definedone();
  n = 0; * prevents "uninitialized" NOTE;
end;
if lookup.find() = 0 then npct=strip(put(f1,best.))||" ("||strip(put(f1/n*100,5.1))||")";
drop n;
run;

In place of the hash, you could also use a join or an informat created from the dataset, but the hash is the way to go for issues like this.

blueskyxyz
Lapis Lazuli | Level 10
thank yop, KurtBremser , it is a good idea to use HASH to merge with trtn, but I intent to get the value of variable (trtn) which is equal to the value of macro variable(&i)
blueskyxyz
Lapis Lazuli | Level 10
Hi KurtBremser , the answers from andreas_lds and Tom is what I really want, thanks anyway.
Tom
Super User Tom
Super User

It doesn't work because the value of &I can only be the digit strings 1 ,  2 or 3 and none of those will ever equal the string trtn.

 

If you want to use a %DO loop to recreate the repetitive code in your first step then there is no need for and %IF statements.

Just replace the digit 1 with &i in the first example. Make sure to add an extra & so that you can get the value of macro variable N1 instead of the value of macro variable N.

data pct;
  length npct $200;
  set have;
%do i=1 %to 3 ;
  if trtn=&i then npct=strip(put(f1,best.))||" ("||strip(put(f1/&&n&i*100,5.1))||")";
%end;
run;

Or just eliminate the need for any looping by using the SYMGETN() function instead.

data pct;
  length npct $200;
  set have;
  npct=strip(put(f1,best.))||" ("||strip(put(f1/symgetn(cats('N',trtn))*100,5.1))||")";
run;
blueskyxyz
Lapis Lazuli | Level 10
@Tom, thanks a lot, I prefer to use funtion symgetn.
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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 12 replies
  • 2548 views
  • 4 likes
  • 5 in conversation