BookmarkSubscribeRSS Feed
Ruhi
Obsidian | Level 7

 

 

My data set includes a variable name with values such as  ("aaa","abc","ccc".......) . In my macro I have to call first data set dsn1 and extract some rows of data from that and later create macro variable using symput and then use those macro variables in another dataset to calculate my stats. I dont know the right way to work with macro variable lists . Your help is very appreciated.

Thanks.

%macro fade(dsn1,dsn2,id, location);


%do i=1 %to %countw(&id);
	%do j = 1 %to %countw(&location);
		data _null_;
 		set &dsn1 (where= (id=%qscan(&id,&i) and ldmk=%scan(&ldmk,&j); 
				%if extreme= "max" %then call symput('maxtime', time);
  				%if extreme= 'min' %then call symput('mintime', time);
	        	run;
data abd;
set dsn2;
some more codes....;
run;

          %end;
     %end; 
%mend;
%fade(aa,bb,id="aaa" "abc" "ccc", location="f1" "f2" "f3");
8 REPLIES 8
PaigeMiller
Diamond | Level 26

Did you look at the LOG? What does it say? Does it tell you that there is no %COUNTW function in SAS?

 

That's the problem! (One of the problems)

 

I suggest you first get working code without macros and without macro variables for one or two of the datasets and one or two of the variable names. If you don't have working SAS code without macros and without macro variables, you will not get the code to work with macro variables, this is impossible. If you do have working SAS code without macros and without macro variables, then creating a working macro will be much easier.

--
Paige Miller
Ruhi
Obsidian | Level 7

I actually modified the code to put here. I used a actual number of variables in my code but what I dont know is how to assign the variable list in sas macro, so it can scan values of that variable one by one as do loop loops. 

 

Also when for trial purposes when I was trying this code out of macro with just %let commands I am still getting errors. even at this following point. 

581  %let location = "L1" "L2";
ERROR: Open code statement recursion detected.

 

 

 

SASKiwi
PROC Star

There is nothing wrong with the posted statement, assuming 581 is just a line number, your problem lies elsewhere. If you want further help please post the complete log.

PaigeMiller
Diamond | Level 26

@Ruhi wrote:

I actually modified the code to put here. I used a actual number of variables in my code but what I dont know is how to assign the variable list in sas macro, so it can scan values of that variable one by one as do loop loops. 

 

Also when for trial purposes when I was trying this code out of macro with just %let commands I am still getting errors. even at this following point. 

581  %let location = "L1" "L2";
ERROR: Open code statement recursion detected.

 


Seems like you haven't addressed my questions or the points I made. Did you look at the log for the code you posted? What does it say? (or if the code you posted is code you didn't actually run, then why?)


Did you try to write the base SAS code without macros first for one or two situations/datasets/variables and get that to work? If you can't get that to work, then your macro will never work.

--
Paige Miller
Ruhi
Obsidian | Level 7

 


 


Obs year id ldmk side cycle extreme time
1 2013 BZ01 L1 L 1 max 436
2 2013 BZ01 L1 L 1 min 567
3 2013 BZ01 L1 L 2 max 697

4 2013 BZ01 L1 L 2 min 821

5 2013 BZ01 L1 L 3 max 946

%macro forceL(d1,d2,id, year,ldmk, side, cycle);

data _null_;
 set &d1 ;
 where (id=&id and ldmk=&ldmk) & (side=&side & cycle = &cycle);
  if extreme= "max" then call symput('maxtime', time);
  if extreme= 'min' then call symput('mintime', time);
  run;

data force1;
set &d2 (where = (( ltime ge &maxtime and ltime le &mintime) & (id = &id  and ldmk=&ldmk))) ;
	disp=0 ; force=0 ; velocity=0 ; acc=0;
	if _n_ = 1 then baseZ = Ldisp ;
	if _n_ = 1 then baseF = Lforce  ;
	Retain baseZ basef;
  	if _n_ > 1 then  disp= BaseZ - Ldisp ;
	if _n_ > 1 then   force=Lforce-baseF;
        if _n_ > 1 then velocity = (dif(disp)/dif(Ltime))*100 ;
	if _n_ > 2 then acc = (dif(velocity)/dif(Ltime))*100;
run;

*more sas codes to calculate required stats;
%mend;


Let me try again to explain my problem.I have two datasets, d1, d2 and I pasted head of d1 here. I have to extract the information of time from d1, for the combinations of id, ldmk, year, side, cycle and use that information to extract rows from d2 data and run some stats on those subsets of datasets, but I have a large number of combinations of columns in d1 and I am trying to programmatically do that. Else I have to make so many macro calls. and in the macro I pasted here, this works only when values of id are passed such as "BZ01" , ldmk as"L1" and so on as all are character variable except cycle and time. 

 

So I was trying to test a piece of code to extract the id, ldmk , side year combination in one go, but I am failing. Can you please suggest the correct way to extract the information in do loop ?

 

I tried following codes in a small dataest to extract relevant rows of data and I am failing.

%let id="BZ01" "BZ02";
%let side="L";
%let ldmk= "L1" "L2";

data p;
set endpts;
where ((id=%qscan(%bquote(&id),2) and ldmk=%qscan(%bquote(&ldmk),2))) and (year="2013" and side="L"));
RUN;

Log 

 

582 data p;
583 set endpts;
584 where ((id=%qscan(%bquote(&id),2) and ldmk=%qscan(%bquote(&ldmk),2))) and (year="2013" and
584! side="L"));
NOTE: Line generated by the macro function "QSCAN".
2 "BZ02"
-
22
76
ERROR: Syntax error while parsing WHERE clause.
ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string,
a numeric constant, a datetime constant, a missing value, (, *, +, -, :, INPUT,
NOT, PUT, ^, ~.

ERROR 76-322: Syntax error, statement will be ignored.

585 RUN;

 

Tom
Super User Tom
Super User

Why are you not just merging D1 and D2 and then filtering the result based the criteria you are using to filter D1?

Why do you need to go about pulling values out datasets and into macro variables?

 

If the join criteria is complex then perhaps an SQL join would be better suited than a data step with a MERGE statement.

 

Note that if you want to test if variable has any one of a list of values then use the IN operator.

 

Is this what you are trying to do?

%let id="BZ01" "BZ02";
%let side="L";
%let ldmk= "L1" "L2";
...
where (id in (&id))
  and (ldmk in (&ldmk))
  and (year in ("2013"))
  and (side in (&side))
;
...

Or did you mean to somehow pair the values of ID with the values of LDMK ( L1 with BZ01 and L2 with BZ02) and then select if either pair was matched?

where
    (  (id = %scan(&id,1,%str( ),q))
  and (ldmk = %scan(&ldmk,1,%str( ),q))
  and (year in ("2013"))
  and (side in (&side))
  )  
  or (  (id = %scan(&id,2,%str( ),q))
  and (ldmk = %scan(&ldmk,2,%str( ),q))
  and (year in ("2013"))
  and (side in (&side))  
  )
;
Tom
Super User Tom
Super User

Why not use BY groups in your calculation data step so that you can calculate DISP, FORCE, ACC, VELOCITY etc in one data step for all of the groups of data?

 

Instead of using (_N_=1) in your logic you could use a FIRST. variable to test when a new group starts?

Tom
Super User Tom
Super User

Your posted code doesn't make much sense.

 

For example consider this %IF statement

%if extreme= "max" %then call symput('maxtime', time);

The condition being test can never be true.  The 7 letters |extreme| will never equal the five characters |"max"|.

And even if it did and the %IF statement generated the code 

call symput('maxtime', time)

you haven't included a semi-colon to end that data step statement.

 

Can you explain what the purpose of the macro is?

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 8 replies
  • 1085 views
  • 1 like
  • 4 in conversation