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.

 

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
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.

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
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.

SAS Training: Just a Click Away

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

Browse our catalog!

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