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

Hello, I wish to use a do until loop until the condition that there is a unique drug for each observation with some form of randomization for 3 repetitions is met.

 

data units;
do Unit = 1 to 8;
	output;
	end;
run;

 

The top shows dummy data. I will explain the overall problem that I have and how I'm trying to solve it.

 

id           Drug_1 Drug_2 Drug_3

1243
2124
3312
4412
5431
6231
7143
8324

 

In the second-fourth column, 1 shows up 2 times, 2 shows up 2 times, 3 shows up 2 times, and 4 shows up 2 times. They also do not repeat through each observation. In this example, the groups (1-4) are evenly distributed but I'd like to have the option to change their sizes depending on the condition

 

To solve this, I am trying to cycle through different seeds to be able to get the desired outcome. To accomplish this, I created two local macros. n is to cycle through seed numbers and stop is to indicate when I've obtained the desired dataset. This outcome is shown through the sum of indicator being 0 or through drug 1 - drug 3 not equal to one another.

 

 

%macro m(start);

	%local n;
	%let n=&start;

	%local stop;
	%let stop = 0;

	%do %until(stop ne 0);

			proc surveyselect data=units groups=(2,2,2,2) seed=&n reps=3 noprint
			    out=assignedUnits(rename=groupId=drug); 
			run;

			proc sort data=assignedUnits;
				by Unit;
			run;

			proc transpose data=assignedUnits out=wide1(drop=_NAME_ _LABEL_) prefix=drug_;
			    by Unit;
			    var drug;
			run;

			data desiredData;
				set wide1;
				
				indicator=.;				
				if drug_1 ne drug_2 and drug_1 ne drug_3 and drug_2 ne drug_3 then drug = 0;
					else indicator=1;
				
				st=.;
				if drug_1 ne drug_2 and drug_1 ne drug_3 and drug_2 ne drug_3 then st = 0;
					else %let stop=%eval(&stop+1);
			run;

			proc print data=desiredData;
				sum indicator;
				title "Seed number &n";
			run;

		%let n=%eval(&n+1);
	%end;
%mend m;

 

Unfortunately, the second if statement is not working. I want it to change the local variable stop to when the if statement is true but it has not been performing as desired. Is there any way to perform this?

 

1 ACCEPTED SOLUTION

Accepted Solutions
novinosrin
Tourmaline | Level 20

Nope, won't work. If i can guess, You may have to change the part of the  program to this :

data desiredData;
				set wide1 end=last;
				
				indicator=.;	
				st=.;
				if (drug_1 ne drug_2) and (drug_1 ne drug_3) and (drug_2 ne drug_3) then do;
					drug = 0;
					st = 0;
					end;
					else do; 
					indicator=1;
					end;
				sum_indicator+indicator;
      if last then do; if sum_indicator=0 then /*your call symputx goes here*/
				
			run;

 

 

View solution in original post

7 REPLIES 7
novinosrin
Tourmaline | Level 20

That is because you are trying to execute a macro statement at execution time(datastep execution). Unfortunately, that execution

%let stop=%eval(&stop+1);

happens at compile time. 

Astounding
PROC Star

I can't promise this fixes everything, but here are two items that must be changed.

 

%do %until (stop ne 0);

 

This comparison will always be true, because STOP does not refer to a DATA step variable named STOP.  Instead, you can use:

 

%do %until (&stop = 1);

 

Secondly, the DATA step cannot execute a %LET statement.  This statement is not doing anything when the DATA step executes:

 

else %let stop = %eval(&stop + 1);

 

This might be closer to what you want:

 

else call symputx('stop', '1');

 

That would assign the macro variable &STOP a value of 1, when the ELSE statement executes.

 

There may be more, but fixing this would at least be a starting point.

novinosrin
Tourmaline | Level 20

i tried to fix a bit, see if this helps:

 

%macro m(start);

	%local n;
	%let n=&start;

	%local stop;
	%let stop = 0;

	%do %until(stop ne 0);

			proc surveyselect data=units groups=(2,2,2,2) seed=&n reps=3 noprint
			    out=assignedUnits(rename=groupId=drug); 
			run;

			proc sort data=assignedUnits;
				by Unit;
			run;

			proc transpose data=assignedUnits out=wide1(drop=_NAME_ _LABEL_) prefix=drug_;
			    by Unit;
			    var drug;
			run;

			data desiredData;
				set wide1;
				
				indicator=.;	
				st=.;
				if (drug_1 ne drug_2) and (drug_1 ne drug_3) and (drug_2 ne drug_3) then do;
					drug = 0;
					st = 0;
					end;
					else do; 
					indicator=1;
					call symputX('stop',resolve('&stop')+1);
					end;
				
				
			run;

			proc print data=desiredData;
				sum indicator;
				title "Seed number &n";
			run;

		%let n=%eval(&n+1);
	%end;
%mend m;
Learning_S
Obsidian | Level 7

Thanks, that almost works. Unfortunately, it continues past seed 93 (I verified that it meets the aforementioned conditions). I read that symputX converts it to character. Am I correct in that assertion as could that be why it keeps going?

novinosrin
Tourmaline | Level 20

Oops, i missed to change this

	%do %until(stop ne 0);

to

	%do %until(&stop ne 0);

 

Learning_S
Obsidian | Level 7

I apologize, but I saw a major error in my program. The symputX('stop',resolve('&stop')+1); portion should somehow be related to the sum of the indicator variable. Would the following work?

if sum(indicator) = 0 then call symputX('stop',resolve('&stop')+1);
novinosrin
Tourmaline | Level 20

Nope, won't work. If i can guess, You may have to change the part of the  program to this :

data desiredData;
				set wide1 end=last;
				
				indicator=.;	
				st=.;
				if (drug_1 ne drug_2) and (drug_1 ne drug_3) and (drug_2 ne drug_3) then do;
					drug = 0;
					st = 0;
					end;
					else do; 
					indicator=1;
					end;
				sum_indicator+indicator;
      if last then do; if sum_indicator=0 then /*your call symputx goes here*/
				
			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
  • 7 replies
  • 2147 views
  • 5 likes
  • 3 in conversation