BookmarkSubscribeRSS Feed
ajb
Obsidian | Level 7 ajb
Obsidian | Level 7

Hello All, 

 

I am using SAS 9.4.

I worked with a more SAS savvy person than myself on this code and I need to make a few changes to the do loop. I am having a problem changing the %do loop in blue in the following code. 

 

I want to change the incident variable in %do loop.

Currently, incident = 1 if an event occurs within a specific 365.25 period after visitdate.  

           incident=(%eval(&i-1)*365.25<=(&outcome-visitdate)<&i*365.25); where i=1 to 10

I need to change this to only do  

           incident=(0*365.25<=(&outcome-visitdate)<4*365.25); 

           incident=(4*365.25<=(&outcome-visitdate)<7*365.25); 

           incident=(7*365.25<=(&outcome-visitdate)<10*365.25); 

__________________________________

%let outcome=event;  /*date variable*/

/*transpose data set from wide to long*/

%macro outcome;

  data second;

    set first;

    array fox {*} fox1 fox2 fox3 fox4;

    array rabbit {*} rabbit1 rabbit2 rabbit3 rabbit4;

    array dog {*} dog1 dog2 dog3 dog4;

    array date{*} date1 date2 date3 date4;

    do i=1 to dim(fox);

      visit=i+2;

              foxvar=fox(i);

              rabbitvar=rabbit(i);

              dogvar=dog(i);

              visitdate=date(i);

              if ^(&outcome=.) then output; 

    end;

  run;

 

  %do i=1 %to 10;

/* INCIDENT=0 prior to the event, */

/* 1 at the event, missing otherwise(after event occurred) */

    data second;

              set second;

      by id visit;

      drop switch;

      retain switch;

      if first. id then switch=0;

      if switch=1 then incident=.;

              if ^missing(&outcome) and ^missing(&outcome) and switch=0 then do;

                incident=(%eval(&i-1)*365.25<=(&outcome-visitdate)<&i*365.25);

              end;

      if incident=1 then switch=1;

    run;

  %end;

...

%mend;

%outcome;

There is more to the macro code as it drops the ID in the following period after it has had the event in the current interval. 

________________________________________

 

I have tried without success the following 2 strategies 

 

...

  %do i=1 %to 9;

    data second;

              set second;

...

 when i = 1 do; 

    incident=0*365.25<=(&outcome-visitdate)<4*365.25); 

end;

when i=4 do; 

incident=4*365.25<=(&outcome-visitdate)<7*365.25);

end;

        when i=7 do; 

incident=7*365.25<=(&outcome-visitdate)<9*365.25); 

end;

when i=2 or i=3 or i=5 or i=6 or i=8 or i=9 do incident = 0;

 

and also

...

 %do i={0,4 7};

    %do j={4 7 9};

    data second;

              set second; 

...

incident=(%eval(&i)*365.25<=(&outcome-visitdate)<(&j)*365.25); 

__________

Any help would be appreciated!!

3 REPLIES 3
ChrisNZ
Tourmaline | Level 20

Like this?

 

%do i=1 %to 3;
/* INCIDENT=0 prior to the event, */
/* 1 at the event, missing otherwise(after event occurred) */
    data second;
      set second;
      by id visit;
      drop switch;
      retain switch;
      if first. id then switch=0;
      if switch=1 then incident=.;
      if ^missing(&outcome) and switch=0 then do;
        if &i=1 then incident=(0*365.25<=(&outcome-visitdate)<4*365.25); 
        if &i=2 then incident=(4*365.25<=(&outcome-visitdate)<7*365.25); 
        if &i=3 then incident=(7*365.25<=(&outcome-visitdate)<10*365.25); 
      end;
      if incident=1 then switch=1;
    run;
  %end;

 

Please align your code better. Tabs prevent that. Use spaces.

 

 

 

ajb
Obsidian | Level 7 ajb
Obsidian | Level 7

I tried this and incident only has 1 level (0 and missing). which is odd because there are instances where incident should be 1.

Tom
Super User Tom
Super User

Why are you running the same DATA step inside a macro %DO loop?

What is the purpose?

 

Why do you want to change 

incident=(0*365.25<=(&outcome-visitdate)<1*365.25); 
incident=(1*365.25<=(&outcome-visitdate)<2*365.25); 
incident=(2*365.25<=(&outcome-visitdate)<3*365.25); 

to

incident=(0*365.25<=(&outcome-visitdate)<4*365.25); 
incident=(4*365.25<=(&outcome-visitdate)<7*365.25); 
incident=(7*365.25<=(&outcome-visitdate)<10*365.25); 

Why is the first interval 4 years and the others only 3? Shouldn't that be:

incident=(0*365.25<=(&outcome-visitdate)<3*365.25); 
incident=(3*365.25<=(&outcome-visitdate)<6*365.25); 
incident=(6*365.25<=(&outcome-visitdate)<9*365.25); 

If so then use:

incident=(3*(&i-1)*365.25<=(&outcome-visitdate)<3*&i*365.25); 

 

To implement arbitrary boundaries you could just use a list of the cut points.  Just pull the boundaries for the current iteration.

%let cuts=0 4 7 10;
%do i=1 %to %sysfunc(countw(&cuts))-1;
....
incident=(3*%scan(&cuts,&i-1)*365.25<=(&outcome-visitdate)<3*%scan(&cuts,&i)*365.25); 
....
%end;

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 3 replies
  • 532 views
  • 0 likes
  • 3 in conversation