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

Hello everybody, 

 I have a problem while using macro in SAS. I have the table like this:

ID    begin 1     begin 2    begin 3     begin 4      end 1     end 2    end 3      end 4     end_A

Now I want to use macro like this:

 %do i = 1 %to &e;

 %if end_A > end&i %then %do %until (end_A > end&i) AND (begin(&i+1) <=end&i);

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

%end;

But I don't know how to write begin(&i+1) in this macro so computer will understand for example if i=2 then begin 2 (&i+1) <= end 1 (&i).

Can anyone help me?

Thank you guys very much!

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Yes. Make sure to use either the Insert Code  or Insert SAS Code icons on the menu bar so that your formatting is not loss.

 

Now that you have posted data tell us what you want to calculate from that data.

Do you want to derive new variables on each observation?

Do you want to subset that to observations that meet some criteria?

 

Explain what you want and post the expected result for your sample data.

View solution in original post

17 REPLIES 17
SuryaKiran
Meteorite | Level 14

Did you try using %eval function for evaluating  the sum.

Thanks,
Suryakiran
SuryaKiran
Meteorite | Level 14
/* Try this */
%do i = 1 %to &e; %if end_A > end&i %then %do %until ((end_A > end&i) AND (begin%eval(&i+1) <=end&i)); %let i = %eval(&i+1);/* Why */ %end; %end;

Provide some example data and the result your looking for. What are you trying  to achive?

 

Why do you need %let i=%eval(&i+1);  In do loop it will automatically increment. 

Thanks,
Suryakiran
Poisonous_Snake
Calcite | Level 5
Thank you to concern about my question.
I only want to increment i in the loop do until, for example: when i = 1, if end_A > end1 then do until (end_A > end(i)), at this time, i will increase up to 4 to evaluate whether end_A > end(i), meanwhile the i outside for the if then (end_A > end1) still equal 1.
I try to write begin(%eval(&i+1)) but the computer don't understand, in fact it makes my %end begin a text instead of a command.
Now I really want to know how to know how many loops do we have for each end_A. I try to assign a new variable n, but after %let n = 0 and %let n = %eval(&n+1) in the loop %do %until, I don't know how to express n in the table. Can you help me?
Tom
Super User Tom
Super User

Macro code is for manipulating text and is mainly used to generate code. 

If cannot reference values of dataset variables.

 

Not sure what your task really is, but perhaps one place you could use macro code is if you wanted to generate a series of comparison statements to use in a data step.  For example if you wanted to calculate 4 boolean variables named TEST1 to TEST2 where each one compares a different BEGINxxx variable to the variable END_A then the macro code might look like this.

 

%do i=1 to 4 ;
test&i = begin&i < end_a ;
%end;

So if you did that in the middle of a data step you would have generate four assignment statements to create those four new variables.

 

Astounding
PROC Star

It's possible you've been bitten by the Poisonous Macro Snake.

 

If you truly have a table with the structure you have described, macro language would be of no use.  A DATA step processes data in a table.

Tom
Super User Tom
Super User

Macro code is for generating SAS code. SAS code is used to reference data.

Macro code will not help with this problem.

 

Here is some SAS code that might help you.

array begin (4);
array end (4);
do i=1 to dim(end);
  if end_a > end(i) then
   do j=i+1 to dim(begin) until (end_a > end(i) and begin(j) < end(i)) ;
     * What do you want to do here? ;
  end;
end;
Poisonous_Snake
Calcite | Level 5

Thank you to answer my question.

In fact, I want to know if end_A > end1, whether end_A > end(i) (i=2-4). 

In fact, I have a more variable begin_A, and I want to know whether the period between begin_A and end_A is within a period from begin1 to end 4. If it's in begin1-end1, it's ok, but if end_A > end1 (begin1 < beginA), then I must test begin2-end2, it means end_A <= end2 AND begin2 <=end1. And if end_A > end2, I must continue testing begin3-end3. I will do like this until begin4-end4.

I just think do until will help me to run from 2 to 4, but now I'm thinking how to know if it's true in end2 or end3 (end_A <end2 par example)

Tom
Super User Tom
Super User

Not sure what you are asking exactly.

I would recommend creating a small example dataset and posting it. 

data have ;
  input id begin1-begin4 end1-end4 begin_a end_a ;
  informat begin1-begin4 end1-end4  begin_a end_a yymmdd.;
  format begin1-begin4 end1-end4  begin_a end_a yymmdd10. ;
cards;
1 2017-01-01 . . . 2017-03-01 . . . 2017-02-01 2017-02-14
;

Include an example dataset that shows what you are trying to calculate. If you are just trying to make new variables then include them in the original sample.  

 

Poisonous_Snake
Calcite | Level 5

I created an example below for you (I really hope you can help me. Thank you very much hihi). In fact, I want to know whether B (defined by begin_B and end_B) is used with A (defined by begin_Ai to end_Ai). Is it clearer?

Tom
Super User Tom
Super User

@Poisonous_Snake wrote:

I created an example below for you (I really hope you can help me. Thank you very much hihi). In fact, I want to know whether B (defined by begin_B and end_B) is used with A (defined by begin_Ai to end_Ai). Is it clearer?


 

To post data do it in the form of a data step that reads from in-line records. Like the example I posted above.

Poisonous_Snake
Calcite | Level 5
I'm sorry for misunderstanding you, do you mean that?
data example;
input STT begin_A1 begin_A2 begin_A3 begin_A4 end_A1 end_A2 end_A3 end_A4 begin_B end_B;
informat begin_A1 begin_A2 begin_A3 begin_A4 end_A1 end_A2 end_A3 end_A4 begin_B end_B ddmmyy.;
format begin_A1 begin_A2 begin_A3 begin_A4 end_A1 end_A2 end_A3 end_A4 begin_B end_B ddmmyy10.;
cards;
1 12/06/2014 17/06/2014 25/06/2014 01/07/2014 27/06/2014 02/07/2014 10/07/2014 16/07/2014 17/06/2014 15/07/2014
2 28/05/2014 12/06/2014 17/06/2014 25/06/2014 12/06/2014 27/06/2014 02/07/2014 10/07/2014 12/06/2014 10/07/2014
RUN;
Tom
Super User Tom
Super User

Yes. Make sure to use either the Insert Code  or Insert SAS Code icons on the menu bar so that your formatting is not loss.

 

Now that you have posted data tell us what you want to calculate from that data.

Do you want to derive new variables on each observation?

Do you want to subset that to observations that meet some criteria?

 

Explain what you want and post the expected result for your sample data.

Poisonous_Snake
Calcite | Level 5

I want to know whether B is used with A. For example, the period from begin_A1 to end_A1 contains begin_B -> starting using B when using A. But end_B is out of this period, so I must evaluate the next period, which means begin_A2 to end_A2, but end_B > end_A2, so we continue evaluating begin_A3 - end_A3, meanwhile, begin_A2 < end_A1,  which means A continues being used while using B. I evaluate like that until begin_A4 - end_A4 to know whether end_B > end_A4 (that means finishing A before finishing B) or end_B < end_A4 (that means B is used with A). 

I want to know the final result (end_B > end_A4 or end_B < end_A4), meanwhile the condition begin_A2 <= end_A1, begin_A3 <= end_A2, begin_A4 <= end_A3 is reassured. If this condition is wrong, I don't have to evaluate until end_A4.

 

Tom
Super User Tom
Super User

That is as clear as mud.

You have a series of intervals.  And you want to compare it to a new interval.

 Do you want to only find the interval from the series that complete covers the new interval?

So find the first I such that this criteria is true:

begin(i) <= beginB <= endB <= end(i)

Or do you want to construct a new smallest interval by combining different begin and end date?

Find the max(I) and min(J) with I<=J that meet this criteria:

begin(i) <= beginB <= endB <= end(j)

 

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 17 replies
  • 1086 views
  • 0 likes
  • 4 in conversation